save_metrics: config.save_metrics.clone(),
test_shard: config.test_shard.clone(),
nocapture: false,
+ color: test::AutoColor,
}
}
use std::os;
use std::str;
use std::io::process::{ProcessExit, Command, Process, ProcessOutput};
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
fn target_env(lib_path: &str, prog: &str) -> Vec<(String, String)> {
let prog = if cfg!(windows) {prog.slice_to(prog.len() - 4)} else {prog};
use core::prelude::*;
use core::cmp;
+use core::default::Default;
use core::fmt;
use core::iter::{Enumerate, Repeat, Map, Zip};
use core::ops;
bitv: BigBitv
}
+impl Default for BitvSet {
+ #[inline]
+ fn default() -> BitvSet { BitvSet::new() }
+}
+
impl BitvSet {
/// Creates a new bit vector set with initially no contents
pub fn new() -> BitvSet {
use core::prelude::*;
use alloc::owned::Box;
+use core::default::Default;
use core::fmt;
use core::iter;
use core::mem;
}
}
+impl<T> Default for DList<T> {
+ #[inline]
+ fn default() -> DList<T> { DList::new() }
+}
+
impl<T> DList<T> {
/// Create an empty DList
#[inline]
use core::prelude::*;
+use core::default::Default;
use core::mem::{zeroed, replace, swap};
use core::ptr;
fn clear(&mut self) { self.data.truncate(0) }
}
+impl<T: Ord> Default for PriorityQueue<T> {
+ #[inline]
+ fn default() -> PriorityQueue<T> { PriorityQueue::new() }
+}
+
impl<T: Ord> PriorityQueue<T> {
/// An iterator visiting all values in underlying vector, in
/// arbitrary order.
use core::prelude::*;
use core::cmp;
+use core::default::Default;
use core::fmt;
use core::iter::RandomAccessIterator;
}
}
+impl<T> Default for RingBuf<T> {
+ #[inline]
+ fn default() -> RingBuf<T> { RingBuf::new() }
+}
+
impl<T> RingBuf<T> {
/// Create an empty RingBuf
pub fn new() -> RingBuf<T> {
use core::prelude::*;
+use core::default::Default;
use core::fmt;
use core::iter::{Enumerate, FilterMap};
use core::mem::replace;
}
}
+impl<V> Default for SmallIntMap<V> {
+ #[inline]
+ fn default() -> SmallIntMap<V> { SmallIntMap::new() }
+}
+
impl<V> SmallIntMap<V> {
/// Create an empty SmallIntMap
pub fn new() -> SmallIntMap<V> { SmallIntMap{v: vec!()} }
use core::prelude::*;
use alloc::owned::Box;
+use core::default::Default;
use core::fmt;
use core::fmt::Show;
use core::iter::Peekable;
}
}
+impl<K: Ord, V> Default for TreeMap<K,V> {
+ #[inline]
+ fn default() -> TreeMap<K, V> { TreeMap::new() }
+}
+
impl<K: Ord, V> TreeMap<K, V> {
/// Create an empty TreeMap
pub fn new() -> TreeMap<K, V> { TreeMap{root: None, length: 0} }
fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
}
+impl<T: Ord> Default for TreeSet<T> {
+ #[inline]
+ fn default() -> TreeSet<T> { TreeSet::new() }
+}
+
impl<T: Ord> TreeSet<T> {
/// Create an empty TreeSet
#[inline]
use core::prelude::*;
use alloc::owned::Box;
+use core::default::Default;
use core::mem::zeroed;
use core::mem;
use core::uint;
}
}
+impl<T> Default for TrieMap<T> {
+ #[inline]
+ fn default() -> TrieMap<T> { TrieMap::new() }
+}
+
impl<T> TrieMap<T> {
/// Create an empty TrieMap
#[inline]
}
}
+impl Default for TrieSet {
+ #[inline]
+ fn default() -> TrieSet { TrieSet::new() }
+}
+
impl TrieSet {
/// Create an empty TrieSet
#[inline]
pub mod compat {
use std::intrinsics::{atomic_store_relaxed, transmute};
use libc::types::os::arch::extra::{LPCWSTR, HMODULE, LPCSTR, LPVOID};
- use std::os::win32::as_utf16_p;
extern "system" {
fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
// This way, calling a function in this compatibility layer (after it's loaded) shouldn't
// be any slower than a regular DLL call.
unsafe fn store_func<T: Copy>(ptr: *mut T, module: &str, symbol: &str, fallback: T) {
- as_utf16_p(module, |module| {
- symbol.with_c_str(|symbol| {
- let handle = GetModuleHandleW(module);
- let func: Option<T> = transmute(GetProcAddress(handle, symbol));
- atomic_store_relaxed(ptr, func.unwrap_or(fallback))
- })
+ let module = module.to_utf16().append_one(0);
+ symbol.with_c_str(|symbol| {
+ let handle = GetModuleHandleW(module.as_ptr());
+ let func: Option<T> = transmute(GetProcAddress(handle, symbol));
+ atomic_store_relaxed(ptr, func.unwrap_or(fallback))
})
}
use libc;
use std::c_str::CString;
use std::mem;
-use std::os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
+use std::os::win32::fill_utf16_buf_and_decode;
use std::ptr;
use std::rt::rtio;
-use std::rt::rtio::IoResult;
+use std::rt::rtio::{IoResult, IoError};
use std::str;
use std::vec;
}
}
+pub fn to_utf16(s: &CString) -> IoResult<Vec<u16>> {
+ match s.as_str() {
+ Some(s) => Ok(s.to_utf16().append_one(0)),
+ None => Err(IoError {
+ code: libc::ERROR_INVALID_NAME as uint,
+ extra: 0,
+ detail: Some("valid unicode input required".to_str()),
+ })
+ }
+}
+
pub fn open(path: &CString, fm: rtio::FileMode, fa: rtio::FileAccess)
-> IoResult<FileDesc> {
// Flags passed to open_osfhandle
// Compat with unix, this allows opening directories (see libuv)
dwFlagsAndAttributes |= libc::FILE_FLAG_BACKUP_SEMANTICS;
- let handle = as_utf16_p(path.as_str().unwrap(), |buf| unsafe {
- libc::CreateFileW(buf,
+ let path = try!(to_utf16(path));
+ let handle = unsafe {
+ libc::CreateFileW(path.as_ptr(),
dwDesiredAccess,
dwShareMode,
ptr::mut_null(),
dwCreationDisposition,
dwFlagsAndAttributes,
ptr::mut_null())
- });
+ };
if handle == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
Err(super::last_error())
} else {
}
pub fn mkdir(p: &CString, _mode: uint) -> IoResult<()> {
+ let p = try!(to_utf16(p));
super::mkerr_winbool(unsafe {
// FIXME: turn mode into something useful? #2623
- as_utf16_p(p.as_str().unwrap(), |buf| {
- libc::CreateDirectoryW(buf, ptr::mut_null())
- })
+ libc::CreateDirectoryW(p.as_ptr(), ptr::mut_null())
})
}
let star = Path::new(unsafe {
CString::new(p.with_ref(|p| p), false)
}).join("*");
- as_utf16_p(star.as_str().unwrap(), |path_ptr| unsafe {
+ let path = try!(to_utf16(&star.to_c_str()));
+
+ unsafe {
let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
- let find_handle = libc::FindFirstFileW(path_ptr, wfd_ptr as libc::HANDLE);
+ let find_handle = libc::FindFirstFileW(path.as_ptr(), wfd_ptr as libc::HANDLE);
if find_handle as libc::c_int != libc::INVALID_HANDLE_VALUE {
let mut paths = vec!();
let mut more_files = 1 as libc::c_int;
} else {
Err(super::last_error())
}
- })
+ }
}
pub fn unlink(p: &CString) -> IoResult<()> {
+ let p = try!(to_utf16(p));
super::mkerr_winbool(unsafe {
- as_utf16_p(p.as_str().unwrap(), |buf| {
- libc::DeleteFileW(buf)
- })
+ libc::DeleteFileW(p.as_ptr())
})
}
pub fn rename(old: &CString, new: &CString) -> IoResult<()> {
+ let old = try!(to_utf16(old));
+ let new = try!(to_utf16(new));
super::mkerr_winbool(unsafe {
- as_utf16_p(old.as_str().unwrap(), |old| {
- as_utf16_p(new.as_str().unwrap(), |new| {
- libc::MoveFileExW(old, new, libc::MOVEFILE_REPLACE_EXISTING)
- })
- })
+ libc::MoveFileExW(old.as_ptr(), new.as_ptr(),
+ libc::MOVEFILE_REPLACE_EXISTING)
})
}
pub fn chmod(p: &CString, mode: uint) -> IoResult<()> {
- super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
- libc::wchmod(p, mode as libc::c_int)
- }))
+ let p = try!(to_utf16(p));
+ super::mkerr_libc(unsafe {
+ libc::wchmod(p.as_ptr(), mode as libc::c_int)
+ })
}
pub fn rmdir(p: &CString) -> IoResult<()> {
- super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
- libc::wrmdir(p)
- }))
+ let p = try!(to_utf16(p));
+ super::mkerr_libc(unsafe { libc::wrmdir(p.as_ptr()) })
}
pub fn chown(_p: &CString, _uid: int, _gid: int) -> IoResult<()> {
pub fn readlink(p: &CString) -> IoResult<CString> {
// FIXME: I have a feeling that this reads intermediate symlinks as well.
use io::c::compat::kernel32::GetFinalPathNameByHandleW;
+ let p = try!(to_utf16(p));
let handle = unsafe {
- as_utf16_p(p.as_str().unwrap(), |p| {
- libc::CreateFileW(p,
- libc::GENERIC_READ,
- libc::FILE_SHARE_READ,
- ptr::mut_null(),
- libc::OPEN_EXISTING,
- libc::FILE_ATTRIBUTE_NORMAL,
- ptr::mut_null())
- })
+ libc::CreateFileW(p.as_ptr(),
+ libc::GENERIC_READ,
+ libc::FILE_SHARE_READ,
+ ptr::mut_null(),
+ libc::OPEN_EXISTING,
+ libc::FILE_ATTRIBUTE_NORMAL,
+ ptr::mut_null())
};
if handle as int == libc::INVALID_HANDLE_VALUE as int {
return Err(super::last_error())
pub fn symlink(src: &CString, dst: &CString) -> IoResult<()> {
use io::c::compat::kernel32::CreateSymbolicLinkW;
- super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| {
- as_utf16_p(dst.as_str().unwrap(), |dst| {
- unsafe { CreateSymbolicLinkW(dst, src, 0) }
- }) as libc::BOOL
- }))
+ let src = try!(to_utf16(src));
+ let dst = try!(to_utf16(dst));
+ super::mkerr_winbool(unsafe {
+ CreateSymbolicLinkW(dst.as_ptr(), src.as_ptr(), 0) as libc::BOOL
+ })
}
pub fn link(src: &CString, dst: &CString) -> IoResult<()> {
- super::mkerr_winbool(as_utf16_p(src.as_str().unwrap(), |src| {
- as_utf16_p(dst.as_str().unwrap(), |dst| {
- unsafe { libc::CreateHardLinkW(dst, src, ptr::mut_null()) }
- })
- }))
+ let src = try!(to_utf16(src));
+ let dst = try!(to_utf16(dst));
+ super::mkerr_winbool(unsafe {
+ libc::CreateHardLinkW(dst.as_ptr(), src.as_ptr(), ptr::mut_null())
+ })
}
fn mkstat(stat: &libc::stat) -> rtio::FileStat {
pub fn stat(p: &CString) -> IoResult<rtio::FileStat> {
let mut stat: libc::stat = unsafe { mem::zeroed() };
- as_utf16_p(p.as_str().unwrap(), |up| {
- match unsafe { libc::wstat(up, &mut stat) } {
- 0 => Ok(mkstat(&stat)),
- _ => Err(super::last_error()),
- }
- })
+ let p = try!(to_utf16(p));
+ match unsafe { libc::wstat(p.as_ptr(), &mut stat) } {
+ 0 => Ok(mkstat(&stat)),
+ _ => Err(super::last_error()),
+ }
}
pub fn lstat(_p: &CString) -> IoResult<rtio::FileStat> {
actime: (atime / 1000) as libc::time64_t,
modtime: (mtime / 1000) as libc::time64_t,
};
- super::mkerr_libc(as_utf16_p(p.as_str().unwrap(), |p| unsafe {
- libc::wutime(p, &buf)
- }))
+ let p = try!(to_utf16(p));
+ super::mkerr_libc(unsafe {
+ libc::wutime(p.as_ptr(), &buf)
+ })
}
IoError {
code: ERROR as uint,
extra: 0,
- detail: None,
+ detail: Some("not yet supported by the `native` runtime, maybe try `green`.".to_string()),
}
}
use libc;
use std::c_str::CString;
use std::mem;
-use std::os::win32::as_utf16_p;
use std::os;
use std::ptr;
use std::rt::rtio;
use super::c;
use super::util;
+use super::file::to_utf16;
struct Event(libc::HANDLE);
}
pub fn connect(addr: &CString, timeout: Option<u64>) -> IoResult<UnixStream> {
- as_utf16_p(addr.as_str().unwrap(), |p| {
- let start = ::io::timer::now();
- loop {
- match UnixStream::try_connect(p) {
- Some(handle) => {
- let inner = Inner::new(handle);
- let mut mode = libc::PIPE_TYPE_BYTE |
- libc::PIPE_READMODE_BYTE |
- libc::PIPE_WAIT;
- let ret = unsafe {
- libc::SetNamedPipeHandleState(inner.handle,
- &mut mode,
- ptr::mut_null(),
- ptr::mut_null())
- };
- return if ret == 0 {
- Err(super::last_error())
- } else {
- Ok(UnixStream {
- inner: Arc::new(inner),
- read: None,
- write: None,
- read_deadline: 0,
- write_deadline: 0,
- })
- }
+ let addr = try!(to_utf16(addr));
+ let start = ::io::timer::now();
+ loop {
+ match UnixStream::try_connect(addr.as_ptr()) {
+ Some(handle) => {
+ let inner = Inner::new(handle);
+ let mut mode = libc::PIPE_TYPE_BYTE |
+ libc::PIPE_READMODE_BYTE |
+ libc::PIPE_WAIT;
+ let ret = unsafe {
+ libc::SetNamedPipeHandleState(inner.handle,
+ &mut mode,
+ ptr::mut_null(),
+ ptr::mut_null())
+ };
+ return if ret == 0 {
+ Err(super::last_error())
+ } else {
+ Ok(UnixStream {
+ inner: Arc::new(inner),
+ read: None,
+ write: None,
+ read_deadline: 0,
+ write_deadline: 0,
+ })
}
- None => {}
}
+ None => {}
+ }
- // On windows, if you fail to connect, you may need to call the
- // `WaitNamedPipe` function, and this is indicated with an error
- // code of ERROR_PIPE_BUSY.
- let code = unsafe { libc::GetLastError() };
- if code as int != libc::ERROR_PIPE_BUSY as int {
- return Err(super::last_error())
- }
+ // On windows, if you fail to connect, you may need to call the
+ // `WaitNamedPipe` function, and this is indicated with an error
+ // code of ERROR_PIPE_BUSY.
+ let code = unsafe { libc::GetLastError() };
+ if code as int != libc::ERROR_PIPE_BUSY as int {
+ return Err(super::last_error())
+ }
- match timeout {
- Some(timeout) => {
- let now = ::io::timer::now();
- let timed_out = (now - start) >= timeout || unsafe {
- let ms = (timeout - (now - start)) as libc::DWORD;
- libc::WaitNamedPipeW(p, ms) == 0
- };
- if timed_out {
- return Err(util::timeout("connect timed out"))
- }
+ match timeout {
+ Some(timeout) => {
+ let now = ::io::timer::now();
+ let timed_out = (now - start) >= timeout || unsafe {
+ let ms = (timeout - (now - start)) as libc::DWORD;
+ libc::WaitNamedPipeW(addr.as_ptr(), ms) == 0
+ };
+ if timed_out {
+ return Err(util::timeout("connect timed out"))
}
+ }
- // An example I found on microsoft's website used 20
- // seconds, libuv uses 30 seconds, hence we make the
- // obvious choice of waiting for 25 seconds.
- None => {
- if unsafe { libc::WaitNamedPipeW(p, 25000) } == 0 {
- return Err(super::last_error())
- }
+ // An example I found on microsoft's website used 20
+ // seconds, libuv uses 30 seconds, hence we make the
+ // obvious choice of waiting for 25 seconds.
+ None => {
+ if unsafe { libc::WaitNamedPipeW(addr.as_ptr(), 25000) } == 0 {
+ return Err(super::last_error())
}
}
}
- })
+ }
}
fn handle(&self) -> libc::HANDLE { self.inner.handle }
// Although we technically don't need the pipe until much later, we
// create the initial handle up front to test the validity of the name
// and such.
- as_utf16_p(addr.as_str().unwrap(), |p| {
- let ret = unsafe { pipe(p, true) };
- if ret == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
- Err(super::last_error())
- } else {
- Ok(UnixListener { handle: ret, name: addr.clone() })
- }
- })
+ let addr_v = try!(to_utf16(addr));
+ let ret = unsafe { pipe(addr_v.as_ptr(), true) };
+ if ret == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
+ Err(super::last_error())
+ } else {
+ Ok(UnixListener { handle: ret, name: addr.clone() })
+ }
}
pub fn native_listen(self) -> IoResult<UnixAcceptor> {
// using the original server pipe.
let handle = self.listener.handle;
+ let name = try!(to_utf16(&self.listener.name));
+
// Once we've got a "server handle", we need to wait for a client to
// connect. The ConnectNamedPipe function will block this thread until
// someone on the other end connects. This function can "fail" if a
// Now that we've got a connected client to our handle, we need to
// create a second server pipe. If this fails, we disconnect the
// connected client and return an error (see comments above).
- let new_handle = as_utf16_p(self.listener.name.as_str().unwrap(), |p| {
- unsafe { pipe(p, false) }
- });
+ let new_handle = unsafe { pipe(name.as_ptr(), false) };
if new_handle == libc::INVALID_HANDLE_VALUE as libc::HANDLE {
let ret = Err(super::last_error());
// If our disconnection fails, then there's not really a whole lot
lpSecurityDescriptor: ptr::mut_null(),
bInheritHandle: 1,
};
- *slot = os::win32::as_utf16_p("NUL", |filename| {
- libc::CreateFileW(filename,
- access,
- libc::FILE_SHARE_READ |
- libc::FILE_SHARE_WRITE,
- &mut sa,
- libc::OPEN_EXISTING,
- 0,
- ptr::mut_null())
- });
+ let filename = "NUL".to_utf16().append_one(0);
+ *slot = libc::CreateFileW(filename.as_ptr(),
+ access,
+ libc::FILE_SHARE_READ |
+ libc::FILE_SHARE_WRITE,
+ &mut sa,
+ libc::OPEN_EXISTING,
+ 0,
+ ptr::mut_null());
if *slot == INVALID_HANDLE_VALUE as libc::HANDLE {
return Err(super::last_error())
}
with_envp(cfg.env, |envp| {
with_dirp(cfg.cwd, |dirp| {
- os::win32::as_mut_utf16_p(cmd_str.as_slice(), |cmdp| {
- let created = CreateProcessW(ptr::null(),
- cmdp,
- ptr::mut_null(),
- ptr::mut_null(),
- TRUE,
- flags, envp, dirp,
- &mut si, &mut pi);
- if created == FALSE {
- create_err = Some(super::last_error());
- }
- })
+ let mut cmd_str = cmd_str.to_utf16().append_one(0);
+ let created = CreateProcessW(ptr::null(),
+ cmd_str.as_mut_ptr(),
+ ptr::mut_null(),
+ ptr::mut_null(),
+ TRUE,
+ flags, envp, dirp,
+ &mut si, &mut pi);
+ if created == FALSE {
+ create_err = Some(super::last_error());
+ }
})
});
Some(dir) => {
let dir_str = dir.as_str()
.expect("expected workingdirectory to be utf-8 encoded");
- os::win32::as_utf16_p(dir_str, cb)
+ let dir_str = dir_str.to_utf16().append_one(0);
+ cb(dir_str.as_ptr())
},
None => cb(ptr::null())
}
*/
use Integer;
+use rand::Rng;
-use std::cmp;
+use std::{cmp, fmt};
use std::default::Default;
-use std::fmt;
use std::from_str::FromStr;
use std::num::CheckedDiv;
use std::num::{Bitwise, ToPrimitive, FromPrimitive};
use std::num::{Zero, One, ToStrRadix, FromStrRadix};
-use rand::Rng;
use std::string::String;
-use std::uint;
-use std::{i64, u64};
+use std::{uint, i64, u64};
/**
A `BigDigit` is a `BigUint`'s composing element.
impl PartialOrd for BigUint {
#[inline]
fn lt(&self, other: &BigUint) -> bool {
- match self.cmp(other) { Less => true, _ => false}
+ self.cmp(other) == Less
}
}
impl Default for BigUint {
#[inline]
- fn default() -> BigUint { BigUint::new(Vec::new()) }
+ fn default() -> BigUint { Zero::zero() }
}
impl fmt::Show for BigUint {
impl ToStrRadix for BigUint {
fn to_str_radix(&self, radix: uint) -> String {
- assert!(1 < radix && radix <= 16);
+ assert!(1 < radix && radix <= 16, "The radix must be within (1, 16]");
let (base, max_len) = get_radix_base(radix);
if base == BigDigit::base {
return fill_concat(self.data.as_slice(), radix, max_len)
impl FromStrRadix for BigUint {
/// Creates and initializes a `BigUint`.
#[inline]
- fn from_str_radix(s: &str, radix: uint)
- -> Option<BigUint> {
+ fn from_str_radix(s: &str, radix: uint) -> Option<BigUint> {
BigUint::parse_bytes(s.as_bytes(), radix)
}
}
///
/// The digits are be in base 2^32.
#[inline]
- pub fn new(v: Vec<BigDigit>) -> BigUint {
+ pub fn new(mut digits: Vec<BigDigit>) -> BigUint {
// omit trailing zeros
- let new_len = v.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1);
-
- if new_len == v.len() { return BigUint { data: v }; }
- let mut v = v;
- v.truncate(new_len);
- return BigUint { data: v };
+ let new_len = digits.iter().rposition(|n| *n != 0).map_or(0, |p| p + 1);
+ digits.truncate(new_len);
+ BigUint { data: digits }
}
/// Creates and initializes a `BigUint`.
/// The digits are be in base 2^32.
#[inline]
pub fn from_slice(slice: &[BigDigit]) -> BigUint {
- return BigUint::new(Vec::from_slice(slice));
+ BigUint::new(Vec::from_slice(slice))
}
/// Creates and initializes a `BigUint`.
// `DoubleBigDigit` size dependent
#[inline]
fn get_radix_base(radix: uint) -> (DoubleBigDigit, uint) {
- assert!(1 < radix && radix <= 16);
match radix {
2 => (4294967296, 32),
3 => (3486784401, 20),
14 => (1475789056, 8),
15 => (2562890625, 8),
16 => (4294967296, 8),
- _ => fail!()
+ _ => fail!("The radix must be within (1, 16]")
}
}
impl PartialEq for BigInt {
#[inline]
fn eq(&self, other: &BigInt) -> bool {
- match self.cmp(other) { Equal => true, _ => false }
+ self.cmp(other) == Equal
}
}
impl PartialOrd for BigInt {
#[inline]
fn lt(&self, other: &BigInt) -> bool {
- match self.cmp(other) { Less => true, _ => false}
+ self.cmp(other) == Less
}
}
impl Default for BigInt {
#[inline]
- fn default() -> BigInt { BigInt::new(Zero, Vec::new()) }
+ fn default() -> BigInt { Zero::zero() }
}
impl fmt::Show for BigInt {
match (self.sign, other.sign) {
(Zero, _) => other.clone(),
(_, Zero) => self.clone(),
- (Plus, Plus) => BigInt::from_biguint(Plus,
- self.data + other.data),
+ (Plus, Plus) => BigInt::from_biguint(Plus, self.data + other.data),
(Plus, Minus) => self - (-*other),
(Minus, Plus) => other - (-*self),
(Minus, Minus) => -((-self) + (-*other))
#[inline]
fn div(&self, other: &BigInt) -> BigInt {
let (q, _) = self.div_rem(other);
- return q;
+ q
}
}
#[inline]
fn rem(&self, other: &BigInt) -> BigInt {
let (_, r) = self.div_rem(other);
- return r;
+ r
}
}
#[inline]
fn div_floor(&self, other: &BigInt) -> BigInt {
let (d, _) = self.div_mod_floor(other);
- return d;
+ d
}
#[inline]
fn mod_floor(&self, other: &BigInt) -> BigInt {
let (_, m) = self.div_mod_floor(other);
- return m;
+ m
}
fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) {
let final_digit: BigDigit = self.gen();
data.push(final_digit >> (BigDigit::bits - rem));
}
- return BigUint::new(data);
+ BigUint::new(data)
}
fn gen_bigint(&mut self, bit_size: uint) -> BigInt {
} else {
Minus
};
- return BigInt::from_biguint(sign, biguint);
+ BigInt::from_biguint(sign, biguint)
}
fn gen_biguint_below(&mut self, bound: &BigUint) -> BigUint {
///
/// The digits are be in base 2^32.
#[inline]
- pub fn new(sign: Sign, v: Vec<BigDigit>) -> BigInt {
- BigInt::from_biguint(sign, BigUint::new(v))
+ pub fn new(sign: Sign, digits: Vec<BigDigit>) -> BigInt {
+ BigInt::from_biguint(sign, BigUint::new(digits))
}
/// Creates and initializes a `BigInt`.
if sign == Zero || data.is_zero() {
return BigInt { sign: Zero, data: Zero::zero() };
}
- return BigInt { sign: sign, data: data };
+ BigInt { sign: sign, data: data }
}
/// Creates and initializes a `BigInt`.
}
/// Creates and initializes a `BigInt`.
- pub fn parse_bytes(buf: &[u8], radix: uint)
- -> Option<BigInt> {
+ pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<BigInt> {
if buf.is_empty() { return None; }
let mut sign = Plus;
let mut start = 0;
--- /dev/null
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Integer trait and functions
+
+pub trait Integer: Num + PartialOrd
+ + Div<Self, Self>
+ + Rem<Self, Self> {
+ /// Simultaneous truncated integer division and modulus
+ #[inline]
+ fn div_rem(&self, other: &Self) -> (Self, Self) {
+ (*self / *other, *self % *other)
+ }
+
+ /// Floored integer division
+ ///
+ /// # Examples
+ ///
+ /// ~~~
+ /// # use num::Integer;
+ /// assert!(( 8i).div_floor(& 3) == 2);
+ /// assert!(( 8i).div_floor(&-3) == -3);
+ /// assert!((-8i).div_floor(& 3) == -3);
+ /// assert!((-8i).div_floor(&-3) == 2);
+ ///
+ /// assert!(( 1i).div_floor(& 2) == 0);
+ /// assert!(( 1i).div_floor(&-2) == -1);
+ /// assert!((-1i).div_floor(& 2) == -1);
+ /// assert!((-1i).div_floor(&-2) == 0);
+ /// ~~~
+ fn div_floor(&self, other: &Self) -> Self;
+
+ /// Floored integer modulo, satisfying:
+ ///
+ /// ~~~
+ /// # use num::Integer;
+ /// # let n = 1i; let d = 1i;
+ /// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n)
+ /// ~~~
+ ///
+ /// # Examples
+ ///
+ /// ~~~
+ /// # use num::Integer;
+ /// assert!(( 8i).mod_floor(& 3) == 2);
+ /// assert!(( 8i).mod_floor(&-3) == -1);
+ /// assert!((-8i).mod_floor(& 3) == 1);
+ /// assert!((-8i).mod_floor(&-3) == -2);
+ ///
+ /// assert!(( 1i).mod_floor(& 2) == 1);
+ /// assert!(( 1i).mod_floor(&-2) == -1);
+ /// assert!((-1i).mod_floor(& 2) == 1);
+ /// assert!((-1i).mod_floor(&-2) == -1);
+ /// ~~~
+ fn mod_floor(&self, other: &Self) -> Self;
+
+ /// Simultaneous floored integer division and modulus
+ fn div_mod_floor(&self, other: &Self) -> (Self, Self) {
+ (self.div_floor(other), self.mod_floor(other))
+ }
+
+ /// Greatest Common Divisor (GCD)
+ fn gcd(&self, other: &Self) -> Self;
+
+ /// Lowest Common Multiple (LCM)
+ fn lcm(&self, other: &Self) -> Self;
+
+ /// Returns `true` if `other` divides evenly into `self`
+ fn divides(&self, other: &Self) -> bool;
+
+ /// Returns `true` if the number is even
+ fn is_even(&self) -> bool;
+
+ /// Returns `true` if the number is odd
+ fn is_odd(&self) -> bool;
+}
+
+/// Simultaneous integer division and modulus
+#[inline] pub fn div_rem<T: Integer>(x: T, y: T) -> (T, T) { x.div_rem(&y) }
+/// Floored integer division
+#[inline] pub fn div_floor<T: Integer>(x: T, y: T) -> T { x.div_floor(&y) }
+/// Floored integer modulus
+#[inline] pub fn mod_floor<T: Integer>(x: T, y: T) -> T { x.mod_floor(&y) }
+/// Simultaneous floored integer division and modulus
+#[inline] pub fn div_mod_floor<T: Integer>(x: T, y: T) -> (T, T) { x.div_mod_floor(&y) }
+
+/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The
+/// result is always positive.
+#[inline(always)] pub fn gcd<T: Integer>(x: T, y: T) -> T { x.gcd(&y) }
+/// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
+#[inline(always)] pub fn lcm<T: Integer>(x: T, y: T) -> T { x.lcm(&y) }
+
+macro_rules! impl_integer_for_int {
+ ($T:ty, $test_mod:ident) => (
+ impl Integer for $T {
+ /// Floored integer division
+ #[inline]
+ fn div_floor(&self, other: &$T) -> $T {
+ // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+ // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+ match self.div_rem(other) {
+ (d, r) if (r > 0 && *other < 0)
+ || (r < 0 && *other > 0) => d - 1,
+ (d, _) => d,
+ }
+ }
+
+ /// Floored integer modulo
+ #[inline]
+ fn mod_floor(&self, other: &$T) -> $T {
+ // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+ // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+ match *self % *other {
+ r if (r > 0 && *other < 0)
+ || (r < 0 && *other > 0) => r + *other,
+ r => r,
+ }
+ }
+
+ /// Calculates `div_floor` and `mod_floor` simultaneously
+ #[inline]
+ fn div_mod_floor(&self, other: &$T) -> ($T,$T) {
+ // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+ // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+ match self.div_rem(other) {
+ (d, r) if (r > 0 && *other < 0)
+ || (r < 0 && *other > 0) => (d - 1, r + *other),
+ (d, r) => (d, r),
+ }
+ }
+
+ /// Calculates the Greatest Common Divisor (GCD) of the number and
+ /// `other`. The result is always positive.
+ #[inline]
+ fn gcd(&self, other: &$T) -> $T {
+ // Use Euclid's algorithm
+ let mut m = *self;
+ let mut n = *other;
+ while m != 0 {
+ let temp = m;
+ m = n % temp;
+ n = temp;
+ }
+ n.abs()
+ }
+
+ /// Calculates the Lowest Common Multiple (LCM) of the number and
+ /// `other`.
+ #[inline]
+ fn lcm(&self, other: &$T) -> $T {
+ // should not have to recalculate abs
+ ((*self * *other) / self.gcd(other)).abs()
+ }
+
+ /// Returns `true` if the number can be divided by `other` without
+ /// leaving a remainder
+ #[inline]
+ fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
+
+ /// Returns `true` if the number is divisible by `2`
+ #[inline]
+ fn is_even(&self) -> bool { self & 1 == 0 }
+
+ /// Returns `true` if the number is not divisible by `2`
+ #[inline]
+ fn is_odd(&self) -> bool { !self.is_even() }
+ }
+
+ #[cfg(test)]
+ mod $test_mod {
+ use Integer;
+
+ /// Checks that the division rule holds for:
+ ///
+ /// - `n`: numerator (dividend)
+ /// - `d`: denominator (divisor)
+ /// - `qr`: quotient and remainder
+ #[cfg(test)]
+ fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) {
+ assert_eq!(d * q + r, n);
+ }
+
+ #[test]
+ fn test_div_rem() {
+ fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) {
+ let (n,d) = nd;
+ let separate_div_rem = (n / d, n % d);
+ let combined_div_rem = n.div_rem(&d);
+
+ assert_eq!(separate_div_rem, qr);
+ assert_eq!(combined_div_rem, qr);
+
+ test_division_rule(nd, separate_div_rem);
+ test_division_rule(nd, combined_div_rem);
+ }
+
+ test_nd_dr(( 8, 3), ( 2, 2));
+ test_nd_dr(( 8, -3), (-2, 2));
+ test_nd_dr((-8, 3), (-2, -2));
+ test_nd_dr((-8, -3), ( 2, -2));
+
+ test_nd_dr(( 1, 2), ( 0, 1));
+ test_nd_dr(( 1, -2), ( 0, 1));
+ test_nd_dr((-1, 2), ( 0, -1));
+ test_nd_dr((-1, -2), ( 0, -1));
+ }
+
+ #[test]
+ fn test_div_mod_floor() {
+ fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) {
+ let (n,d) = nd;
+ let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
+ let combined_div_mod_floor = n.div_mod_floor(&d);
+
+ assert_eq!(separate_div_mod_floor, dm);
+ assert_eq!(combined_div_mod_floor, dm);
+
+ test_division_rule(nd, separate_div_mod_floor);
+ test_division_rule(nd, combined_div_mod_floor);
+ }
+
+ test_nd_dm(( 8, 3), ( 2, 2));
+ test_nd_dm(( 8, -3), (-3, -1));
+ test_nd_dm((-8, 3), (-3, 1));
+ test_nd_dm((-8, -3), ( 2, -2));
+
+ test_nd_dm(( 1, 2), ( 0, 1));
+ test_nd_dm(( 1, -2), (-1, -1));
+ test_nd_dm((-1, 2), (-1, 1));
+ test_nd_dm((-1, -2), ( 0, -1));
+ }
+
+ #[test]
+ fn test_gcd() {
+ assert_eq!((10 as $T).gcd(&2), 2 as $T);
+ assert_eq!((10 as $T).gcd(&3), 1 as $T);
+ assert_eq!((0 as $T).gcd(&3), 3 as $T);
+ assert_eq!((3 as $T).gcd(&3), 3 as $T);
+ assert_eq!((56 as $T).gcd(&42), 14 as $T);
+ assert_eq!((3 as $T).gcd(&-3), 3 as $T);
+ assert_eq!((-6 as $T).gcd(&3), 3 as $T);
+ assert_eq!((-4 as $T).gcd(&-2), 2 as $T);
+ }
+
+ #[test]
+ fn test_lcm() {
+ assert_eq!((1 as $T).lcm(&0), 0 as $T);
+ assert_eq!((0 as $T).lcm(&1), 0 as $T);
+ assert_eq!((1 as $T).lcm(&1), 1 as $T);
+ assert_eq!((-1 as $T).lcm(&1), 1 as $T);
+ assert_eq!((1 as $T).lcm(&-1), 1 as $T);
+ assert_eq!((-1 as $T).lcm(&-1), 1 as $T);
+ assert_eq!((8 as $T).lcm(&9), 72 as $T);
+ assert_eq!((11 as $T).lcm(&5), 55 as $T);
+ }
+
+ #[test]
+ fn test_even() {
+ assert_eq!((-4 as $T).is_even(), true);
+ assert_eq!((-3 as $T).is_even(), false);
+ assert_eq!((-2 as $T).is_even(), true);
+ assert_eq!((-1 as $T).is_even(), false);
+ assert_eq!((0 as $T).is_even(), true);
+ assert_eq!((1 as $T).is_even(), false);
+ assert_eq!((2 as $T).is_even(), true);
+ assert_eq!((3 as $T).is_even(), false);
+ assert_eq!((4 as $T).is_even(), true);
+ }
+
+ #[test]
+ fn test_odd() {
+ assert_eq!((-4 as $T).is_odd(), false);
+ assert_eq!((-3 as $T).is_odd(), true);
+ assert_eq!((-2 as $T).is_odd(), false);
+ assert_eq!((-1 as $T).is_odd(), true);
+ assert_eq!((0 as $T).is_odd(), false);
+ assert_eq!((1 as $T).is_odd(), true);
+ assert_eq!((2 as $T).is_odd(), false);
+ assert_eq!((3 as $T).is_odd(), true);
+ assert_eq!((4 as $T).is_odd(), false);
+ }
+ }
+ )
+}
+
+impl_integer_for_int!(i8, test_integer_i8)
+impl_integer_for_int!(i16, test_integer_i16)
+impl_integer_for_int!(i32, test_integer_i32)
+impl_integer_for_int!(i64, test_integer_i64)
+impl_integer_for_int!(int, test_integer_int)
+
+macro_rules! impl_integer_for_uint {
+ ($T:ty, $test_mod:ident) => (
+ impl Integer for $T {
+ /// Unsigned integer division. Returns the same result as `div` (`/`).
+ #[inline]
+ fn div_floor(&self, other: &$T) -> $T { *self / *other }
+
+ /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
+ #[inline]
+ fn mod_floor(&self, other: &$T) -> $T { *self % *other }
+
+ /// Calculates the Greatest Common Divisor (GCD) of the number and `other`
+ #[inline]
+ fn gcd(&self, other: &$T) -> $T {
+ // Use Euclid's algorithm
+ let mut m = *self;
+ let mut n = *other;
+ while m != 0 {
+ let temp = m;
+ m = n % temp;
+ n = temp;
+ }
+ n
+ }
+
+ /// Calculates the Lowest Common Multiple (LCM) of the number and `other`
+ #[inline]
+ fn lcm(&self, other: &$T) -> $T {
+ (*self * *other) / self.gcd(other)
+ }
+
+ /// Returns `true` if the number can be divided by `other` without leaving a remainder
+ #[inline]
+ fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
+
+ /// Returns `true` if the number is divisible by `2`
+ #[inline]
+ fn is_even(&self) -> bool { self & 1 == 0 }
+
+ /// Returns `true` if the number is not divisible by `2`
+ #[inline]
+ fn is_odd(&self) -> bool { !self.is_even() }
+ }
+
+ #[cfg(test)]
+ mod $test_mod {
+ use Integer;
+
+ #[test]
+ fn test_div_mod_floor() {
+ assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T);
+ assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T);
+ assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T));
+ assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T);
+ assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T);
+ assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T));
+ assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T);
+ assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T);
+ assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T));
+ }
+
+ #[test]
+ fn test_gcd() {
+ assert_eq!((10 as $T).gcd(&2), 2 as $T);
+ assert_eq!((10 as $T).gcd(&3), 1 as $T);
+ assert_eq!((0 as $T).gcd(&3), 3 as $T);
+ assert_eq!((3 as $T).gcd(&3), 3 as $T);
+ assert_eq!((56 as $T).gcd(&42), 14 as $T);
+ }
+
+ #[test]
+ fn test_lcm() {
+ assert_eq!((1 as $T).lcm(&0), 0 as $T);
+ assert_eq!((0 as $T).lcm(&1), 0 as $T);
+ assert_eq!((1 as $T).lcm(&1), 1 as $T);
+ assert_eq!((8 as $T).lcm(&9), 72 as $T);
+ assert_eq!((11 as $T).lcm(&5), 55 as $T);
+ assert_eq!((99 as $T).lcm(&17), 1683 as $T);
+ }
+
+ #[test]
+ fn test_divides() {
+ assert!((6 as $T).divides(&(6 as $T)));
+ assert!((6 as $T).divides(&(3 as $T)));
+ assert!((6 as $T).divides(&(1 as $T)));
+ }
+
+ #[test]
+ fn test_even() {
+ assert_eq!((0 as $T).is_even(), true);
+ assert_eq!((1 as $T).is_even(), false);
+ assert_eq!((2 as $T).is_even(), true);
+ assert_eq!((3 as $T).is_even(), false);
+ assert_eq!((4 as $T).is_even(), true);
+ }
+
+ #[test]
+ fn test_odd() {
+ assert_eq!((0 as $T).is_odd(), false);
+ assert_eq!((1 as $T).is_odd(), true);
+ assert_eq!((2 as $T).is_odd(), false);
+ assert_eq!((3 as $T).is_odd(), true);
+ assert_eq!((4 as $T).is_odd(), false);
+ }
+ }
+ )
+}
+
+impl_integer_for_uint!(u8, test_integer_u8)
+impl_integer_for_uint!(u16, test_integer_u16)
+impl_integer_for_uint!(u32, test_integer_u32)
+impl_integer_for_uint!(u64, test_integer_u64)
+impl_integer_for_uint!(uint, test_integer_uint)
extern crate rand;
+pub use bigint::{BigInt, BigUint};
+pub use rational::{Rational, BigRational};
+pub use complex::Complex;
+pub use integer::Integer;
+
pub mod bigint;
-pub mod rational;
pub mod complex;
-
-pub trait Integer: Num + PartialOrd
- + Div<Self, Self>
- + Rem<Self, Self> {
- /// Simultaneous truncated integer division and modulus
- #[inline]
- fn div_rem(&self, other: &Self) -> (Self, Self) {
- (*self / *other, *self % *other)
- }
-
- /// Floored integer division
- ///
- /// # Examples
- ///
- /// ~~~
- /// # use num::Integer;
- /// assert!(( 8i).div_floor(& 3) == 2);
- /// assert!(( 8i).div_floor(&-3) == -3);
- /// assert!((-8i).div_floor(& 3) == -3);
- /// assert!((-8i).div_floor(&-3) == 2);
- ///
- /// assert!(( 1i).div_floor(& 2) == 0);
- /// assert!(( 1i).div_floor(&-2) == -1);
- /// assert!((-1i).div_floor(& 2) == -1);
- /// assert!((-1i).div_floor(&-2) == 0);
- /// ~~~
- fn div_floor(&self, other: &Self) -> Self;
-
- /// Floored integer modulo, satisfying:
- ///
- /// ~~~
- /// # use num::Integer;
- /// # let n = 1i; let d = 1i;
- /// assert!(n.div_floor(&d) * d + n.mod_floor(&d) == n)
- /// ~~~
- ///
- /// # Examples
- ///
- /// ~~~
- /// # use num::Integer;
- /// assert!(( 8i).mod_floor(& 3) == 2);
- /// assert!(( 8i).mod_floor(&-3) == -1);
- /// assert!((-8i).mod_floor(& 3) == 1);
- /// assert!((-8i).mod_floor(&-3) == -2);
- ///
- /// assert!(( 1i).mod_floor(& 2) == 1);
- /// assert!(( 1i).mod_floor(&-2) == -1);
- /// assert!((-1i).mod_floor(& 2) == 1);
- /// assert!((-1i).mod_floor(&-2) == -1);
- /// ~~~
- fn mod_floor(&self, other: &Self) -> Self;
-
- /// Simultaneous floored integer division and modulus
- fn div_mod_floor(&self, other: &Self) -> (Self, Self) {
- (self.div_floor(other), self.mod_floor(other))
- }
-
- /// Greatest Common Divisor (GCD)
- fn gcd(&self, other: &Self) -> Self;
-
- /// Lowest Common Multiple (LCM)
- fn lcm(&self, other: &Self) -> Self;
-
- /// Returns `true` if `other` divides evenly into `self`
- fn divides(&self, other: &Self) -> bool;
-
- /// Returns `true` if the number is even
- fn is_even(&self) -> bool;
-
- /// Returns `true` if the number is odd
- fn is_odd(&self) -> bool;
-}
-
-/// Simultaneous integer division and modulus
-#[inline] pub fn div_rem<T: Integer>(x: T, y: T) -> (T, T) { x.div_rem(&y) }
-/// Floored integer division
-#[inline] pub fn div_floor<T: Integer>(x: T, y: T) -> T { x.div_floor(&y) }
-/// Floored integer modulus
-#[inline] pub fn mod_floor<T: Integer>(x: T, y: T) -> T { x.mod_floor(&y) }
-/// Simultaneous floored integer division and modulus
-#[inline] pub fn div_mod_floor<T: Integer>(x: T, y: T) -> (T, T) { x.div_mod_floor(&y) }
-
-/// Calculates the Greatest Common Divisor (GCD) of the number and `other`. The
-/// result is always positive.
-#[inline(always)] pub fn gcd<T: Integer>(x: T, y: T) -> T { x.gcd(&y) }
-/// Calculates the Lowest Common Multiple (LCM) of the number and `other`.
-#[inline(always)] pub fn lcm<T: Integer>(x: T, y: T) -> T { x.lcm(&y) }
-
-macro_rules! impl_integer_for_int {
- ($T:ty, $test_mod:ident) => (
- impl Integer for $T {
- /// Floored integer division
- #[inline]
- fn div_floor(&self, other: &$T) -> $T {
- // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
- // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
- match self.div_rem(other) {
- (d, r) if (r > 0 && *other < 0)
- || (r < 0 && *other > 0) => d - 1,
- (d, _) => d,
- }
- }
-
- /// Floored integer modulo
- #[inline]
- fn mod_floor(&self, other: &$T) -> $T {
- // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
- // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
- match *self % *other {
- r if (r > 0 && *other < 0)
- || (r < 0 && *other > 0) => r + *other,
- r => r,
- }
- }
-
- /// Calculates `div_floor` and `mod_floor` simultaneously
- #[inline]
- fn div_mod_floor(&self, other: &$T) -> ($T,$T) {
- // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
- // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
- match self.div_rem(other) {
- (d, r) if (r > 0 && *other < 0)
- || (r < 0 && *other > 0) => (d - 1, r + *other),
- (d, r) => (d, r),
- }
- }
-
- /// Calculates the Greatest Common Divisor (GCD) of the number and
- /// `other`. The result is always positive.
- #[inline]
- fn gcd(&self, other: &$T) -> $T {
- // Use Euclid's algorithm
- let mut m = *self;
- let mut n = *other;
- while m != 0 {
- let temp = m;
- m = n % temp;
- n = temp;
- }
- n.abs()
- }
-
- /// Calculates the Lowest Common Multiple (LCM) of the number and
- /// `other`.
- #[inline]
- fn lcm(&self, other: &$T) -> $T {
- // should not have to recalculate abs
- ((*self * *other) / self.gcd(other)).abs()
- }
-
- /// Returns `true` if the number can be divided by `other` without
- /// leaving a remainder
- #[inline]
- fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
-
- /// Returns `true` if the number is divisible by `2`
- #[inline]
- fn is_even(&self) -> bool { self & 1 == 0 }
-
- /// Returns `true` if the number is not divisible by `2`
- #[inline]
- fn is_odd(&self) -> bool { !self.is_even() }
- }
-
- #[cfg(test)]
- mod $test_mod {
- use Integer;
-
- /// Checks that the division rule holds for:
- ///
- /// - `n`: numerator (dividend)
- /// - `d`: denominator (divisor)
- /// - `qr`: quotient and remainder
- #[cfg(test)]
- fn test_division_rule((n,d): ($T,$T), (q,r): ($T,$T)) {
- assert_eq!(d * q + r, n);
- }
-
- #[test]
- fn test_div_rem() {
- fn test_nd_dr(nd: ($T,$T), qr: ($T,$T)) {
- let (n,d) = nd;
- let separate_div_rem = (n / d, n % d);
- let combined_div_rem = n.div_rem(&d);
-
- assert_eq!(separate_div_rem, qr);
- assert_eq!(combined_div_rem, qr);
-
- test_division_rule(nd, separate_div_rem);
- test_division_rule(nd, combined_div_rem);
- }
-
- test_nd_dr(( 8, 3), ( 2, 2));
- test_nd_dr(( 8, -3), (-2, 2));
- test_nd_dr((-8, 3), (-2, -2));
- test_nd_dr((-8, -3), ( 2, -2));
-
- test_nd_dr(( 1, 2), ( 0, 1));
- test_nd_dr(( 1, -2), ( 0, 1));
- test_nd_dr((-1, 2), ( 0, -1));
- test_nd_dr((-1, -2), ( 0, -1));
- }
-
- #[test]
- fn test_div_mod_floor() {
- fn test_nd_dm(nd: ($T,$T), dm: ($T,$T)) {
- let (n,d) = nd;
- let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
- let combined_div_mod_floor = n.div_mod_floor(&d);
-
- assert_eq!(separate_div_mod_floor, dm);
- assert_eq!(combined_div_mod_floor, dm);
-
- test_division_rule(nd, separate_div_mod_floor);
- test_division_rule(nd, combined_div_mod_floor);
- }
-
- test_nd_dm(( 8, 3), ( 2, 2));
- test_nd_dm(( 8, -3), (-3, -1));
- test_nd_dm((-8, 3), (-3, 1));
- test_nd_dm((-8, -3), ( 2, -2));
-
- test_nd_dm(( 1, 2), ( 0, 1));
- test_nd_dm(( 1, -2), (-1, -1));
- test_nd_dm((-1, 2), (-1, 1));
- test_nd_dm((-1, -2), ( 0, -1));
- }
-
- #[test]
- fn test_gcd() {
- assert_eq!((10 as $T).gcd(&2), 2 as $T);
- assert_eq!((10 as $T).gcd(&3), 1 as $T);
- assert_eq!((0 as $T).gcd(&3), 3 as $T);
- assert_eq!((3 as $T).gcd(&3), 3 as $T);
- assert_eq!((56 as $T).gcd(&42), 14 as $T);
- assert_eq!((3 as $T).gcd(&-3), 3 as $T);
- assert_eq!((-6 as $T).gcd(&3), 3 as $T);
- assert_eq!((-4 as $T).gcd(&-2), 2 as $T);
- }
-
- #[test]
- fn test_lcm() {
- assert_eq!((1 as $T).lcm(&0), 0 as $T);
- assert_eq!((0 as $T).lcm(&1), 0 as $T);
- assert_eq!((1 as $T).lcm(&1), 1 as $T);
- assert_eq!((-1 as $T).lcm(&1), 1 as $T);
- assert_eq!((1 as $T).lcm(&-1), 1 as $T);
- assert_eq!((-1 as $T).lcm(&-1), 1 as $T);
- assert_eq!((8 as $T).lcm(&9), 72 as $T);
- assert_eq!((11 as $T).lcm(&5), 55 as $T);
- }
-
- #[test]
- fn test_even() {
- assert_eq!((-4 as $T).is_even(), true);
- assert_eq!((-3 as $T).is_even(), false);
- assert_eq!((-2 as $T).is_even(), true);
- assert_eq!((-1 as $T).is_even(), false);
- assert_eq!((0 as $T).is_even(), true);
- assert_eq!((1 as $T).is_even(), false);
- assert_eq!((2 as $T).is_even(), true);
- assert_eq!((3 as $T).is_even(), false);
- assert_eq!((4 as $T).is_even(), true);
- }
-
- #[test]
- fn test_odd() {
- assert_eq!((-4 as $T).is_odd(), false);
- assert_eq!((-3 as $T).is_odd(), true);
- assert_eq!((-2 as $T).is_odd(), false);
- assert_eq!((-1 as $T).is_odd(), true);
- assert_eq!((0 as $T).is_odd(), false);
- assert_eq!((1 as $T).is_odd(), true);
- assert_eq!((2 as $T).is_odd(), false);
- assert_eq!((3 as $T).is_odd(), true);
- assert_eq!((4 as $T).is_odd(), false);
- }
- }
- )
-}
-
-impl_integer_for_int!(i8, test_integer_i8)
-impl_integer_for_int!(i16, test_integer_i16)
-impl_integer_for_int!(i32, test_integer_i32)
-impl_integer_for_int!(i64, test_integer_i64)
-impl_integer_for_int!(int, test_integer_int)
-
-macro_rules! impl_integer_for_uint {
- ($T:ty, $test_mod:ident) => (
- impl Integer for $T {
- /// Unsigned integer division. Returns the same result as `div` (`/`).
- #[inline]
- fn div_floor(&self, other: &$T) -> $T { *self / *other }
-
- /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
- #[inline]
- fn mod_floor(&self, other: &$T) -> $T { *self % *other }
-
- /// Calculates the Greatest Common Divisor (GCD) of the number and `other`
- #[inline]
- fn gcd(&self, other: &$T) -> $T {
- // Use Euclid's algorithm
- let mut m = *self;
- let mut n = *other;
- while m != 0 {
- let temp = m;
- m = n % temp;
- n = temp;
- }
- n
- }
-
- /// Calculates the Lowest Common Multiple (LCM) of the number and `other`
- #[inline]
- fn lcm(&self, other: &$T) -> $T {
- (*self * *other) / self.gcd(other)
- }
-
- /// Returns `true` if the number can be divided by `other` without leaving a remainder
- #[inline]
- fn divides(&self, other: &$T) -> bool { *self % *other == 0 }
-
- /// Returns `true` if the number is divisible by `2`
- #[inline]
- fn is_even(&self) -> bool { self & 1 == 0 }
-
- /// Returns `true` if the number is not divisible by `2`
- #[inline]
- fn is_odd(&self) -> bool { !self.is_even() }
- }
-
- #[cfg(test)]
- mod $test_mod {
- use Integer;
-
- #[test]
- fn test_div_mod_floor() {
- assert_eq!((10 as $T).div_floor(&(3 as $T)), 3 as $T);
- assert_eq!((10 as $T).mod_floor(&(3 as $T)), 1 as $T);
- assert_eq!((10 as $T).div_mod_floor(&(3 as $T)), (3 as $T, 1 as $T));
- assert_eq!((5 as $T).div_floor(&(5 as $T)), 1 as $T);
- assert_eq!((5 as $T).mod_floor(&(5 as $T)), 0 as $T);
- assert_eq!((5 as $T).div_mod_floor(&(5 as $T)), (1 as $T, 0 as $T));
- assert_eq!((3 as $T).div_floor(&(7 as $T)), 0 as $T);
- assert_eq!((3 as $T).mod_floor(&(7 as $T)), 3 as $T);
- assert_eq!((3 as $T).div_mod_floor(&(7 as $T)), (0 as $T, 3 as $T));
- }
-
- #[test]
- fn test_gcd() {
- assert_eq!((10 as $T).gcd(&2), 2 as $T);
- assert_eq!((10 as $T).gcd(&3), 1 as $T);
- assert_eq!((0 as $T).gcd(&3), 3 as $T);
- assert_eq!((3 as $T).gcd(&3), 3 as $T);
- assert_eq!((56 as $T).gcd(&42), 14 as $T);
- }
-
- #[test]
- fn test_lcm() {
- assert_eq!((1 as $T).lcm(&0), 0 as $T);
- assert_eq!((0 as $T).lcm(&1), 0 as $T);
- assert_eq!((1 as $T).lcm(&1), 1 as $T);
- assert_eq!((8 as $T).lcm(&9), 72 as $T);
- assert_eq!((11 as $T).lcm(&5), 55 as $T);
- assert_eq!((99 as $T).lcm(&17), 1683 as $T);
- }
-
- #[test]
- fn test_divides() {
- assert!((6 as $T).divides(&(6 as $T)));
- assert!((6 as $T).divides(&(3 as $T)));
- assert!((6 as $T).divides(&(1 as $T)));
- }
-
- #[test]
- fn test_even() {
- assert_eq!((0 as $T).is_even(), true);
- assert_eq!((1 as $T).is_even(), false);
- assert_eq!((2 as $T).is_even(), true);
- assert_eq!((3 as $T).is_even(), false);
- assert_eq!((4 as $T).is_even(), true);
- }
-
- #[test]
- fn test_odd() {
- assert_eq!((0 as $T).is_odd(), false);
- assert_eq!((1 as $T).is_odd(), true);
- assert_eq!((2 as $T).is_odd(), false);
- assert_eq!((3 as $T).is_odd(), true);
- assert_eq!((4 as $T).is_odd(), false);
- }
- }
- )
-}
-
-impl_integer_for_uint!(u8, test_integer_u8)
-impl_integer_for_uint!(u16, test_integer_u16)
-impl_integer_for_uint!(u32, test_integer_u32)
-impl_integer_for_uint!(u64, test_integer_u64)
-impl_integer_for_uint!(uint, test_integer_uint)
+pub mod integer;
+pub mod rational;
let cdata = cstore.get_crate_data(cnum);
decoder::get_reachable_extern_fns(&*cdata)
}
+
+pub fn is_typedef(cstore: &cstore::CStore, did: ast::DefId) -> bool {
+ let cdata = cstore.get_crate_data(did.krate);
+ decoder::is_typedef(&*cdata, did.node)
+}
});
return ret;
}
+
+pub fn is_typedef(cdata: Cmd, id: ast::NodeId) -> bool {
+ let item_doc = lookup_item(id, cdata.data());
+ match item_family(item_doc) {
+ Type => true,
+ _ => false,
+ }
+}
use std::cell::RefCell;
use std::os;
use std::io::fs;
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
use std::collections::HashSet;
use myfs = util::fs;
use std::mem;
use std::os;
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
use syntax::ast;
use syntax::attr;
use syntax::visit;
fn build_type(tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
let t = ty::lookup_item_type(tcx, did);
match ty::get(t.ty).sty {
- ty::ty_enum(edid, _) => {
+ ty::ty_enum(edid, _) if !csearch::is_typedef(&tcx.sess.cstore, did) => {
return clean::EnumItem(clean::Enum {
generics: t.generics.clean(),
variants_stripped: false,
mod imp {
use libc;
use std::mem;
- use std::os::win32::as_utf16_p;
use std::os;
use std::ptr;
impl Lock {
pub fn new(p: &Path) -> Lock {
- let handle = as_utf16_p(p.as_str().unwrap(), |p| unsafe {
- libc::CreateFileW(p,
+ let p_16 = p.as_str().unwrap().to_utf16().append_one(0);
+ let handle = unsafe {
+ libc::CreateFileW(p_16.as_ptr(),
libc::FILE_GENERIC_READ |
libc::FILE_GENERIC_WRITE,
libc::FILE_SHARE_READ |
libc::CREATE_ALWAYS,
libc::FILE_ATTRIBUTE_NORMAL,
ptr::mut_null())
- });
+ };
if handle as uint == libc::INVALID_HANDLE_VALUE as uint {
fail!("create file error: {}", os::last_os_error());
}
use clean;
-use dl = std::unstable::dynamic_lib;
+use dl = std::dynamic_lib;
use serialize::json;
use std::string::String;
use std::os;
use std::str;
use std::string::String;
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
use std::collections::{HashSet, HashMap};
use testing;
--- /dev/null
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+Dynamic library facilities.
+
+A simple wrapper over the platform's dynamic library facilities
+
+*/
+
+#![experimental]
+#![allow(missing_doc)]
+
+use clone::Clone;
+use c_str::ToCStr;
+use iter::Iterator;
+use mem;
+use ops::*;
+use option::*;
+use os;
+use path::{Path,GenericPath};
+use result::*;
+use slice::{Vector,ImmutableVector};
+use str;
+use string::String;
+use vec::Vec;
+
+pub struct DynamicLibrary { handle: *u8}
+
+impl Drop for DynamicLibrary {
+ fn drop(&mut self) {
+ match dl::check_for_errors_in(|| {
+ unsafe {
+ dl::close(self.handle)
+ }
+ }) {
+ Ok(()) => {},
+ Err(str) => fail!("{}", str)
+ }
+ }
+}
+
+impl DynamicLibrary {
+ // FIXME (#12938): Until DST lands, we cannot decompose &str into
+ // & and str, so we cannot usefully take ToCStr arguments by
+ // reference (without forcing an additional & around &str). So we
+ // are instead temporarily adding an instance for &Path, so that
+ // we can take ToCStr as owned. When DST lands, the &Path instance
+ // should be removed, and arguments bound by ToCStr should be
+ // passed by reference. (Here: in the `open` method.)
+
+ /// Lazily open a dynamic library. When passed None it gives a
+ /// handle to the calling process
+ pub fn open<T: ToCStr>(filename: Option<T>)
+ -> Result<DynamicLibrary, String> {
+ unsafe {
+ let mut filename = filename;
+ let maybe_library = dl::check_for_errors_in(|| {
+ match filename.take() {
+ Some(name) => dl::open_external(name),
+ None => dl::open_internal()
+ }
+ });
+
+ // The dynamic library must not be constructed if there is
+ // an error opening the library so the destructor does not
+ // run.
+ match maybe_library {
+ Err(err) => Err(err),
+ Ok(handle) => Ok(DynamicLibrary { handle: handle })
+ }
+ }
+ }
+
+ /// Prepends a path to this process's search path for dynamic libraries
+ pub fn prepend_search_path(path: &Path) {
+ let mut search_path = DynamicLibrary::search_path();
+ search_path.insert(0, path.clone());
+ let newval = DynamicLibrary::create_path(search_path.as_slice());
+ os::setenv(DynamicLibrary::envvar(),
+ str::from_utf8(newval.as_slice()).unwrap());
+ }
+
+ /// From a slice of paths, create a new vector which is suitable to be an
+ /// environment variable for this platforms dylib search path.
+ pub fn create_path(path: &[Path]) -> Vec<u8> {
+ let mut newvar = Vec::new();
+ for (i, path) in path.iter().enumerate() {
+ if i > 0 { newvar.push(DynamicLibrary::separator()); }
+ newvar.push_all(path.as_vec());
+ }
+ return newvar;
+ }
+
+ /// Returns the environment variable for this process's dynamic library
+ /// search path
+ pub fn envvar() -> &'static str {
+ if cfg!(windows) {
+ "PATH"
+ } else if cfg!(target_os = "macos") {
+ "DYLD_LIBRARY_PATH"
+ } else {
+ "LD_LIBRARY_PATH"
+ }
+ }
+
+ fn separator() -> u8 {
+ if cfg!(windows) {';' as u8} else {':' as u8}
+ }
+
+ /// Returns the current search path for dynamic libraries being used by this
+ /// process
+ pub fn search_path() -> Vec<Path> {
+ let mut ret = Vec::new();
+ match os::getenv_as_bytes(DynamicLibrary::envvar()) {
+ Some(env) => {
+ for portion in
+ env.as_slice()
+ .split(|a| *a == DynamicLibrary::separator()) {
+ ret.push(Path::new(portion));
+ }
+ }
+ None => {}
+ }
+ return ret;
+ }
+
+ /// Access the value at the symbol of the dynamic library
+ pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, String> {
+ // This function should have a lifetime constraint of 'a on
+ // T but that feature is still unimplemented
+
+ let maybe_symbol_value = dl::check_for_errors_in(|| {
+ symbol.with_c_str(|raw_string| {
+ dl::symbol(self.handle, raw_string)
+ })
+ });
+
+ // The value must not be constructed if there is an error so
+ // the destructor does not run.
+ match maybe_symbol_value {
+ Err(err) => Err(err),
+ Ok(symbol_value) => Ok(mem::transmute(symbol_value))
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+ use prelude::*;
+ use libc;
+
+ #[test]
+ #[ignore(cfg(windows))] // FIXME #8818
+ #[ignore(cfg(target_os="android"))] // FIXME(#10379)
+ fn test_loading_cosine() {
+ // The math library does not need to be loaded since it is already
+ // statically linked in
+ let none: Option<Path> = None; // appease the typechecker
+ let libm = match DynamicLibrary::open(none) {
+ Err(error) => fail!("Could not load self as module: {}", error),
+ Ok(libm) => libm
+ };
+
+ let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
+ match libm.symbol("cos") {
+ Err(error) => fail!("Could not load function cos: {}", error),
+ Ok(cosine) => cosine
+ }
+ };
+
+ let argument = 0.0;
+ let expected_result = 1.0;
+ let result = cosine(argument);
+ if result != expected_result {
+ fail!("cos({:?}) != {:?} but equaled {:?} instead", argument,
+ expected_result, result)
+ }
+ }
+
+ #[test]
+ #[cfg(target_os = "linux")]
+ #[cfg(target_os = "macos")]
+ #[cfg(target_os = "freebsd")]
+ fn test_errors_do_not_crash() {
+ // Open /dev/null as a library to get an error, and make sure
+ // that only causes an error, and not a crash.
+ let path = Path::new("/dev/null");
+ match DynamicLibrary::open(Some(&path)) {
+ Err(_) => {}
+ Ok(_) => fail!("Successfully opened the empty library.")
+ }
+ }
+}
+
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "android")]
+#[cfg(target_os = "macos")]
+#[cfg(target_os = "freebsd")]
+pub mod dl {
+ use prelude::*;
+
+ use c_str::{CString, ToCStr};
+ use libc;
+ use ptr;
+ use result::*;
+ use str::StrAllocating;
+ use string::String;
+
+ pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
+ filename.with_c_str(|raw_name| {
+ dlopen(raw_name, Lazy as libc::c_int) as *u8
+ })
+ }
+
+ pub unsafe fn open_internal() -> *u8 {
+ dlopen(ptr::null(), Lazy as libc::c_int) as *u8
+ }
+
+ pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
+ use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
+ static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
+ unsafe {
+ // dlerror isn't thread safe, so we need to lock around this entire
+ // sequence
+ let _guard = lock.lock();
+ let _old_error = dlerror();
+
+ let result = f();
+
+ let last_error = dlerror();
+ let ret = if ptr::null() == last_error {
+ Ok(result)
+ } else {
+ Err(CString::new(last_error, false).as_str()
+ .unwrap()
+ .to_string())
+ };
+
+ ret
+ }
+ }
+
+ pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
+ dlsym(handle as *libc::c_void, symbol) as *u8
+ }
+ pub unsafe fn close(handle: *u8) {
+ dlclose(handle as *libc::c_void); ()
+ }
+
+ pub enum RTLD {
+ Lazy = 1,
+ Now = 2,
+ Global = 256,
+ Local = 0,
+ }
+
+ #[link_name = "dl"]
+ extern {
+ fn dlopen(filename: *libc::c_char, flag: libc::c_int) -> *libc::c_void;
+ fn dlerror() -> *libc::c_char;
+ fn dlsym(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void;
+ fn dlclose(handle: *libc::c_void) -> libc::c_int;
+ }
+}
+
+#[cfg(target_os = "win32")]
+pub mod dl {
+ use c_str::ToCStr;
+ use libc;
+ use os;
+ use ptr;
+ use result::{Ok, Err, Result};
+ use str::StrAllocating;
+ use str;
+ use string::String;
+
+ pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
+ // Windows expects Unicode data
+ let filename_cstr = filename.to_c_str();
+ let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap();
+ let filename_str = filename_str.to_utf16().append_one(0);
+ LoadLibraryW(filename_str.as_ptr() as *libc::c_void) as *u8
+ }
+
+ pub unsafe fn open_internal() -> *u8 {
+ let handle = ptr::null();
+ GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void);
+ handle as *u8
+ }
+
+ pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
+ unsafe {
+ SetLastError(0);
+
+ let result = f();
+
+ let error = os::errno();
+ if 0 == error {
+ Ok(result)
+ } else {
+ Err(format!("Error code {}", error))
+ }
+ }
+ }
+
+ pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
+ GetProcAddress(handle as *libc::c_void, symbol) as *u8
+ }
+ pub unsafe fn close(handle: *u8) {
+ FreeLibrary(handle as *libc::c_void); ()
+ }
+
+ #[allow(non_snake_case_functions)]
+ extern "system" {
+ fn SetLastError(error: libc::size_t);
+ fn LoadLibraryW(name: *libc::c_void) -> *libc::c_void;
+ fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
+ handle: **libc::c_void) -> *libc::c_void;
+ fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
+ fn FreeLibrary(handle: *libc::c_void);
+ }
+}
* Make a simple TCP client connection and request
- ```rust,should_fail
+ ```rust
# #![allow(unused_must_use)]
use std::io::net::tcp::TcpStream;
+ # // connection doesn't fail if a server is running on 8080
+ # // locally, we still want to be type checking this code, so lets
+ # // just stop it running (#11576)
+ # if false {
let mut socket = TcpStream::connect("127.0.0.1", 8080).unwrap();
socket.write(bytes!("GET / HTTP/1.0\n\n"));
let response = socket.read_to_end();
+ # }
```
* Make a simple TCP server
/* Runtime and platform support */
pub mod c_vec;
+pub mod dynamic_lib;
pub mod os;
pub mod io;
pub mod path;
pub mod fmt;
-// Private APIs
-#[unstable]
-pub mod unstable;
-
// FIXME #7809: This shouldn't be pub, and it should be reexported under 'unstable'
// but name resolution doesn't work without it being pub.
#[unstable]
// The test runner requires std::slice::Vector, so re-export std::slice just for it.
#[cfg(test)] pub use slice;
}
+
+#[deprecated]
+#[allow(missing_doc)]
+#[doc(hiden)]
+pub mod unstable {
+ #[deprecated = "use std::dynamic_lib"]
+ pub use dynamic_lib;
+}
use os::TMPBUF_SZ;
use slice::{MutableVector, ImmutableVector};
use string::String;
- use str::{StrSlice, StrAllocating};
+ use str::StrSlice;
use str;
use vec::Vec;
return res;
}
}
-
- pub fn as_utf16_p<T>(s: &str, f: |*u16| -> T) -> T {
- as_mut_utf16_p(s, |t| { f(t as *u16) })
- }
-
- pub fn as_mut_utf16_p<T>(s: &str, f: |*mut u16| -> T) -> T {
- let mut t = s.to_utf16();
- // Null terminate before passing on.
- t.push(0u16);
- f(t.as_mut_ptr())
- }
}
/*
pub fn getenv(n: &str) -> Option<String> {
unsafe {
with_env_lock(|| {
- use os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
- as_utf16_p(n, |u| {
- fill_utf16_buf_and_decode(|buf, sz| {
- libc::GetEnvironmentVariableW(u, buf, sz)
- })
+ use os::win32::{fill_utf16_buf_and_decode};
+ let n = n.to_utf16().append_one(0);
+ fill_utf16_buf_and_decode(|buf, sz| {
+ libc::GetEnvironmentVariableW(n.as_ptr(), buf, sz)
})
})
}
/// Sets the environment variable `n` to the value `v` for the currently running
/// process
pub fn setenv(n: &str, v: &str) {
+ let n = n.to_utf16().append_one(0);
+ let v = v.to_utf16().append_one(0);
unsafe {
with_env_lock(|| {
- use os::win32::as_utf16_p;
- as_utf16_p(n, |nbuf| {
- as_utf16_p(v, |vbuf| {
- libc::SetEnvironmentVariableW(nbuf, vbuf);
- })
- })
+ libc::SetEnvironmentVariableW(n.as_ptr(), v.as_ptr());
})
}
}
}
#[cfg(windows)]
fn _unsetenv(n: &str) {
+ let n = n.to_utf16().append_one(0);
unsafe {
with_env_lock(|| {
- use os::win32::as_utf16_p;
- as_utf16_p(n, |nbuf| {
- libc::SetEnvironmentVariableW(nbuf, ptr::null());
- })
+ libc::SetEnvironmentVariableW(n.as_ptr(), ptr::null());
})
}
}
#[cfg(windows)]
fn chdir(p: &Path) -> bool {
+ let p = match p.as_str() {
+ Some(s) => s.to_utf16().append_one(0),
+ None => return false,
+ };
unsafe {
- use os::win32::as_utf16_p;
- return as_utf16_p(p.as_str().unwrap(), |buf| {
- libc::SetCurrentDirectoryW(buf) != (0 as libc::BOOL)
- });
+ libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL)
}
}
use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
use slice::ImmutableVector;
use str::StrSlice;
- use unstable::dynamic_lib::DynamicLibrary;
+ use dynamic_lib::DynamicLibrary;
#[allow(non_snake_case_functions)]
extern "system" {
+++ /dev/null
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
-
-Dynamic library facilities.
-
-A simple wrapper over the platform's dynamic library facilities
-
-*/
-
-use clone::Clone;
-use c_str::ToCStr;
-use iter::Iterator;
-use mem;
-use ops::*;
-use option::*;
-use os;
-use path::{Path,GenericPath};
-use result::*;
-use slice::{Vector,ImmutableVector};
-use str;
-use string::String;
-use vec::Vec;
-
-pub struct DynamicLibrary { handle: *u8}
-
-impl Drop for DynamicLibrary {
- fn drop(&mut self) {
- match dl::check_for_errors_in(|| {
- unsafe {
- dl::close(self.handle)
- }
- }) {
- Ok(()) => {},
- Err(str) => fail!("{}", str)
- }
- }
-}
-
-impl DynamicLibrary {
- // FIXME (#12938): Until DST lands, we cannot decompose &str into
- // & and str, so we cannot usefully take ToCStr arguments by
- // reference (without forcing an additional & around &str). So we
- // are instead temporarily adding an instance for &Path, so that
- // we can take ToCStr as owned. When DST lands, the &Path instance
- // should be removed, and arguments bound by ToCStr should be
- // passed by reference. (Here: in the `open` method.)
-
- /// Lazily open a dynamic library. When passed None it gives a
- /// handle to the calling process
- pub fn open<T: ToCStr>(filename: Option<T>)
- -> Result<DynamicLibrary, String> {
- unsafe {
- let mut filename = filename;
- let maybe_library = dl::check_for_errors_in(|| {
- match filename.take() {
- Some(name) => dl::open_external(name),
- None => dl::open_internal()
- }
- });
-
- // The dynamic library must not be constructed if there is
- // an error opening the library so the destructor does not
- // run.
- match maybe_library {
- Err(err) => Err(err),
- Ok(handle) => Ok(DynamicLibrary { handle: handle })
- }
- }
- }
-
- /// Prepends a path to this process's search path for dynamic libraries
- pub fn prepend_search_path(path: &Path) {
- let mut search_path = DynamicLibrary::search_path();
- search_path.insert(0, path.clone());
- let newval = DynamicLibrary::create_path(search_path.as_slice());
- os::setenv(DynamicLibrary::envvar(),
- str::from_utf8(newval.as_slice()).unwrap());
- }
-
- /// From a slice of paths, create a new vector which is suitable to be an
- /// environment variable for this platforms dylib search path.
- pub fn create_path(path: &[Path]) -> Vec<u8> {
- let mut newvar = Vec::new();
- for (i, path) in path.iter().enumerate() {
- if i > 0 { newvar.push(DynamicLibrary::separator()); }
- newvar.push_all(path.as_vec());
- }
- return newvar;
- }
-
- /// Returns the environment variable for this process's dynamic library
- /// search path
- pub fn envvar() -> &'static str {
- if cfg!(windows) {
- "PATH"
- } else if cfg!(target_os = "macos") {
- "DYLD_LIBRARY_PATH"
- } else {
- "LD_LIBRARY_PATH"
- }
- }
-
- fn separator() -> u8 {
- if cfg!(windows) {';' as u8} else {':' as u8}
- }
-
- /// Returns the current search path for dynamic libraries being used by this
- /// process
- pub fn search_path() -> Vec<Path> {
- let mut ret = Vec::new();
- match os::getenv_as_bytes(DynamicLibrary::envvar()) {
- Some(env) => {
- for portion in
- env.as_slice()
- .split(|a| *a == DynamicLibrary::separator()) {
- ret.push(Path::new(portion));
- }
- }
- None => {}
- }
- return ret;
- }
-
- /// Access the value at the symbol of the dynamic library
- pub unsafe fn symbol<T>(&self, symbol: &str) -> Result<T, String> {
- // This function should have a lifetime constraint of 'a on
- // T but that feature is still unimplemented
-
- let maybe_symbol_value = dl::check_for_errors_in(|| {
- symbol.with_c_str(|raw_string| {
- dl::symbol(self.handle, raw_string)
- })
- });
-
- // The value must not be constructed if there is an error so
- // the destructor does not run.
- match maybe_symbol_value {
- Err(err) => Err(err),
- Ok(symbol_value) => Ok(mem::transmute(symbol_value))
- }
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
- use prelude::*;
- use libc;
-
- #[test]
- #[ignore(cfg(windows))] // FIXME #8818
- #[ignore(cfg(target_os="android"))] // FIXME(#10379)
- fn test_loading_cosine() {
- // The math library does not need to be loaded since it is already
- // statically linked in
- let none: Option<Path> = None; // appease the typechecker
- let libm = match DynamicLibrary::open(none) {
- Err(error) => fail!("Could not load self as module: {}", error),
- Ok(libm) => libm
- };
-
- let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
- match libm.symbol("cos") {
- Err(error) => fail!("Could not load function cos: {}", error),
- Ok(cosine) => cosine
- }
- };
-
- let argument = 0.0;
- let expected_result = 1.0;
- let result = cosine(argument);
- if result != expected_result {
- fail!("cos({:?}) != {:?} but equaled {:?} instead", argument,
- expected_result, result)
- }
- }
-
- #[test]
- #[cfg(target_os = "linux")]
- #[cfg(target_os = "macos")]
- #[cfg(target_os = "freebsd")]
- fn test_errors_do_not_crash() {
- // Open /dev/null as a library to get an error, and make sure
- // that only causes an error, and not a crash.
- let path = Path::new("/dev/null");
- match DynamicLibrary::open(Some(&path)) {
- Err(_) => {}
- Ok(_) => fail!("Successfully opened the empty library.")
- }
- }
-}
-
-#[cfg(target_os = "linux")]
-#[cfg(target_os = "android")]
-#[cfg(target_os = "macos")]
-#[cfg(target_os = "freebsd")]
-pub mod dl {
- use prelude::*;
-
- use c_str::{CString, ToCStr};
- use libc;
- use ptr;
- use result::*;
- use str::StrAllocating;
- use string::String;
-
- pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
- filename.with_c_str(|raw_name| {
- dlopen(raw_name, Lazy as libc::c_int) as *u8
- })
- }
-
- pub unsafe fn open_internal() -> *u8 {
- dlopen(ptr::null(), Lazy as libc::c_int) as *u8
- }
-
- pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
- use rt::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
- static mut lock: StaticNativeMutex = NATIVE_MUTEX_INIT;
- unsafe {
- // dlerror isn't thread safe, so we need to lock around this entire
- // sequence
- let _guard = lock.lock();
- let _old_error = dlerror();
-
- let result = f();
-
- let last_error = dlerror();
- let ret = if ptr::null() == last_error {
- Ok(result)
- } else {
- Err(CString::new(last_error, false).as_str()
- .unwrap()
- .to_string())
- };
-
- ret
- }
- }
-
- pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
- dlsym(handle as *libc::c_void, symbol) as *u8
- }
- pub unsafe fn close(handle: *u8) {
- dlclose(handle as *libc::c_void); ()
- }
-
- pub enum RTLD {
- Lazy = 1,
- Now = 2,
- Global = 256,
- Local = 0,
- }
-
- #[link_name = "dl"]
- extern {
- fn dlopen(filename: *libc::c_char, flag: libc::c_int) -> *libc::c_void;
- fn dlerror() -> *libc::c_char;
- fn dlsym(handle: *libc::c_void, symbol: *libc::c_char) -> *libc::c_void;
- fn dlclose(handle: *libc::c_void) -> libc::c_int;
- }
-}
-
-#[cfg(target_os = "win32")]
-pub mod dl {
- use libc;
- use os;
- use ptr;
- use result::{Ok, Err, Result};
- use string::String;
- use str;
- use c_str::ToCStr;
-
- pub unsafe fn open_external<T: ToCStr>(filename: T) -> *u8 {
- // Windows expects Unicode data
- let filename_cstr = filename.to_c_str();
- let filename_str = str::from_utf8(filename_cstr.as_bytes_no_nul()).unwrap();
- os::win32::as_utf16_p(filename_str, |raw_name| {
- LoadLibraryW(raw_name as *libc::c_void) as *u8
- })
- }
-
- pub unsafe fn open_internal() -> *u8 {
- let handle = ptr::null();
- GetModuleHandleExW(0 as libc::DWORD, ptr::null(), &handle as **libc::c_void);
- handle as *u8
- }
-
- pub fn check_for_errors_in<T>(f: || -> T) -> Result<T, String> {
- unsafe {
- SetLastError(0);
-
- let result = f();
-
- let error = os::errno();
- if 0 == error {
- Ok(result)
- } else {
- Err(format!("Error code {}", error))
- }
- }
- }
-
- pub unsafe fn symbol(handle: *u8, symbol: *libc::c_char) -> *u8 {
- GetProcAddress(handle as *libc::c_void, symbol) as *u8
- }
- pub unsafe fn close(handle: *u8) {
- FreeLibrary(handle as *libc::c_void); ()
- }
-
- #[allow(non_snake_case_functions)]
- extern "system" {
- fn SetLastError(error: libc::size_t);
- fn LoadLibraryW(name: *libc::c_void) -> *libc::c_void;
- fn GetModuleHandleExW(dwFlags: libc::DWORD, name: *u16,
- handle: **libc::c_void) -> *libc::c_void;
- fn GetProcAddress(handle: *libc::c_void, name: *libc::c_char) -> *libc::c_void;
- fn FreeLibrary(handle: *libc::c_void);
- }
-}
+++ /dev/null
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![doc(hidden)]
-
-pub mod dynamic_lib;
tests)
}
+pub enum ColorConfig {
+ AutoColor,
+ AlwaysColor,
+ NeverColor,
+}
+
pub struct TestOpts {
pub filter: Option<Regex>,
pub run_ignored: bool,
pub test_shard: Option<(uint,uint)>,
pub logfile: Option<Path>,
pub nocapture: bool,
+ pub color: ColorConfig,
}
impl TestOpts {
test_shard: None,
logfile: None,
nocapture: false,
+ color: AutoColor,
}
}
}
getopts::optopt("", "test-shard", "run shard A, of B shards, worth of the testsuite",
"A.B"),
getopts::optflag("", "nocapture", "don't capture stdout/stderr of each \
- task, allow printing directly"))
+ task, allow printing directly"),
+ getopts::optopt("", "color", "Configure coloring of output:
+ auto = colorize if stdout is a tty and tests are run on serially (default);
+ always = always colorize output;
+ never = never colorize output;", "auto|always|never"))
}
fn usage(binary: &str) {
nocapture = os::getenv("RUST_TEST_NOCAPTURE").is_some();
}
+ let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
+ Some("auto") | None => AutoColor,
+ Some("always") => AlwaysColor,
+ Some("never") => NeverColor,
+
+ Some(v) => return Some(Err(format!("argument for --color must be \
+ auto, always, or never (was {})",
+ v))),
+ };
+
let test_opts = TestOpts {
filter: filter,
run_ignored: run_ignored,
test_shard: test_shard,
logfile: logfile,
nocapture: nocapture,
+ color: color,
};
Some(Ok(test_opts))
Ok(ConsoleTestState {
out: out,
log_out: log_out,
- use_color: use_color(),
+ use_color: use_color(opts),
total: 0u,
passed: 0u,
failed: 0u,
assert!(apos < bpos);
}
-fn use_color() -> bool {
- get_concurrency() == 1 && io::stdout().get_ref().isatty()
+fn use_color(opts: &TestOpts) -> bool {
+ match opts.color {
+ AutoColor => get_concurrency() == 1 && io::stdout().get_ref().isatty(),
+ AlwaysColor => true,
+ NeverColor => false,
+ }
}
#[deriving(Clone)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
#[no_mangle]
pub fn foo() { bar(); }
--- /dev/null
+// 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.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+// Used to cause ICE
+
+static VEC: [u32, ..256] = vec!(); //~ ERROR mismatched types
+
+fn main() {}
+
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use std::unstable::dynamic_lib::DynamicLibrary;
+use std::dynamic_lib::DynamicLibrary;
use std::os;
pub fn main() {
// aux-build:linkage-visibility.rs
// ignore-android: FIXME(#10379)
-// ignore-win32: std::unstable::dynamic_lib does not work on win32 well
+// ignore-win32: std::dynamic_lib does not work on win32 well
extern crate foo = "linkage-visibility";