1
Fork 0

auto merge of #18978 : jakub-/rust/roll-up, r=cmr

This commit is contained in:
bors 2014-11-16 11:27:35 +00:00
commit 0c7a3d6c16
74 changed files with 1015 additions and 937 deletions

View file

@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use std::from_str::FromStr;
use std::fmt; use std::fmt;
use std::str::FromStr;
use regex::Regex; use regex::Regex;
#[deriving(Clone, PartialEq)] #[deriving(Clone, PartialEq)]

View file

@ -22,7 +22,7 @@ extern crate regex;
use std::os; use std::os;
use std::io; use std::io;
use std::io::fs; use std::io::fs;
use std::from_str::FromStr; use std::str::FromStr;
use getopts::{optopt, optflag, reqopt}; use getopts::{optopt, optflag, reqopt};
use common::Config; use common::Config;
use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Codegen}; use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Codegen};

View file

@ -12,8 +12,6 @@ use common::Config;
use common; use common;
use util; use util;
use std::from_str::FromStr;
pub struct TestProps { pub struct TestProps {
// Lines that should be expected, in order, on standard out // Lines that should be expected, in order, on standard out
pub error_patterns: Vec<String> , pub error_patterns: Vec<String> ,
@ -353,8 +351,8 @@ pub fn gdb_version_to_int(version_string: &str) -> int {
panic!("{}", error_string); panic!("{}", error_string);
} }
let major: int = FromStr::from_str(components[0]).expect(error_string); let major: int = from_str(components[0]).expect(error_string);
let minor: int = FromStr::from_str(components[1]).expect(error_string); let minor: int = from_str(components[1]).expect(error_string);
return major * 1000 + minor; return major * 1000 + minor;
} }
@ -364,6 +362,6 @@ pub fn lldb_version_to_int(version_string: &str) -> int {
"Encountered LLDB version string with unexpected format: {}", "Encountered LLDB version string with unexpected format: {}",
version_string); version_string);
let error_string = error_string.as_slice(); let error_string = error_string.as_slice();
let major: int = FromStr::from_str(version_string).expect(error_string); let major: int = from_str(version_string).expect(error_string);
return major; return major;
} }

View file

@ -95,7 +95,7 @@ code should need to run is a stack.
`match` being exhaustive has some useful properties. First, if every `match` being exhaustive has some useful properties. First, if every
possibility is covered by the `match`, adding further variants to the `enum` possibility is covered by the `match`, adding further variants to the `enum`
in the future will prompt a compilation failure, rather than runtime panic. in the future will prompt a compilation failure, rather than runtime panic.
Second, it makes cost explicit. In general, only safe way to have a Second, it makes cost explicit. In general, the only safe way to have a
non-exhaustive match would be to panic the task if nothing is matched, though non-exhaustive match would be to panic the task if nothing is matched, though
it could fall through if the type of the `match` expression is `()`. This sort it could fall through if the type of the `match` expression is `()`. This sort
of hidden cost and special casing is against the language's philosophy. It's of hidden cost and special casing is against the language's philosophy. It's

View file

@ -133,11 +133,11 @@ pass-by-reference. Basically, languages can make two choices (this is made
up syntax, it's not Rust): up syntax, it's not Rust):
```{notrust,ignore} ```{notrust,ignore}
fn foo(x) { func foo(x) {
x = 5 x = 5
} }
fn main() { func main() {
i = 1 i = 1
foo(i) foo(i)
// what is the value of i here? // what is the value of i here?
@ -153,11 +153,11 @@ So what do pointers have to do with this? Well, since pointers point to a
location in memory... location in memory...
```{notrust,ignore} ```{notrust,ignore}
fn foo(&int x) { func foo(&int x) {
*x = 5 *x = 5
} }
fn main() { func main() {
i = 1 i = 1
foo(&i) foo(&i)
// what is the value of i here? // what is the value of i here?
@ -192,13 +192,13 @@ When you combine pointers and functions, it's easy to accidentally invalidate
the memory the pointer is pointing to. For example: the memory the pointer is pointing to. For example:
```{notrust,ignore} ```{notrust,ignore}
fn make_pointer(): &int { func make_pointer(): &int {
x = 5; x = 5;
return &x; return &x;
} }
fn main() { func main() {
&int i = make_pointer(); &int i = make_pointer();
*i = 5; // uh oh! *i = 5; // uh oh!
} }
@ -214,11 +214,11 @@ issue. Two pointers are said to alias when they point at the same location
in memory. Like this: in memory. Like this:
```{notrust,ignore} ```{notrust,ignore}
fn mutate(&int i, int j) { func mutate(&int i, int j) {
*i = j; *i = j;
} }
fn main() { func main() {
x = 5; x = 5;
y = &x; y = &x;
z = &x; //y and z are aliased z = &x; //y and z are aliased

View file

@ -155,7 +155,7 @@ println!("{}", s[0]);
This does not compile. This is on purpose. In the world of UTF-8, direct This does not compile. This is on purpose. In the world of UTF-8, direct
indexing is basically never what you want to do. The reason is that each indexing is basically never what you want to do. The reason is that each
character can be a variable number of bytes. This means that you have to iterate character can be a variable number of bytes. This means that you have to iterate
through the characters anyway, which is a O(n) operation. through the characters anyway, which is an O(n) operation.
There's 3 basic levels of unicode (and its encodings): There's 3 basic levels of unicode (and its encodings):

View file

@ -2526,7 +2526,7 @@ The currently implemented features of the reference compiler are:
* `plugin_registrar` - Indicates that a crate has [compiler plugins][plugin] that it * `plugin_registrar` - Indicates that a crate has [compiler plugins][plugin] that it
wants to load. As with `phase`, the implementation is wants to load. As with `phase`, the implementation is
in need of a overhaul, and it is not clear that plugins in need of an overhaul, and it is not clear that plugins
defined using this will continue to work. defined using this will continue to work.
* `quote` - Allows use of the `quote_*!` family of macros, which are * `quote` - Allows use of the `quote_*!` family of macros, which are
@ -2583,7 +2583,7 @@ there isn't a parser error first). The directive in this case is no longer
necessary, and it's likely that existing code will break if the feature isn't necessary, and it's likely that existing code will break if the feature isn't
removed. removed.
If a unknown feature is found in a directive, it results in a compiler error. If an unknown feature is found in a directive, it results in a compiler error.
An unknown feature is one which has never been recognized by the compiler. An unknown feature is one which has never been recognized by the compiler.
# Statements and expressions # Statements and expressions
@ -2685,7 +2685,7 @@ When an lvalue is evaluated in an _lvalue context_, it denotes a memory
location; when evaluated in an _rvalue context_, it denotes the value held _in_ location; when evaluated in an _rvalue context_, it denotes the value held _in_
that memory location. that memory location.
When an rvalue is used in lvalue context, a temporary un-named lvalue is When an rvalue is used in an lvalue context, a temporary un-named lvalue is
created and used instead. A temporary's lifetime equals the largest lifetime created and used instead. A temporary's lifetime equals the largest lifetime
of any reference that points to it. of any reference that points to it.
@ -2833,7 +2833,7 @@ foo().x;
``` ```
A field access is an [lvalue](#lvalues,-rvalues-and-temporaries) referring to A field access is an [lvalue](#lvalues,-rvalues-and-temporaries) referring to
the value of that field. When the type providing the field inherits mutabilty, the value of that field. When the type providing the field inherits mutability,
it can be [assigned](#assignment-expressions) to. it can be [assigned](#assignment-expressions) to.
Also, if the type of the expression to the left of the dot is a pointer, it is Also, if the type of the expression to the left of the dot is a pointer, it is
@ -3108,11 +3108,10 @@ then the expression completes.
Some examples of call expressions: Some examples of call expressions:
``` ```
# use std::from_str::FromStr;
# fn add(x: int, y: int) -> int { 0 } # fn add(x: int, y: int) -> int { 0 }
let x: int = add(1, 2); let x: int = add(1, 2);
let pi: Option<f32> = FromStr::from_str("3.14"); let pi: Option<f32> = from_str("3.14");
``` ```
### Lambda expressions ### Lambda expressions
@ -3321,7 +3320,7 @@ between `_` and `..` is that the pattern `C(_)` is only type-correct if `C` has
exactly one argument, while the pattern `C(..)` is type-correct for any enum exactly one argument, while the pattern `C(..)` is type-correct for any enum
variant `C`, regardless of how many arguments `C` has. variant `C`, regardless of how many arguments `C` has.
Used inside a array pattern, `..` stands for any number of elements, when the Used inside an array pattern, `..` stands for any number of elements, when the
`advanced_slice_patterns` feature gate is turned on. This wildcard can be used `advanced_slice_patterns` feature gate is turned on. This wildcard can be used
at most once for a given array, which implies that it cannot be used to at most once for a given array, which implies that it cannot be used to
specifically match elements that are at an unknown distance from both ends of a specifically match elements that are at an unknown distance from both ends of a
@ -3584,7 +3583,7 @@ is not a surrogate), represented as a 32-bit unsigned word in the 0x0000 to
0xD7FF or 0xE000 to 0x10FFFF range. A `[char]` array is effectively an UCS-4 / 0xD7FF or 0xE000 to 0x10FFFF range. A `[char]` array is effectively an UCS-4 /
UTF-32 string. UTF-32 string.
A value of type `str` is a Unicode string, represented as a array of 8-bit A value of type `str` is a Unicode string, represented as an array of 8-bit
unsigned bytes holding a sequence of UTF-8 codepoints. Since `str` is of unsigned bytes holding a sequence of UTF-8 codepoints. Since `str` is of
unknown size, it is not a _first class_ type, but can only be instantiated unknown size, it is not a _first class_ type, but can only be instantiated
through a pointer type, such as `&str` or `String`. through a pointer type, such as `&str` or `String`.

View file

@ -75,7 +75,11 @@ def full_snapshot_name(date, rev, platform, hsh):
def get_kernel(triple): def get_kernel(triple):
os_name = triple.split('-')[2] t = triple.split('-')
if len(t) == 2:
os_name = t[1]
else:
os_name = t[2]
if os_name == "windows": if os_name == "windows":
return "winnt" return "winnt"
if os_name == "darwin": if os_name == "darwin":

View file

@ -105,7 +105,7 @@ syn keyword rustTrait RawPtr
syn keyword rustTrait Buffer Writer Reader Seek syn keyword rustTrait Buffer Writer Reader Seek
syn keyword rustTrait Str StrVector StrSlice syn keyword rustTrait Str StrVector StrSlice
syn keyword rustTrait IntoMaybeOwned StrAllocating UnicodeStrSlice syn keyword rustTrait IntoMaybeOwned StrAllocating UnicodeStrSlice
syn keyword rustTrait ToString IntoStr syn keyword rustTrait ToString IntoString
syn keyword rustTrait Tuple1 Tuple2 Tuple3 Tuple4 syn keyword rustTrait Tuple1 Tuple2 Tuple3 Tuple4
syn keyword rustTrait Tuple5 Tuple6 Tuple7 Tuple8 syn keyword rustTrait Tuple5 Tuple6 Tuple7 Tuple8
syn keyword rustTrait Tuple9 Tuple10 Tuple11 Tuple12 syn keyword rustTrait Tuple9 Tuple10 Tuple11 Tuple12

View file

@ -179,9 +179,9 @@ pub struct Rc<T> {
_noshare: marker::NoSync _noshare: marker::NoSync
} }
#[stable]
impl<T> Rc<T> { impl<T> Rc<T> {
/// Constructs a new reference-counted pointer. /// Constructs a new reference-counted pointer.
#[stable]
pub fn new(value: T) -> Rc<T> { pub fn new(value: T) -> Rc<T> {
unsafe { unsafe {
Rc { Rc {
@ -200,9 +200,7 @@ impl<T> Rc<T> {
} }
} }
} }
}
impl<T> Rc<T> {
/// Downgrades the reference-counted pointer to a weak reference. /// Downgrades the reference-counted pointer to a weak reference.
#[experimental = "Weak pointers may not belong in this module"] #[experimental = "Weak pointers may not belong in this module"]
pub fn downgrade(&self) -> Weak<T> { pub fn downgrade(&self) -> Weak<T> {

View file

@ -73,6 +73,7 @@ pub use core::str::{CharSplitsN, AnyLines, MatchIndices, StrSplits};
pub use core::str::{Utf16CodeUnits, eq_slice, is_utf8, is_utf16, Utf16Items}; pub use core::str::{Utf16CodeUnits, eq_slice, is_utf8, is_utf16, Utf16Items};
pub use core::str::{Utf16Item, ScalarValue, LoneSurrogate, utf16_items}; pub use core::str::{Utf16Item, ScalarValue, LoneSurrogate, utf16_items};
pub use core::str::{truncate_utf16_at_nul, utf8_char_width, CharRange}; pub use core::str::{truncate_utf16_at_nul, utf8_char_width, CharRange};
pub use core::str::{FromStr, from_str};
pub use core::str::{Str, StrPrelude}; pub use core::str::{Str, StrPrelude};
pub use unicode::str::{UnicodeStrPrelude, Words, Graphemes, GraphemeIndices}; pub use unicode::str::{UnicodeStrPrelude, Words, Graphemes, GraphemeIndices};

View file

@ -25,7 +25,7 @@ use core::raw::Slice as RawSlice;
use hash; use hash;
use slice::CloneSliceAllocPrelude; use slice::CloneSliceAllocPrelude;
use str; use str;
use str::{CharRange, StrAllocating, MaybeOwned, Owned}; use str::{CharRange, FromStr, StrAllocating, MaybeOwned, Owned};
use str::Slice as MaybeOwnedSlice; // So many `Slice`s... use str::Slice as MaybeOwnedSlice; // So many `Slice`s...
use vec::{DerefVec, Vec, as_vec}; use vec::{DerefVec, Vec, as_vec};
@ -795,6 +795,33 @@ pub fn as_string<'a>(x: &'a str) -> DerefString<'a> {
DerefString { x: as_vec(x.as_bytes()) } DerefString { x: as_vec(x.as_bytes()) }
} }
impl FromStr for String {
#[inline]
fn from_str(s: &str) -> Option<String> {
Some(String::from_str(s))
}
}
/// Trait for converting a type to a string, consuming it in the process.
pub trait IntoString {
/// Consume and convert to a string.
fn into_string(self) -> String;
}
/// A generic trait for converting a value to a string
pub trait ToString {
/// Converts the value of `self` to an owned string
fn to_string(&self) -> String;
}
impl<T: fmt::Show> ToString for T {
fn to_string(&self) -> String {
let mut buf = Vec::<u8>::new();
let _ = format_args!(|args| fmt::write(&mut buf, args), "{}", self);
String::from_utf8(buf).unwrap()
}
}
/// Unsafe operations /// Unsafe operations
#[unstable = "waiting on raw module conventions"] #[unstable = "waiting on raw module conventions"]
pub mod raw { pub mod raw {
@ -860,7 +887,7 @@ mod tests {
use str; use str;
use str::{Str, StrPrelude, Owned}; use str::{Str, StrPrelude, Owned};
use super::{as_string, String}; use super::{as_string, String, ToString};
use vec::Vec; use vec::Vec;
use slice::CloneSliceAllocPrelude; use slice::CloneSliceAllocPrelude;
@ -1164,6 +1191,28 @@ mod tests {
assert_eq!("oob", s[1..4]); assert_eq!("oob", s[1..4]);
} }
#[test]
fn test_simple_types() {
assert_eq!(1i.to_string(), "1".to_string());
assert_eq!((-1i).to_string(), "-1".to_string());
assert_eq!(200u.to_string(), "200".to_string());
assert_eq!(2u8.to_string(), "2".to_string());
assert_eq!(true.to_string(), "true".to_string());
assert_eq!(false.to_string(), "false".to_string());
assert_eq!(().to_string(), "()".to_string());
assert_eq!(("hi".to_string()).to_string(), "hi".to_string());
}
#[test]
fn test_vectors() {
let x: Vec<int> = vec![];
assert_eq!(x.to_string(), "[]".to_string());
assert_eq!((vec![1i]).to_string(), "[1]".to_string());
assert_eq!((vec![1i, 2, 3]).to_string(), "[1, 2, 3]".to_string());
assert!((vec![vec![], vec![1i], vec![1i, 1]]).to_string() ==
"[[], [1], [1, 1]]".to_string());
}
#[bench] #[bench]
fn bench_with_capacity(b: &mut Bencher) { fn bench_with_capacity(b: &mut Bencher) {
b.iter(|| { b.iter(|| {

View file

@ -504,9 +504,9 @@ impl<T: Ord> TreeSet<T> {
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use std::collections::BTreeSet; /// use std::collections::TreeSet;
/// ///
/// let mut set = BTreeSet::new(); /// let mut set = TreeSet::new();
/// ///
/// assert_eq!(set.insert(2i), true); /// assert_eq!(set.insert(2i), true);
/// assert_eq!(set.insert(2i), false); /// assert_eq!(set.insert(2i), false);
@ -522,9 +522,9 @@ impl<T: Ord> TreeSet<T> {
/// # Example /// # Example
/// ///
/// ``` /// ```
/// use std::collections::BTreeSet; /// use std::collections::TreeSet;
/// ///
/// let mut set = BTreeSet::new(); /// let mut set = TreeSet::new();
/// ///
/// set.insert(2i); /// set.insert(2i);
/// assert_eq!(set.remove(&2), true); /// assert_eq!(set.remove(&2), true);

View file

@ -645,7 +645,6 @@ impl<T> Vec<T> {
/// assert!(vec.capacity() >= 3); /// assert!(vec.capacity() >= 3);
/// ``` /// ```
#[stable] #[stable]
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn shrink_to_fit(&mut self) { pub fn shrink_to_fit(&mut self) {
if mem::size_of::<T>() == 0 { return } if mem::size_of::<T>() == 0 { return }
@ -1653,6 +1652,13 @@ impl<T> Vec<T> {
} }
} }
impl<'a> fmt::FormatWriter for Vec<u8> {
fn write(&mut self, buf: &[u8]) -> fmt::Result {
self.push_all(buf);
Ok(())
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
extern crate test; extern crate test;

View file

@ -88,6 +88,7 @@ use intrinsics::TypeId;
#[stable] #[stable]
pub trait Any: 'static { pub trait Any: 'static {
/// Get the `TypeId` of `self` /// Get the `TypeId` of `self`
#[stable]
fn get_type_id(&self) -> TypeId; fn get_type_id(&self) -> TypeId;
} }
@ -117,7 +118,6 @@ pub trait AnyRefExt<'a> {
#[stable] #[stable]
impl<'a> AnyRefExt<'a> for &'a Any { impl<'a> AnyRefExt<'a> for &'a Any {
#[inline] #[inline]
#[stable]
fn is<T: 'static>(self) -> bool { fn is<T: 'static>(self) -> bool {
// Get TypeId of the type this function is instantiated with // Get TypeId of the type this function is instantiated with
let t = TypeId::of::<T>(); let t = TypeId::of::<T>();
@ -130,7 +130,6 @@ impl<'a> AnyRefExt<'a> for &'a Any {
} }
#[inline] #[inline]
#[unstable = "naming conventions around acquiring references may change"]
fn downcast_ref<T: 'static>(self) -> Option<&'a T> { fn downcast_ref<T: 'static>(self) -> Option<&'a T> {
if self.is::<T>() { if self.is::<T>() {
unsafe { unsafe {
@ -159,7 +158,6 @@ pub trait AnyMutRefExt<'a> {
#[stable] #[stable]
impl<'a> AnyMutRefExt<'a> for &'a mut Any { impl<'a> AnyMutRefExt<'a> for &'a mut Any {
#[inline] #[inline]
#[unstable = "naming conventions around acquiring references may change"]
fn downcast_mut<T: 'static>(self) -> Option<&'a mut T> { fn downcast_mut<T: 'static>(self) -> Option<&'a mut T> {
if self.is::<T>() { if self.is::<T>() {
unsafe { unsafe {

View file

@ -58,20 +58,25 @@ pub struct AtomicPtr<T> {
#[stable] #[stable]
pub enum Ordering { pub enum Ordering {
/// No ordering constraints, only atomic operations /// No ordering constraints, only atomic operations
#[stable]
Relaxed, Relaxed,
/// When coupled with a store, all previous writes become visible /// When coupled with a store, all previous writes become visible
/// to another thread that performs a load with `Acquire` ordering /// to another thread that performs a load with `Acquire` ordering
/// on the same value /// on the same value
#[stable]
Release, Release,
/// When coupled with a load, all subsequent loads will see data /// When coupled with a load, all subsequent loads will see data
/// written before a store with `Release` ordering on the same value /// written before a store with `Release` ordering on the same value
/// in another thread /// in another thread
#[stable]
Acquire, Acquire,
/// When coupled with a load, uses `Acquire` ordering, and with a store /// When coupled with a load, uses `Acquire` ordering, and with a store
/// `Release` ordering /// `Release` ordering
#[stable]
AcqRel, AcqRel,
/// Like `AcqRel` with the additional guarantee that all threads see all /// Like `AcqRel` with the additional guarantee that all threads see all
/// sequentially consistent operations in the same order. /// sequentially consistent operations in the same order.
#[stable]
SeqCst SeqCst
} }
@ -91,10 +96,10 @@ pub const INIT_ATOMIC_UINT: AtomicUint =
// NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly // NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly
const UINT_TRUE: uint = -1; const UINT_TRUE: uint = -1;
#[stable]
impl AtomicBool { impl AtomicBool {
/// Create a new `AtomicBool` /// Create a new `AtomicBool`
#[inline] #[inline]
#[stable]
pub fn new(v: bool) -> AtomicBool { pub fn new(v: bool) -> AtomicBool {
let val = if v { UINT_TRUE } else { 0 }; let val = if v { UINT_TRUE } else { 0 };
AtomicBool { v: UnsafeCell::new(val), nocopy: marker::NoCopy } AtomicBool { v: UnsafeCell::new(val), nocopy: marker::NoCopy }
@ -106,6 +111,7 @@ impl AtomicBool {
/// ///
/// Panics if `order` is `Release` or `AcqRel`. /// Panics if `order` is `Release` or `AcqRel`.
#[inline] #[inline]
#[stable]
pub fn load(&self, order: Ordering) -> bool { pub fn load(&self, order: Ordering) -> bool {
unsafe { atomic_load(self.v.get() as *const uint, order) > 0 } unsafe { atomic_load(self.v.get() as *const uint, order) > 0 }
} }
@ -116,6 +122,7 @@ impl AtomicBool {
/// ///
/// Panics if `order` is `Acquire` or `AcqRel`. /// Panics if `order` is `Acquire` or `AcqRel`.
#[inline] #[inline]
#[stable]
pub fn store(&self, val: bool, order: Ordering) { pub fn store(&self, val: bool, order: Ordering) {
let val = if val { UINT_TRUE } else { 0 }; let val = if val { UINT_TRUE } else { 0 };
@ -124,6 +131,7 @@ impl AtomicBool {
/// Store a value, returning the old value /// Store a value, returning the old value
#[inline] #[inline]
#[stable]
pub fn swap(&self, val: bool, order: Ordering) -> bool { pub fn swap(&self, val: bool, order: Ordering) -> bool {
let val = if val { UINT_TRUE } else { 0 }; let val = if val { UINT_TRUE } else { 0 };
@ -174,6 +182,7 @@ impl AtomicBool {
/// } /// }
/// ``` /// ```
#[inline] #[inline]
#[stable]
pub fn compare_and_swap(&self, old: bool, new: bool, order: Ordering) -> bool { pub fn compare_and_swap(&self, old: bool, new: bool, order: Ordering) -> bool {
let old = if old { UINT_TRUE } else { 0 }; let old = if old { UINT_TRUE } else { 0 };
let new = if new { UINT_TRUE } else { 0 }; let new = if new { UINT_TRUE } else { 0 };
@ -205,6 +214,7 @@ impl AtomicBool {
/// assert_eq!(false, foo.load(SeqCst)); /// assert_eq!(false, foo.load(SeqCst));
/// ``` /// ```
#[inline] #[inline]
#[stable]
pub fn fetch_and(&self, val: bool, order: Ordering) -> bool { pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
let val = if val { UINT_TRUE } else { 0 }; let val = if val { UINT_TRUE } else { 0 };
@ -236,6 +246,7 @@ impl AtomicBool {
/// assert_eq!(true, foo.load(SeqCst)); /// assert_eq!(true, foo.load(SeqCst));
/// ``` /// ```
#[inline] #[inline]
#[stable]
pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool { pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool {
let val = if val { UINT_TRUE } else { 0 }; let val = if val { UINT_TRUE } else { 0 };
@ -266,6 +277,7 @@ impl AtomicBool {
/// assert_eq!(false, foo.load(SeqCst)); /// assert_eq!(false, foo.load(SeqCst));
/// ``` /// ```
#[inline] #[inline]
#[stable]
pub fn fetch_or(&self, val: bool, order: Ordering) -> bool { pub fn fetch_or(&self, val: bool, order: Ordering) -> bool {
let val = if val { UINT_TRUE } else { 0 }; let val = if val { UINT_TRUE } else { 0 };
@ -296,6 +308,7 @@ impl AtomicBool {
/// assert_eq!(false, foo.load(SeqCst)); /// assert_eq!(false, foo.load(SeqCst));
/// ``` /// ```
#[inline] #[inline]
#[stable]
pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool { pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
let val = if val { UINT_TRUE } else { 0 }; let val = if val { UINT_TRUE } else { 0 };
@ -303,10 +316,10 @@ impl AtomicBool {
} }
} }
#[stable]
impl AtomicInt { impl AtomicInt {
/// Create a new `AtomicInt` /// Create a new `AtomicInt`
#[inline] #[inline]
#[stable]
pub fn new(v: int) -> AtomicInt { pub fn new(v: int) -> AtomicInt {
AtomicInt {v: UnsafeCell::new(v), nocopy: marker::NoCopy} AtomicInt {v: UnsafeCell::new(v), nocopy: marker::NoCopy}
} }
@ -317,6 +330,7 @@ impl AtomicInt {
/// ///
/// Panics if `order` is `Release` or `AcqRel`. /// Panics if `order` is `Release` or `AcqRel`.
#[inline] #[inline]
#[stable]
pub fn load(&self, order: Ordering) -> int { pub fn load(&self, order: Ordering) -> int {
unsafe { atomic_load(self.v.get() as *const int, order) } unsafe { atomic_load(self.v.get() as *const int, order) }
} }
@ -327,12 +341,14 @@ impl AtomicInt {
/// ///
/// Panics if `order` is `Acquire` or `AcqRel`. /// Panics if `order` is `Acquire` or `AcqRel`.
#[inline] #[inline]
#[stable]
pub fn store(&self, val: int, order: Ordering) { pub fn store(&self, val: int, order: Ordering) {
unsafe { atomic_store(self.v.get(), val, order); } unsafe { atomic_store(self.v.get(), val, order); }
} }
/// Store a value, returning the old value /// Store a value, returning the old value
#[inline] #[inline]
#[stable]
pub fn swap(&self, val: int, order: Ordering) -> int { pub fn swap(&self, val: int, order: Ordering) -> int {
unsafe { atomic_swap(self.v.get(), val, order) } unsafe { atomic_swap(self.v.get(), val, order) }
} }
@ -343,6 +359,7 @@ impl AtomicInt {
/// replace the current value with `new`. Return the previous value. /// replace the current value with `new`. Return the previous value.
/// If the return value is equal to `old` then the value was updated. /// If the return value is equal to `old` then the value was updated.
#[inline] #[inline]
#[stable]
pub fn compare_and_swap(&self, old: int, new: int, order: Ordering) -> int { pub fn compare_and_swap(&self, old: int, new: int, order: Ordering) -> int {
unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) } unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
} }
@ -359,6 +376,7 @@ impl AtomicInt {
/// assert_eq!(10, foo.load(SeqCst)); /// assert_eq!(10, foo.load(SeqCst));
/// ``` /// ```
#[inline] #[inline]
#[stable]
pub fn fetch_add(&self, val: int, order: Ordering) -> int { pub fn fetch_add(&self, val: int, order: Ordering) -> int {
unsafe { atomic_add(self.v.get(), val, order) } unsafe { atomic_add(self.v.get(), val, order) }
} }
@ -375,6 +393,7 @@ impl AtomicInt {
/// assert_eq!(-10, foo.load(SeqCst)); /// assert_eq!(-10, foo.load(SeqCst));
/// ``` /// ```
#[inline] #[inline]
#[stable]
pub fn fetch_sub(&self, val: int, order: Ordering) -> int { pub fn fetch_sub(&self, val: int, order: Ordering) -> int {
unsafe { atomic_sub(self.v.get(), val, order) } unsafe { atomic_sub(self.v.get(), val, order) }
} }
@ -390,6 +409,7 @@ impl AtomicInt {
/// assert_eq!(0b101101, foo.fetch_and(0b110011, SeqCst)); /// assert_eq!(0b101101, foo.fetch_and(0b110011, SeqCst));
/// assert_eq!(0b100001, foo.load(SeqCst)); /// assert_eq!(0b100001, foo.load(SeqCst));
#[inline] #[inline]
#[stable]
pub fn fetch_and(&self, val: int, order: Ordering) -> int { pub fn fetch_and(&self, val: int, order: Ordering) -> int {
unsafe { atomic_and(self.v.get(), val, order) } unsafe { atomic_and(self.v.get(), val, order) }
} }
@ -405,6 +425,7 @@ impl AtomicInt {
/// assert_eq!(0b101101, foo.fetch_or(0b110011, SeqCst)); /// assert_eq!(0b101101, foo.fetch_or(0b110011, SeqCst));
/// assert_eq!(0b111111, foo.load(SeqCst)); /// assert_eq!(0b111111, foo.load(SeqCst));
#[inline] #[inline]
#[stable]
pub fn fetch_or(&self, val: int, order: Ordering) -> int { pub fn fetch_or(&self, val: int, order: Ordering) -> int {
unsafe { atomic_or(self.v.get(), val, order) } unsafe { atomic_or(self.v.get(), val, order) }
} }
@ -420,15 +441,16 @@ impl AtomicInt {
/// assert_eq!(0b101101, foo.fetch_xor(0b110011, SeqCst)); /// assert_eq!(0b101101, foo.fetch_xor(0b110011, SeqCst));
/// assert_eq!(0b011110, foo.load(SeqCst)); /// assert_eq!(0b011110, foo.load(SeqCst));
#[inline] #[inline]
#[stable]
pub fn fetch_xor(&self, val: int, order: Ordering) -> int { pub fn fetch_xor(&self, val: int, order: Ordering) -> int {
unsafe { atomic_xor(self.v.get(), val, order) } unsafe { atomic_xor(self.v.get(), val, order) }
} }
} }
#[stable]
impl AtomicUint { impl AtomicUint {
/// Create a new `AtomicUint` /// Create a new `AtomicUint`
#[inline] #[inline]
#[stable]
pub fn new(v: uint) -> AtomicUint { pub fn new(v: uint) -> AtomicUint {
AtomicUint { v: UnsafeCell::new(v), nocopy: marker::NoCopy } AtomicUint { v: UnsafeCell::new(v), nocopy: marker::NoCopy }
} }
@ -439,6 +461,7 @@ impl AtomicUint {
/// ///
/// Panics if `order` is `Release` or `AcqRel`. /// Panics if `order` is `Release` or `AcqRel`.
#[inline] #[inline]
#[stable]
pub fn load(&self, order: Ordering) -> uint { pub fn load(&self, order: Ordering) -> uint {
unsafe { atomic_load(self.v.get() as *const uint, order) } unsafe { atomic_load(self.v.get() as *const uint, order) }
} }
@ -449,12 +472,14 @@ impl AtomicUint {
/// ///
/// Panics if `order` is `Acquire` or `AcqRel`. /// Panics if `order` is `Acquire` or `AcqRel`.
#[inline] #[inline]
#[stable]
pub fn store(&self, val: uint, order: Ordering) { pub fn store(&self, val: uint, order: Ordering) {
unsafe { atomic_store(self.v.get(), val, order); } unsafe { atomic_store(self.v.get(), val, order); }
} }
/// Store a value, returning the old value /// Store a value, returning the old value
#[inline] #[inline]
#[stable]
pub fn swap(&self, val: uint, order: Ordering) -> uint { pub fn swap(&self, val: uint, order: Ordering) -> uint {
unsafe { atomic_swap(self.v.get(), val, order) } unsafe { atomic_swap(self.v.get(), val, order) }
} }
@ -465,6 +490,7 @@ impl AtomicUint {
/// replace the current value with `new`. Return the previous value. /// replace the current value with `new`. Return the previous value.
/// If the return value is equal to `old` then the value was updated. /// If the return value is equal to `old` then the value was updated.
#[inline] #[inline]
#[stable]
pub fn compare_and_swap(&self, old: uint, new: uint, order: Ordering) -> uint { pub fn compare_and_swap(&self, old: uint, new: uint, order: Ordering) -> uint {
unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) } unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
} }
@ -481,6 +507,7 @@ impl AtomicUint {
/// assert_eq!(10, foo.load(SeqCst)); /// assert_eq!(10, foo.load(SeqCst));
/// ``` /// ```
#[inline] #[inline]
#[stable]
pub fn fetch_add(&self, val: uint, order: Ordering) -> uint { pub fn fetch_add(&self, val: uint, order: Ordering) -> uint {
unsafe { atomic_add(self.v.get(), val, order) } unsafe { atomic_add(self.v.get(), val, order) }
} }
@ -497,6 +524,7 @@ impl AtomicUint {
/// assert_eq!(0, foo.load(SeqCst)); /// assert_eq!(0, foo.load(SeqCst));
/// ``` /// ```
#[inline] #[inline]
#[stable]
pub fn fetch_sub(&self, val: uint, order: Ordering) -> uint { pub fn fetch_sub(&self, val: uint, order: Ordering) -> uint {
unsafe { atomic_sub(self.v.get(), val, order) } unsafe { atomic_sub(self.v.get(), val, order) }
} }
@ -512,6 +540,7 @@ impl AtomicUint {
/// assert_eq!(0b101101, foo.fetch_and(0b110011, SeqCst)); /// assert_eq!(0b101101, foo.fetch_and(0b110011, SeqCst));
/// assert_eq!(0b100001, foo.load(SeqCst)); /// assert_eq!(0b100001, foo.load(SeqCst));
#[inline] #[inline]
#[stable]
pub fn fetch_and(&self, val: uint, order: Ordering) -> uint { pub fn fetch_and(&self, val: uint, order: Ordering) -> uint {
unsafe { atomic_and(self.v.get(), val, order) } unsafe { atomic_and(self.v.get(), val, order) }
} }
@ -527,6 +556,7 @@ impl AtomicUint {
/// assert_eq!(0b101101, foo.fetch_or(0b110011, SeqCst)); /// assert_eq!(0b101101, foo.fetch_or(0b110011, SeqCst));
/// assert_eq!(0b111111, foo.load(SeqCst)); /// assert_eq!(0b111111, foo.load(SeqCst));
#[inline] #[inline]
#[stable]
pub fn fetch_or(&self, val: uint, order: Ordering) -> uint { pub fn fetch_or(&self, val: uint, order: Ordering) -> uint {
unsafe { atomic_or(self.v.get(), val, order) } unsafe { atomic_or(self.v.get(), val, order) }
} }
@ -542,15 +572,16 @@ impl AtomicUint {
/// assert_eq!(0b101101, foo.fetch_xor(0b110011, SeqCst)); /// assert_eq!(0b101101, foo.fetch_xor(0b110011, SeqCst));
/// assert_eq!(0b011110, foo.load(SeqCst)); /// assert_eq!(0b011110, foo.load(SeqCst));
#[inline] #[inline]
#[stable]
pub fn fetch_xor(&self, val: uint, order: Ordering) -> uint { pub fn fetch_xor(&self, val: uint, order: Ordering) -> uint {
unsafe { atomic_xor(self.v.get(), val, order) } unsafe { atomic_xor(self.v.get(), val, order) }
} }
} }
#[stable]
impl<T> AtomicPtr<T> { impl<T> AtomicPtr<T> {
/// Create a new `AtomicPtr` /// Create a new `AtomicPtr`
#[inline] #[inline]
#[stable]
pub fn new(p: *mut T) -> AtomicPtr<T> { pub fn new(p: *mut T) -> AtomicPtr<T> {
AtomicPtr { p: UnsafeCell::new(p as uint), nocopy: marker::NoCopy } AtomicPtr { p: UnsafeCell::new(p as uint), nocopy: marker::NoCopy }
} }
@ -561,6 +592,7 @@ impl<T> AtomicPtr<T> {
/// ///
/// Panics if `order` is `Release` or `AcqRel`. /// Panics if `order` is `Release` or `AcqRel`.
#[inline] #[inline]
#[stable]
pub fn load(&self, order: Ordering) -> *mut T { pub fn load(&self, order: Ordering) -> *mut T {
unsafe { unsafe {
atomic_load(self.p.get() as *const *mut T, order) as *mut T atomic_load(self.p.get() as *const *mut T, order) as *mut T
@ -573,12 +605,14 @@ impl<T> AtomicPtr<T> {
/// ///
/// Panics if `order` is `Acquire` or `AcqRel`. /// Panics if `order` is `Acquire` or `AcqRel`.
#[inline] #[inline]
#[stable]
pub fn store(&self, ptr: *mut T, order: Ordering) { pub fn store(&self, ptr: *mut T, order: Ordering) {
unsafe { atomic_store(self.p.get(), ptr as uint, order); } unsafe { atomic_store(self.p.get(), ptr as uint, order); }
} }
/// Store a value, returning the old value /// Store a value, returning the old value
#[inline] #[inline]
#[stable]
pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
unsafe { atomic_swap(self.p.get(), ptr as uint, order) as *mut T } unsafe { atomic_swap(self.p.get(), ptr as uint, order) as *mut T }
} }
@ -589,6 +623,7 @@ impl<T> AtomicPtr<T> {
/// replace the current value with `new`. Return the previous value. /// replace the current value with `new`. Return the previous value.
/// If the return value is equal to `old` then the value was updated. /// If the return value is equal to `old` then the value was updated.
#[inline] #[inline]
#[stable]
pub fn compare_and_swap(&self, old: *mut T, new: *mut T, order: Ordering) -> *mut T { pub fn compare_and_swap(&self, old: *mut T, new: *mut T, order: Ordering) -> *mut T {
unsafe { unsafe {
atomic_compare_and_swap(self.p.get(), old as uint, atomic_compare_and_swap(self.p.get(), old as uint,
@ -609,6 +644,7 @@ unsafe fn atomic_store<T>(dst: *mut T, val: T, order:Ordering) {
} }
#[inline] #[inline]
#[stable]
unsafe fn atomic_load<T>(dst: *const T, order:Ordering) -> T { unsafe fn atomic_load<T>(dst: *const T, order:Ordering) -> T {
match order { match order {
Acquire => intrinsics::atomic_load_acq(dst), Acquire => intrinsics::atomic_load_acq(dst),
@ -620,6 +656,7 @@ unsafe fn atomic_load<T>(dst: *const T, order:Ordering) -> T {
} }
#[inline] #[inline]
#[stable]
unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T { unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order { match order {
Acquire => intrinsics::atomic_xchg_acq(dst, val), Acquire => intrinsics::atomic_xchg_acq(dst, val),
@ -632,6 +669,7 @@ unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
/// Returns the old value (like __sync_fetch_and_add). /// Returns the old value (like __sync_fetch_and_add).
#[inline] #[inline]
#[stable]
unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T { unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order { match order {
Acquire => intrinsics::atomic_xadd_acq(dst, val), Acquire => intrinsics::atomic_xadd_acq(dst, val),
@ -644,6 +682,7 @@ unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
/// Returns the old value (like __sync_fetch_and_sub). /// Returns the old value (like __sync_fetch_and_sub).
#[inline] #[inline]
#[stable]
unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T { unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order { match order {
Acquire => intrinsics::atomic_xsub_acq(dst, val), Acquire => intrinsics::atomic_xsub_acq(dst, val),
@ -655,6 +694,7 @@ unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
} }
#[inline] #[inline]
#[stable]
unsafe fn atomic_compare_and_swap<T>(dst: *mut T, old:T, new:T, order: Ordering) -> T { unsafe fn atomic_compare_and_swap<T>(dst: *mut T, old:T, new:T, order: Ordering) -> T {
match order { match order {
Acquire => intrinsics::atomic_cxchg_acq(dst, old, new), Acquire => intrinsics::atomic_cxchg_acq(dst, old, new),
@ -666,6 +706,7 @@ unsafe fn atomic_compare_and_swap<T>(dst: *mut T, old:T, new:T, order: Ordering)
} }
#[inline] #[inline]
#[stable]
unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T { unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order { match order {
Acquire => intrinsics::atomic_and_acq(dst, val), Acquire => intrinsics::atomic_and_acq(dst, val),
@ -677,6 +718,7 @@ unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
} }
#[inline] #[inline]
#[stable]
unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T { unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order { match order {
Acquire => intrinsics::atomic_nand_acq(dst, val), Acquire => intrinsics::atomic_nand_acq(dst, val),
@ -689,6 +731,7 @@ unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
#[inline] #[inline]
#[stable]
unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T { unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order { match order {
Acquire => intrinsics::atomic_or_acq(dst, val), Acquire => intrinsics::atomic_or_acq(dst, val),
@ -701,6 +744,7 @@ unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
#[inline] #[inline]
#[stable]
unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T { unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order { match order {
Acquire => intrinsics::atomic_xor_acq(dst, val), Acquire => intrinsics::atomic_xor_acq(dst, val),

View file

@ -157,6 +157,7 @@
use clone::Clone; use clone::Clone;
use cmp::PartialEq; use cmp::PartialEq;
use default::Default;
use kinds::{marker, Copy}; use kinds::{marker, Copy};
use ops::{Deref, DerefMut, Drop}; use ops::{Deref, DerefMut, Drop};
use option::{None, Option, Some}; use option::{None, Option, Some};
@ -168,9 +169,9 @@ pub struct Cell<T> {
noshare: marker::NoSync, noshare: marker::NoSync,
} }
#[stable]
impl<T:Copy> Cell<T> { impl<T:Copy> Cell<T> {
/// Creates a new `Cell` containing the given value. /// Creates a new `Cell` containing the given value.
#[stable]
pub fn new(value: T) -> Cell<T> { pub fn new(value: T) -> Cell<T> {
Cell { Cell {
value: UnsafeCell::new(value), value: UnsafeCell::new(value),
@ -180,12 +181,14 @@ impl<T:Copy> Cell<T> {
/// Returns a copy of the contained value. /// Returns a copy of the contained value.
#[inline] #[inline]
#[stable]
pub fn get(&self) -> T { pub fn get(&self) -> T {
unsafe{ *self.value.get() } unsafe{ *self.value.get() }
} }
/// Sets the contained value. /// Sets the contained value.
#[inline] #[inline]
#[stable]
pub fn set(&self, value: T) { pub fn set(&self, value: T) {
unsafe { unsafe {
*self.value.get() = value; *self.value.get() = value;
@ -211,6 +214,13 @@ impl<T:Copy> Clone for Cell<T> {
} }
} }
#[unstable]
impl<T:Default + Copy> Default for Cell<T> {
fn default() -> Cell<T> {
Cell::new(Default::default())
}
}
#[unstable = "waiting for `PartialEq` trait to become stable"] #[unstable = "waiting for `PartialEq` trait to become stable"]
impl<T:PartialEq + Copy> PartialEq for Cell<T> { impl<T:PartialEq + Copy> PartialEq for Cell<T> {
fn eq(&self, other: &Cell<T>) -> bool { fn eq(&self, other: &Cell<T>) -> bool {
@ -337,6 +347,13 @@ impl<T: Clone> Clone for RefCell<T> {
} }
} }
#[unstable]
impl<T:Default> Default for RefCell<T> {
fn default() -> RefCell<T> {
RefCell::new(Default::default())
}
}
#[unstable = "waiting for `PartialEq` to become stable"] #[unstable = "waiting for `PartialEq` to become stable"]
impl<T: PartialEq> PartialEq for RefCell<T> { impl<T: PartialEq> PartialEq for RefCell<T> {
fn eq(&self, other: &RefCell<T>) -> bool { fn eq(&self, other: &RefCell<T>) -> bool {

View file

@ -16,8 +16,8 @@
use intrinsics; use intrinsics;
use mem; use mem;
use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN}; use num::{Float, FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN};
use num::Float; use num::from_str_radix;
use option::Option; use option::Option;
pub const RADIX: uint = 2u; pub const RADIX: uint = 2u;
@ -424,3 +424,10 @@ impl Float for f32 {
self * (value / 180.0f32) self * (value / 180.0f32)
} }
} }
#[inline]
#[allow(missing_docs)]
#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"]
pub fn from_str_hex(src: &str) -> Option<f32> {
from_str_radix(src, 16)
}

View file

@ -16,8 +16,8 @@
use intrinsics; use intrinsics;
use mem; use mem;
use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN}; use num::{Float, FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN};
use num::Float; use num::from_str_radix;
use option::Option; use option::Option;
// FIXME(#5527): These constants should be deprecated once associated // FIXME(#5527): These constants should be deprecated once associated
@ -430,3 +430,10 @@ impl Float for f64 {
self * (value / 180.0) self * (value / 180.0)
} }
} }
#[inline]
#[allow(missing_docs)]
#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"]
pub fn from_str_hex(src: &str) -> Option<f64> {
from_str_radix(src, 16)
}

View file

@ -14,18 +14,21 @@
#![allow(missing_docs)] #![allow(missing_docs)]
use intrinsics;
use {int, i8, i16, i32, i64}; use {int, i8, i16, i32, i64};
use {uint, u8, u16, u32, u64}; use {uint, u8, u16, u32, u64};
use {f32, f64}; use {f32, f64};
use char::Char;
use clone::Clone; use clone::Clone;
use cmp::{PartialEq, Eq}; use cmp::{PartialEq, Eq};
use cmp::{PartialOrd, Ord}; use cmp::{PartialOrd, Ord};
use intrinsics;
use iter::Iterator;
use kinds::Copy; use kinds::Copy;
use mem::size_of; use mem::size_of;
use ops::{Add, Sub, Mul, Div, Rem, Neg}; use ops::{Add, Sub, Mul, Div, Rem, Neg};
use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
use option::{Option, Some, None}; use option::{Option, Some, None};
use str::{FromStr, from_str, StrPrelude};
/// Simultaneous division and remainder /// Simultaneous division and remainder
#[inline] #[inline]
@ -1372,6 +1375,290 @@ pub trait Float
fn to_radians(self) -> Self; fn to_radians(self) -> Self;
} }
/// A generic trait for converting a string with a radix (base) to a value
#[experimental = "might need to return Result"]
pub trait FromStrRadix {
fn from_str_radix(str: &str, radix: uint) -> Option<Self>;
}
/// A utility function that just calls FromStrRadix::from_str_radix.
#[experimental = "might need to return Result"]
pub fn from_str_radix<T: FromStrRadix>(str: &str, radix: uint) -> Option<T> {
FromStrRadix::from_str_radix(str, radix)
}
macro_rules! from_str_radix_float_impl {
($T:ty) => {
#[experimental = "might need to return Result"]
impl FromStr for $T {
/// Convert a string in base 10 to a float.
/// Accepts an optional decimal exponent.
///
/// This function accepts strings such as
///
/// * '3.14'
/// * '+3.14', equivalent to '3.14'
/// * '-3.14'
/// * '2.5E10', or equivalently, '2.5e10'
/// * '2.5E-10'
/// * '.' (understood as 0)
/// * '5.'
/// * '.5', or, equivalently, '0.5'
/// * '+inf', 'inf', '-inf', 'NaN'
///
/// Leading and trailing whitespace represent an error.
///
/// # Arguments
///
/// * src - A string
///
/// # Return value
///
/// `None` if the string did not represent a valid number. Otherwise,
/// `Some(n)` where `n` is the floating-point number represented by `src`.
#[inline]
fn from_str(src: &str) -> Option<$T> {
from_str_radix(src, 10)
}
}
#[experimental = "might need to return Result"]
impl FromStrRadix for $T {
/// Convert a string in a given base to a float.
///
/// Due to possible conflicts, this function does **not** accept
/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
/// does it recognize exponents of any kind.
///
/// Leading and trailing whitespace represent an error.
///
/// # Arguments
///
/// * src - A string
/// * radix - The base to use. Must lie in the range [2 .. 36]
///
/// # Return value
///
/// `None` if the string did not represent a valid number. Otherwise,
/// `Some(n)` where `n` is the floating-point number represented by `src`.
fn from_str_radix(src: &str, radix: uint) -> Option<$T> {
assert!(radix >= 2 && radix <= 36,
"from_str_radix_float: must lie in the range `[2, 36]` - found {}",
radix);
// Special values
match src {
"inf" => return Some(Float::infinity()),
"-inf" => return Some(Float::neg_infinity()),
"NaN" => return Some(Float::nan()),
_ => {},
}
let (is_positive, src) = match src.slice_shift_char() {
(None, _) => return None,
(Some('-'), "") => return None,
(Some('-'), src) => (false, src),
(Some(_), _) => (true, src),
};
// The significand to accumulate
let mut sig = if is_positive { 0.0 } else { -0.0 };
// Necessary to detect overflow
let mut prev_sig = sig;
let mut cs = src.chars().enumerate();
// Exponent prefix and exponent index offset
let mut exp_info = None::<(char, uint)>;
// Parse the integer part of the significand
for (i, c) in cs {
match c.to_digit(radix) {
Some(digit) => {
// shift significand one digit left
sig = sig * (radix as $T);
// add/subtract current digit depending on sign
if is_positive {
sig = sig + ((digit as int) as $T);
} else {
sig = sig - ((digit as int) as $T);
}
// Detect overflow by comparing to last value, except
// if we've not seen any non-zero digits.
if prev_sig != 0.0 {
if is_positive && sig <= prev_sig
{ return Some(Float::infinity()); }
if !is_positive && sig >= prev_sig
{ return Some(Float::neg_infinity()); }
// Detect overflow by reversing the shift-and-add process
if is_positive && (prev_sig != (sig - digit as $T) / radix as $T)
{ return Some(Float::infinity()); }
if !is_positive && (prev_sig != (sig + digit as $T) / radix as $T)
{ return Some(Float::neg_infinity()); }
}
prev_sig = sig;
},
None => match c {
'e' | 'E' | 'p' | 'P' => {
exp_info = Some((c, i + 1));
break; // start of exponent
},
'.' => {
break; // start of fractional part
},
_ => {
return None;
},
},
}
}
// If we are not yet at the exponent parse the fractional
// part of the significand
if exp_info.is_none() {
let mut power = 1.0;
for (i, c) in cs {
match c.to_digit(radix) {
Some(digit) => {
// Decrease power one order of magnitude
power = power / (radix as $T);
// add/subtract current digit depending on sign
sig = if is_positive {
sig + (digit as $T) * power
} else {
sig - (digit as $T) * power
};
// Detect overflow by comparing to last value
if is_positive && sig < prev_sig
{ return Some(Float::infinity()); }
if !is_positive && sig > prev_sig
{ return Some(Float::neg_infinity()); }
prev_sig = sig;
},
None => match c {
'e' | 'E' | 'p' | 'P' => {
exp_info = Some((c, i + 1));
break; // start of exponent
},
_ => {
return None; // invalid number
},
},
}
}
}
// Parse and calculate the exponent
let exp = match exp_info {
Some((c, offset)) => {
let base = match c {
'E' | 'e' if radix == 10 => 10u as $T,
'P' | 'p' if radix == 16 => 2u as $T,
_ => return None,
};
// Parse the exponent as decimal integer
let src = src[offset..];
let (is_positive, exp) = match src.slice_shift_char() {
(Some('-'), src) => (false, from_str::<uint>(src)),
(Some('+'), src) => (true, from_str::<uint>(src)),
(Some(_), _) => (true, from_str::<uint>(src)),
(None, _) => return None,
};
match (is_positive, exp) {
(true, Some(exp)) => base.powi(exp as i32),
(false, Some(exp)) => 1.0 / base.powi(exp as i32),
(_, None) => return None,
}
},
None => 1.0, // no exponent
};
Some(sig * exp)
}
}
}
}
from_str_radix_float_impl!(f32)
from_str_radix_float_impl!(f64)
macro_rules! from_str_radix_int_impl {
($T:ty) => {
#[experimental = "might need to return Result"]
impl FromStr for $T {
#[inline]
fn from_str(src: &str) -> Option<$T> {
from_str_radix(src, 10)
}
}
#[experimental = "might need to return Result"]
impl FromStrRadix for $T {
fn from_str_radix(src: &str, radix: uint) -> Option<$T> {
assert!(radix >= 2 && radix <= 36,
"from_str_radix_int: must lie in the range `[2, 36]` - found {}",
radix);
let is_signed_ty = (0 as $T) > Int::min_value();
match src.slice_shift_char() {
(Some('-'), src) if is_signed_ty => {
// The number is negative
let mut result = 0;
for c in src.chars() {
let x = match c.to_digit(radix) {
Some(x) => x,
None => return None,
};
result = match result.checked_mul(radix as $T) {
Some(result) => result,
None => return None,
};
result = match result.checked_sub(x as $T) {
Some(result) => result,
None => return None,
};
}
Some(result)
},
(Some(_), _) => {
// The number is signed
let mut result = 0;
for c in src.chars() {
let x = match c.to_digit(radix) {
Some(x) => x,
None => return None,
};
result = match result.checked_mul(radix as $T) {
Some(result) => result,
None => return None,
};
result = match result.checked_add(x as $T) {
Some(result) => result,
None => return None,
};
}
Some(result)
},
(None, _) => None,
}
}
}
}
}
from_str_radix_int_impl!(int)
from_str_radix_int_impl!(i8)
from_str_radix_int_impl!(i16)
from_str_radix_int_impl!(i32)
from_str_radix_int_impl!(i64)
from_str_radix_int_impl!(uint)
from_str_radix_int_impl!(u8)
from_str_radix_int_impl!(u16)
from_str_radix_int_impl!(u32)
from_str_radix_int_impl!(u64)
// DEPRECATED // DEPRECATED
macro_rules! trait_impl { macro_rules! trait_impl {

View file

@ -716,7 +716,6 @@ impl<T: Default> Option<T> {
impl<T> AsSlice<T> for Option<T> { impl<T> AsSlice<T> for Option<T> {
/// Convert from `Option<T>` to `&[T]` (without copying) /// Convert from `Option<T>` to `&[T]` (without copying)
#[inline] #[inline]
#[stable]
fn as_slice<'a>(&'a self) -> &'a [T] { fn as_slice<'a>(&'a self) -> &'a [T] {
match *self { match *self {
Some(ref x) => slice::ref_slice(x), Some(ref x) => slice::ref_slice(x),
@ -728,6 +727,7 @@ impl<T> AsSlice<T> for Option<T> {
} }
} }
#[stable]
impl<T> Default for Option<T> { impl<T> Default for Option<T> {
#[inline] #[inline]
fn default() -> Option<T> { None } fn default() -> Option<T> { None }
@ -772,9 +772,10 @@ impl<A> DoubleEndedIterator<A> for Item<A> {
impl<A> ExactSize<A> for Item<A> {} impl<A> ExactSize<A> for Item<A> {}
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// Free functions // FromIterator
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#[stable]
impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> { impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
/// Takes each element in the `Iterator`: if it is `None`, no further /// Takes each element in the `Iterator`: if it is `None`, no further
/// elements are taken, and the `None` is returned. Should no `None` occur, a /// elements are taken, and the `None` is returned. Should no `None` occur, a

View file

@ -41,6 +41,7 @@ pub use ops::{Fn, FnMut, FnOnce};
// Reexported functions // Reexported functions
pub use iter::{range, repeat}; pub use iter::{range, repeat};
pub use mem::drop; pub use mem::drop;
pub use str::from_str;
// Reexported types and traits // Reexported types and traits

View file

@ -878,9 +878,10 @@ impl<A> DoubleEndedIterator<A> for Item<A> {
impl<A> ExactSize<A> for Item<A> {} impl<A> ExactSize<A> for Item<A> {}
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// Free functions // FromIterator
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
#[stable]
impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> { impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
/// Takes each element in the `Iterator`: if it is an `Err`, no further /// Takes each element in the `Iterator`: if it is an `Err`, no further
/// elements are taken, and the `Err` is returned. Should no `Err` occur, a /// elements are taken, and the `Err` is returned. Should no `Err` occur, a
@ -933,6 +934,10 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
} }
} }
/////////////////////////////////////////////////////////////////////////////
// FromIterator
/////////////////////////////////////////////////////////////////////////////
/// Perform a fold operation over the result values from an iterator. /// Perform a fold operation over the result values from an iterator.
/// ///
/// If an `Err` is encountered, it is immediately returned. /// If an `Err` is encountered, it is immediately returned.

View file

@ -31,6 +31,42 @@ use raw::Repr;
use slice::{mod, SlicePrelude}; use slice::{mod, SlicePrelude};
use uint; use uint;
/// A trait to abstract the idea of creating a new instance of a type from a
/// string.
#[experimental = "might need to return Result"]
pub trait FromStr {
/// Parses a string `s` to return an optional value of this type. If the
/// string is ill-formatted, the None is returned.
fn from_str(s: &str) -> Option<Self>;
}
/// A utility function that just calls FromStr::from_str
pub fn from_str<A: FromStr>(s: &str) -> Option<A> {
FromStr::from_str(s)
}
impl FromStr for bool {
/// Parse a `bool` from a string.
///
/// Yields an `Option<bool>`, because `s` may or may not actually be parseable.
///
/// # Examples
///
/// ```rust
/// assert_eq!(from_str::<bool>("true"), Some(true));
/// assert_eq!(from_str::<bool>("false"), Some(false));
/// assert_eq!(from_str::<bool>("not even a boolean"), None);
/// ```
#[inline]
fn from_str(s: &str) -> Option<bool> {
match s {
"true" => Some(true),
"false" => Some(false),
_ => None,
}
}
}
/* /*
Section: Creating a string Section: Creating a string
*/ */

View file

@ -9,6 +9,7 @@
// except according to those terms. // except according to those terms.
use core::cell::*; use core::cell::*;
use core::default::Default;
use std::mem::drop; use std::mem::drop;
#[test] #[test]
@ -146,3 +147,15 @@ fn as_unsafe_cell() {
unsafe { *r2.as_unsafe_cell().get() = 1u; } unsafe { *r2.as_unsafe_cell().get() = 1u; }
assert_eq!(1u, *r2.borrow()); assert_eq!(1u, *r2.borrow());
} }
#[test]
fn cell_default() {
let cell: Cell<u32> = Default::default();
assert_eq!(0, cell.get());
}
#[test]
fn refcell_default() {
let cell: RefCell<u64> = Default::default();
assert_eq!(0, *cell.borrow());
}

View file

@ -15,7 +15,8 @@ macro_rules! int_module (($T:ty, $T_i:ident) => (
mod tests { mod tests {
use core::$T_i::*; use core::$T_i::*;
use core::int; use core::int;
use core::num::{Int, SignedInt}; use core::num::{FromStrRadix, Int, SignedInt};
use core::str::from_str;
use num; use num;
#[test] #[test]
@ -156,6 +157,49 @@ mod tests {
assert!(5i.checked_div(0) == None); assert!(5i.checked_div(0) == None);
assert!(int::MIN.checked_div(-1) == None); assert!(int::MIN.checked_div(-1) == None);
} }
#[test]
fn test_from_str() {
assert_eq!(from_str::<$T>("0"), Some(0 as $T));
assert_eq!(from_str::<$T>("3"), Some(3 as $T));
assert_eq!(from_str::<$T>("10"), Some(10 as $T));
assert_eq!(from_str::<i32>("123456789"), Some(123456789 as i32));
assert_eq!(from_str::<$T>("00100"), Some(100 as $T));
assert_eq!(from_str::<$T>("-1"), Some(-1 as $T));
assert_eq!(from_str::<$T>("-3"), Some(-3 as $T));
assert_eq!(from_str::<$T>("-10"), Some(-10 as $T));
assert_eq!(from_str::<i32>("-123456789"), Some(-123456789 as i32));
assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T));
assert_eq!(from_str::<$T>(""), None);
assert_eq!(from_str::<$T>(" "), None);
assert_eq!(from_str::<$T>("x"), None);
}
#[test]
fn test_from_str_radix() {
assert_eq!(FromStrRadix::from_str_radix("123", 10), Some(123 as $T));
assert_eq!(FromStrRadix::from_str_radix("1001", 2), Some(9 as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 8), Some(83 as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 16), Some(291 as i32));
assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Some(65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("FFFF", 16), Some(65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("z", 36), Some(35 as $T));
assert_eq!(FromStrRadix::from_str_radix("Z", 36), Some(35 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 10), Some(-123 as $T));
assert_eq!(FromStrRadix::from_str_radix("-1001", 2), Some(-9 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 8), Some(-83 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 16), Some(-291 as i32));
assert_eq!(FromStrRadix::from_str_radix("-ffff", 16), Some(-65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("-FFFF", 16), Some(-65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("-z", 36), Some(-35 as $T));
assert_eq!(FromStrRadix::from_str_radix("-Z", 36), Some(-35 as $T));
assert_eq!(FromStrRadix::from_str_radix("Z", 35), None::<$T>);
assert_eq!(FromStrRadix::from_str_radix("-9", 2), None::<$T>);
}
} }
)) ))

View file

@ -45,3 +45,73 @@ pub fn test_num<T>(ten: T, two: T) where
assert_eq!(ten.div(&two), ten / two); assert_eq!(ten.div(&two), ten / two);
assert_eq!(ten.rem(&two), ten % two); assert_eq!(ten.rem(&two), ten % two);
} }
#[cfg(test)]
mod test {
use core::option::{Option, Some, None};
use core::num::Float;
use core::num::from_str_radix;
#[test]
fn from_str_issue7588() {
let u : Option<u8> = from_str_radix("1000", 10);
assert_eq!(u, None);
let s : Option<i16> = from_str_radix("80000", 10);
assert_eq!(s, None);
let f : Option<f32> = from_str_radix("10000000000000000000000000000000000000000", 10);
assert_eq!(f, Some(Float::infinity()))
let fe : Option<f32> = from_str_radix("1e40", 10);
assert_eq!(fe, Some(Float::infinity()))
}
#[test]
fn test_from_str_radix_float() {
let x1 : Option<f64> = from_str_radix("-123.456", 10);
assert_eq!(x1, Some(-123.456));
let x2 : Option<f32> = from_str_radix("123.456", 10);
assert_eq!(x2, Some(123.456));
let x3 : Option<f32> = from_str_radix("-0.0", 10);
assert_eq!(x3, Some(-0.0));
let x4 : Option<f32> = from_str_radix("0.0", 10);
assert_eq!(x4, Some(0.0));
let x4 : Option<f32> = from_str_radix("1.0", 10);
assert_eq!(x4, Some(1.0));
let x5 : Option<f32> = from_str_radix("-1.0", 10);
assert_eq!(x5, Some(-1.0));
}
#[test]
fn test_int_from_str_overflow() {
let mut i8_val: i8 = 127_i8;
assert_eq!(from_str::<i8>("127"), Some(i8_val));
assert_eq!(from_str::<i8>("128"), None);
i8_val += 1 as i8;
assert_eq!(from_str::<i8>("-128"), Some(i8_val));
assert_eq!(from_str::<i8>("-129"), None);
let mut i16_val: i16 = 32_767_i16;
assert_eq!(from_str::<i16>("32767"), Some(i16_val));
assert_eq!(from_str::<i16>("32768"), None);
i16_val += 1 as i16;
assert_eq!(from_str::<i16>("-32768"), Some(i16_val));
assert_eq!(from_str::<i16>("-32769"), None);
let mut i32_val: i32 = 2_147_483_647_i32;
assert_eq!(from_str::<i32>("2147483647"), Some(i32_val));
assert_eq!(from_str::<i32>("2147483648"), None);
i32_val += 1 as i32;
assert_eq!(from_str::<i32>("-2147483648"), Some(i32_val));
assert_eq!(from_str::<i32>("-2147483649"), None);
let mut i64_val: i64 = 9_223_372_036_854_775_807_i64;
assert_eq!(from_str::<i64>("9223372036854775807"), Some(i64_val));
assert_eq!(from_str::<i64>("9223372036854775808"), None);
i64_val += 1 as i64;
assert_eq!(from_str::<i64>("-9223372036854775808"), Some(i64_val));
assert_eq!(from_str::<i64>("-9223372036854775809"), None);
}
}

View file

@ -8,6 +8,13 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#[test]
fn test_bool_from_str() {
assert_eq!(from_str::<bool>("true"), Some(true));
assert_eq!(from_str::<bool>("false"), Some(false));
assert_eq!(from_str::<bool>("not even a boolean"), None);
}
fn check_contains_all_substrings(s: &str) { fn check_contains_all_substrings(s: &str) {
assert!(s.contains("")); assert!(s.contains(""));
for i in range(0, s.len()) { for i in range(0, s.len()) {

View file

@ -10,7 +10,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt; use std::fmt;
use std::from_str::from_str;
use std::str::{MaybeOwned, Owned, Slice}; use std::str::{MaybeOwned, Owned, Slice};
use compile::Program; use compile::Program;

View file

@ -268,8 +268,21 @@ macro_rules! cgoptions(
pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool; pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool;
pub const CG_OPTIONS: &'static [(&'static str, CodegenSetter, pub const CG_OPTIONS: &'static [(&'static str, CodegenSetter,
&'static str)] = Option<&'static str>, &'static str)] =
&[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ]; &[ $( (stringify!($opt), cgsetters::$opt, cg_type_descs::$parse, $desc) ),* ];
#[allow(non_upper_case_globals)]
mod cg_type_descs {
pub const parse_bool: Option<&'static str> = None;
pub const parse_opt_bool: Option<&'static str> = None;
pub const parse_string: Option<&'static str> = Some("a string");
pub const parse_opt_string: Option<&'static str> = Some("a string");
pub const parse_list: Option<&'static str> = Some("a space-separated list of strings");
pub const parse_opt_list: Option<&'static str> = Some("a space-separated list of strings");
pub const parse_uint: Option<&'static str> = Some("a number");
pub const parse_passes: Option<&'static str> =
Some("a space-separated list of passes, or `all`");
}
mod cgsetters { mod cgsetters {
use super::{CodegenOptions, Passes, SomePasses, AllPasses}; use super::{CodegenOptions, Passes, SomePasses, AllPasses};
@ -334,8 +347,7 @@ macro_rules! cgoptions(
} }
fn parse_uint(slot: &mut uint, v: Option<&str>) -> bool { fn parse_uint(slot: &mut uint, v: Option<&str>) -> bool {
use std::from_str::FromStr; match v.and_then(from_str) {
match v.and_then(FromStr::from_str) {
Some(i) => { *slot = i; true }, Some(i) => { *slot = i; true },
None => false None => false
} }
@ -421,19 +433,25 @@ pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
let value = iter.next(); let value = iter.next();
let option_to_lookup = key.replace("-", "_"); let option_to_lookup = key.replace("-", "_");
let mut found = false; let mut found = false;
for &(candidate, setter, _) in CG_OPTIONS.iter() { for &(candidate, setter, opt_type_desc, _) in CG_OPTIONS.iter() {
if option_to_lookup.as_slice() != candidate { continue } if option_to_lookup.as_slice() != candidate { continue }
if !setter(&mut cg, value) { if !setter(&mut cg, value) {
match value { match (value, opt_type_desc) {
Some(..) => { (Some(..), None) => {
early_error(format!("codegen option `{}` takes no \ early_error(format!("codegen option `{}` takes no \
value", key).as_slice()) value", key).as_slice())
} }
None => { (None, Some(type_desc)) => {
early_error(format!("codegen option `{0}` requires \ early_error(format!("codegen option `{0}` requires \
a value (-C {0}=<value>)", {1} (-C {0}=<value>)",
key).as_slice()) key, type_desc).as_slice())
} }
(Some(value), Some(type_desc)) => {
early_error(format!("incorrect value `{}` for codegen \
option `{}` - {} was expected",
value, key, type_desc).as_slice())
}
(None, None) => unreachable!()
} }
} }
found = true; found = true;

View file

@ -299,14 +299,10 @@ fn describe_debug_flags() {
fn describe_codegen_flags() { fn describe_codegen_flags() {
println!("\nAvailable codegen options:\n"); println!("\nAvailable codegen options:\n");
let mut cg = config::basic_codegen_options(); for &(name, _, opt_type_desc, desc) in config::CG_OPTIONS.iter() {
for &(name, parser, desc) in config::CG_OPTIONS.iter() { let (width, extra) = match opt_type_desc {
// we invoke the parser function on `None` to see if this option needs Some(..) => (21, "=val"),
// an argument or not. None => (25, "")
let (width, extra) = if parser(&mut cg, None) {
(25, "")
} else {
(21, "=val")
}; };
println!(" -C {:>width$s}{} -- {}", name.replace("_", "-"), println!(" -C {:>width$s}{} -- {}", name.replace("_", "-"),
extra, desc, width=width); extra, desc, width=width);

View file

@ -31,8 +31,8 @@ use syntax::print::{pp, pprust};
use graphviz as dot; use graphviz as dot;
use std::io::{mod, MemReader}; use std::io::{mod, MemReader};
use std::from_str::FromStr;
use std::option; use std::option;
use std::str::FromStr;
use arena::TypedArena; use arena::TypedArena;
#[deriving(PartialEq, Show)] #[deriving(PartialEq, Show)]

View file

@ -455,7 +455,12 @@ pub fn llvm_type_name(cx: &CrateContext,
let base = ty::item_path_str(cx.tcx(), did); let base = ty::item_path_str(cx.tcx(), did);
let strings: Vec<String> = tps.iter().map(|t| t.repr(cx.tcx())).collect(); let strings: Vec<String> = tps.iter().map(|t| t.repr(cx.tcx())).collect();
let tstr = format!("{}<{}>", base, strings); let tstr = if strings.is_empty() {
base
} else {
format!("{}<{}>", base, strings)
};
if did.krate == 0 { if did.krate == 0 {
format!("{}.{}", name, tstr) format!("{}.{}", name, tstr)
} else { } else {

View file

@ -584,3 +584,9 @@ pre.rust { position: relative; }
height: 1.5em; height: 1.5em;
} }
} }
@media print {
nav.sub, .content .out-of-band, .collapse-toggle {
display: none;
}
}

View file

@ -19,7 +19,7 @@ use std::num::Zero;
use syntax::attr::{Deprecated, Experimental, Unstable, Stable, Frozen, Locked}; use syntax::attr::{Deprecated, Experimental, Unstable, Stable, Frozen, Locked};
use syntax::ast::Public; use syntax::ast::Public;
use clean::{Crate, Item, ModuleItem, Module, StructItem, Struct, EnumItem, Enum}; use clean::{Crate, Item, ModuleItem, Module, EnumItem, Enum};
use clean::{ImplItem, Impl, Trait, TraitItem, TraitMethod, ProvidedMethod, RequiredMethod}; use clean::{ImplItem, Impl, Trait, TraitItem, TraitMethod, ProvidedMethod, RequiredMethod};
use clean::{TypeTraitItem, ViewItemItem, PrimitiveItem, Stability}; use clean::{TypeTraitItem, ViewItemItem, PrimitiveItem, Stability};
@ -146,13 +146,12 @@ fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
// considered to have no children. // considered to have no children.
match item.inner { match item.inner {
// Require explicit `pub` to be visible // Require explicit `pub` to be visible
StructItem(Struct { fields: ref subitems, .. }) |
ImplItem(Impl { items: ref subitems, trait_: None, .. }) => { ImplItem(Impl { items: ref subitems, trait_: None, .. }) => {
let subcounts = subitems.iter().filter(|i| visible(*i)) let subcounts = subitems.iter().filter(|i| visible(*i))
.map(summarize_item) .map(summarize_item)
.map(|s| s.val0()) .map(|s| s.val0())
.fold(Counts::zero(), |acc, x| acc + x); .fold(Counts::zero(), |acc, x| acc + x);
(item_counts + subcounts, None) (subcounts, None)
} }
// `pub` automatically // `pub` automatically
EnumItem(Enum { variants: ref subitems, .. }) => { EnumItem(Enum { variants: ref subitems, .. }) => {

View file

@ -200,7 +200,7 @@ use std::{char, f64, fmt, io, num, str};
use std::io::MemWriter; use std::io::MemWriter;
use std::mem::{swap, transmute}; use std::mem::{swap, transmute};
use std::num::{Float, FPNaN, FPInfinite, Int}; use std::num::{Float, FPNaN, FPInfinite, Int};
use std::str::ScalarValue; use std::str::{FromStr, ScalarValue};
use std::string; use std::string;
use std::vec::Vec; use std::vec::Vec;
use std::ops; use std::ops;
@ -1988,7 +1988,7 @@ macro_rules! read_primitive {
String(s) => { String(s) => {
// re: #12967.. a type w/ numeric keys (ie HashMap<uint, V> etc) // re: #12967.. a type w/ numeric keys (ie HashMap<uint, V> etc)
// is going to have a string here, as per JSON spec. // is going to have a string here, as per JSON spec.
match std::from_str::from_str(s.as_slice()) { match std::str::from_str(s.as_slice()) {
Some(f) => Ok(f), Some(f) => Ok(f),
None => Err(ExpectedError("Number".to_string(), s)), None => Err(ExpectedError("Number".to_string(), s)),
} }
@ -2027,7 +2027,7 @@ impl ::Decoder<DecoderError> for Decoder {
String(s) => { String(s) => {
// re: #12967.. a type w/ numeric keys (ie HashMap<uint, V> etc) // re: #12967.. a type w/ numeric keys (ie HashMap<uint, V> etc)
// is going to have a string here, as per JSON spec. // is going to have a string here, as per JSON spec.
match std::from_str::from_str(s.as_slice()) { match std::str::from_str(s.as_slice()) {
Some(f) => Ok(f), Some(f) => Ok(f),
None => Err(ExpectedError("Number".to_string(), s)), None => Err(ExpectedError("Number".to_string(), s)),
} }
@ -2315,6 +2315,10 @@ impl ToJson for bool {
fn to_json(&self) -> Json { Boolean(*self) } fn to_json(&self) -> Json { Boolean(*self) }
} }
impl ToJson for str {
fn to_json(&self) -> Json { String(self.into_string()) }
}
impl ToJson for string::String { impl ToJson for string::String {
fn to_json(&self) -> Json { String((*self).clone()) } fn to_json(&self) -> Json { String((*self).clone()) }
} }
@ -2395,7 +2399,7 @@ impl fmt::Show for Json {
} }
} }
impl std::from_str::FromStr for Json { impl FromStr for Json {
fn from_str(s: &str) -> Option<Json> { fn from_str(s: &str) -> Option<Json> {
from_str(s).ok() from_str(s).ok()
} }
@ -2480,7 +2484,7 @@ mod tests {
#[test] #[test]
fn test_from_str_trait() { fn test_from_str_trait() {
let s = "null"; let s = "null";
assert!(::std::from_str::from_str::<Json>(s).unwrap() == from_str(s).unwrap()); assert!(::std::str::from_str::<Json>(s).unwrap() == from_str(s).unwrap());
} }
#[test] #[test]
@ -3714,7 +3718,8 @@ mod tests {
assert_eq!(f64::NAN.to_json(), Null); assert_eq!(f64::NAN.to_json(), Null);
assert_eq!(true.to_json(), Boolean(true)); assert_eq!(true.to_json(), Boolean(true));
assert_eq!(false.to_json(), Boolean(false)); assert_eq!(false.to_json(), Boolean(false));
assert_eq!("abc".to_string().to_json(), String("abc".to_string())); assert_eq!("abc".to_json(), String("abc".into_string()));
assert_eq!("abc".into_string().to_json(), String("abc".into_string()));
assert_eq!((1u, 2u).to_json(), list2); assert_eq!((1u, 2u).to_json(), list2);
assert_eq!((1u, 2u, 3u).to_json(), list3); assert_eq!((1u, 2u, 3u).to_json(), list3);
assert_eq!([1u, 2].to_json(), list2); assert_eq!([1u, 2].to_json(), list2);

View file

@ -21,8 +21,7 @@ use mem;
use option::{Option, Some, None}; use option::{Option, Some, None};
use slice::{SlicePrelude, AsSlice}; use slice::{SlicePrelude, AsSlice};
use str::{Str, StrPrelude}; use str::{Str, StrPrelude};
use string::{mod, String}; use string::{mod, String, IntoString};
use to_string::IntoStr;
use vec::Vec; use vec::Vec;
/// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero. /// Datatype to hold one ascii character. It wraps a `u8`, with the highest bit always zero.
@ -326,7 +325,7 @@ impl AsciiStr for [Ascii] {
} }
} }
impl IntoStr for Vec<Ascii> { impl IntoString for Vec<Ascii> {
#[inline] #[inline]
fn into_string(self) -> String { fn into_string(self) -> String {
unsafe { unsafe {

View file

@ -1,71 +0,0 @@
// Copyright 2012 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.
//! The `FromStr` trait for types that can be created from strings
#![experimental]
use option::{Option, Some, None};
use string::String;
/// A trait to abstract the idea of creating a new instance of a type from a
/// string.
#[experimental = "might need to return Result"]
pub trait FromStr {
/// Parses a string `s` to return an optional value of this type. If the
/// string is ill-formatted, the None is returned.
fn from_str(s: &str) -> Option<Self>;
}
/// A utility function that just calls FromStr::from_str
pub fn from_str<A: FromStr>(s: &str) -> Option<A> {
FromStr::from_str(s)
}
impl FromStr for bool {
/// Parse a `bool` from a string.
///
/// Yields an `Option<bool>`, because `s` may or may not actually be parseable.
///
/// # Examples
///
/// ```rust
/// assert_eq!(from_str::<bool>("true"), Some(true));
/// assert_eq!(from_str::<bool>("false"), Some(false));
/// assert_eq!(from_str::<bool>("not even a boolean"), None);
/// ```
#[inline]
fn from_str(s: &str) -> Option<bool> {
match s {
"true" => Some(true),
"false" => Some(false),
_ => None,
}
}
}
impl FromStr for String {
#[inline]
fn from_str(s: &str) -> Option<String> {
Some(String::from_str(s))
}
}
#[cfg(test)]
mod test {
use prelude::*;
#[test]
fn test_bool_from_str() {
assert_eq!(from_str::<bool>("true"), Some(true));
assert_eq!(from_str::<bool>("false"), Some(false));
assert_eq!(from_str::<bool>("not even a boolean"), None);
}
}

View file

@ -16,13 +16,12 @@
#![allow(missing_docs)] #![allow(missing_docs)]
use fmt; use fmt;
use from_str::FromStr;
use io::{mod, IoResult, IoError}; use io::{mod, IoResult, IoError};
use io::net; use io::net;
use iter::Iterator; use iter::Iterator;
use option::{Option, None, Some}; use option::{Option, None, Some};
use result::{Ok, Err}; use result::{Ok, Err};
use str::StrPrelude; use str::{FromStr, StrPrelude};
use slice::{CloneSlicePrelude, SlicePrelude}; use slice::{CloneSlicePrelude, SlicePrelude};
use vec::Vec; use vec::Vec;
@ -540,7 +539,7 @@ impl<'a> ToSocketAddr for &'a str {
mod test { mod test {
use prelude::*; use prelude::*;
use super::*; use super::*;
use from_str::FromStr; use str::FromStr;
#[test] #[test]
fn test_from_str_ipv4() { fn test_from_str_ipv4() {

View file

@ -661,23 +661,22 @@ mod test {
let addr = next_test_ip4(); let addr = next_test_ip4();
let mut acceptor = TcpListener::bind(addr).listen(); let mut acceptor = TcpListener::bind(addr).listen();
let (tx, rx) = channel();
spawn(proc() { spawn(proc() {
let _stream = TcpStream::connect(addr); drop(TcpStream::connect(addr));
// Close tx.send(());
}); });
let mut stream = acceptor.accept(); let mut stream = acceptor.accept();
rx.recv();
let buf = [0]; let buf = [0];
loop { match stream.write(buf) {
match stream.write(buf) { Ok(..) => {}
Ok(..) => {} Err(e) => {
Err(e) => { assert!(e.kind == ConnectionReset ||
assert!(e.kind == ConnectionReset || e.kind == BrokenPipe ||
e.kind == BrokenPipe || e.kind == ConnectionAborted,
e.kind == ConnectionAborted, "unknown error: {}", e);
"unknown error: {}", e);
break;
}
} }
} }
} }
@ -687,23 +686,22 @@ mod test {
let addr = next_test_ip6(); let addr = next_test_ip6();
let mut acceptor = TcpListener::bind(addr).listen(); let mut acceptor = TcpListener::bind(addr).listen();
let (tx, rx) = channel();
spawn(proc() { spawn(proc() {
let _stream = TcpStream::connect(addr); drop(TcpStream::connect(addr));
// Close tx.send(());
}); });
let mut stream = acceptor.accept(); let mut stream = acceptor.accept();
rx.recv();
let buf = [0]; let buf = [0];
loop { match stream.write(buf) {
match stream.write(buf) { Ok(..) => {}
Ok(..) => {} Err(e) => {
Err(e) => { assert!(e.kind == ConnectionReset ||
assert!(e.kind == ConnectionReset || e.kind == BrokenPipe ||
e.kind == BrokenPipe || e.kind == ConnectionAborted,
e.kind == ConnectionAborted, "unknown error: {}", e);
"unknown error: {}", e);
break;
}
} }
} }
} }

View file

@ -1190,7 +1190,7 @@ mod tests {
Path::new("/dev/null") Path::new("/dev/null")
}; };
let mut fdes = match fs::open(&path, Truncate, Write) { let fdes = match fs::open(&path, Truncate, Write) {
Ok(f) => f, Ok(f) => f,
Err(_) => panic!("failed to open file descriptor"), Err(_) => panic!("failed to open file descriptor"),
}; };

View file

@ -54,7 +54,7 @@
//! //!
//! For converting to strings use the [`format!`](fmt/index.html) //! For converting to strings use the [`format!`](fmt/index.html)
//! macro, and for converting from strings use the //! macro, and for converting from strings use the
//! [`FromStr`](from_str/index.html) trait. //! [`FromStr`](str/trait.FromStr.html) trait.
//! //!
//! ## Platform abstractions //! ## Platform abstractions
//! //!
@ -219,9 +219,7 @@ pub mod time;
/* Common traits */ /* Common traits */
pub mod error; pub mod error;
pub mod from_str;
pub mod num; pub mod num;
pub mod to_string;
/* Common data structures */ /* Common data structures */

View file

@ -17,12 +17,10 @@
use prelude::*; use prelude::*;
use from_str::FromStr;
use intrinsics; use intrinsics;
use libc::c_int; use libc::c_int;
use num::{Float, FloatMath}; use num::{Float, FloatMath};
use num::strconv; use num::strconv;
use num;
pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE}; pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE};
pub use core::f32::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP}; pub use core::f32::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP};
@ -339,68 +337,6 @@ pub fn to_str_exp_digits(num: f32, dig: uint, upper: bool) -> String {
r r
} }
#[inline]
#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"]
pub fn from_str_hex(src: &str) -> Option<f32> {
strconv::from_str_radix_float(src, 16)
}
impl FromStr for f32 {
/// Convert a string in base 10 to a float.
/// Accepts an optional decimal exponent.
///
/// This function accepts strings such as
///
/// * '3.14'
/// * '+3.14', equivalent to '3.14'
/// * '-3.14'
/// * '2.5E10', or equivalently, '2.5e10'
/// * '2.5E-10'
/// * '.' (understood as 0)
/// * '5.'
/// * '.5', or, equivalently, '0.5'
/// * '+inf', 'inf', '-inf', 'NaN'
///
/// Leading and trailing whitespace represent an error.
///
/// # Arguments
///
/// * src - A string
///
/// # Return value
///
/// `None` if the string did not represent a valid number. Otherwise,
/// `Some(n)` where `n` is the floating-point number represented by `src`.
#[inline]
fn from_str(src: &str) -> Option<f32> {
strconv::from_str_radix_float(src, 10u)
}
}
impl num::FromStrRadix for f32 {
/// Convert a string in a given base to a float.
///
/// Due to possible conflicts, this function does **not** accept
/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
/// does it recognize exponents of any kind.
///
/// Leading and trailing whitespace represent an error.
///
/// # Arguments
///
/// * src - A string
/// * radix - The base to use. Must lie in the range [2 .. 36]
///
/// # Return value
///
/// `None` if the string did not represent a valid number. Otherwise,
/// `Some(n)` where `n` is the floating-point number represented by `src`.
#[inline]
fn from_str_radix(src: &str, radix: uint) -> Option<f32> {
strconv::from_str_radix_float(src, radix)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use f32::*; use f32::*;

View file

@ -16,12 +16,10 @@
use prelude::*; use prelude::*;
use from_str::FromStr;
use intrinsics; use intrinsics;
use libc::c_int; use libc::c_int;
use num::{Float, FloatMath}; use num::{Float, FloatMath};
use num::strconv; use num::strconv;
use num;
pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE}; pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE};
pub use core::f64::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP}; pub use core::f64::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP};
@ -347,63 +345,6 @@ pub fn to_str_exp_digits(num: f64, dig: uint, upper: bool) -> String {
r r
} }
#[inline]
#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"]
pub fn from_str_hex(src: &str) -> Option<f64> {
strconv::from_str_radix_float(src, 16)
}
impl FromStr for f64 {
/// Convert a string in base 10 to a float.
/// Accepts an optional decimal exponent.
///
/// This function accepts strings such as:
///
/// * '3.14'
/// * '-3.14'
/// * '2.5E10', or equivalently, '2.5e10'
/// * '2.5E-10'
/// * '.' (understood as 0)
/// * '5.'
/// * '.5', or, equivalently, '0.5'
/// * inf', '-inf', 'NaN'
///
/// Leading and trailing whitespace represent an error.
///
/// # Arguments
///
/// * src - A string
///
/// # Return value
///
/// `none` if the string did not represent a valid number. Otherwise,
/// `Some(n)` where `n` is the floating-point number represented by `src`.
#[inline]
fn from_str(src: &str) -> Option<f64> {
strconv::from_str_radix_float(src, 10u)
}
}
impl num::FromStrRadix for f64 {
/// Convert a string in a given base to a float.
///
/// Leading and trailing whitespace represent an error.
///
/// # Arguments
///
/// * src - A string
/// * radix - The base to use. Must lie in the range [2 .. 36]
///
/// # Return value
///
/// `None` if the string did not represent a valid number. Otherwise,
/// `Some(n)` where `n` is the floating-point number represented by `src`.
#[inline]
fn from_str_radix(src: &str, radix: uint) -> Option<f64> {
strconv::from_str_radix_float(src, radix)
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use f64::*; use f64::*;

View file

@ -13,11 +13,6 @@
#![unstable] #![unstable]
#![doc(primitive = "i16")] #![doc(primitive = "i16")]
use from_str::FromStr;
use num::FromStrRadix;
use num::strconv;
use option::Option;
pub use core::i16::{BITS, BYTES, MIN, MAX}; pub use core::i16::{BITS, BYTES, MIN, MAX};
int_module!(i16) int_module!(i16)

View file

@ -13,11 +13,6 @@
#![unstable] #![unstable]
#![doc(primitive = "i32")] #![doc(primitive = "i32")]
use from_str::FromStr;
use num::FromStrRadix;
use num::strconv;
use option::Option;
pub use core::i32::{BITS, BYTES, MIN, MAX}; pub use core::i32::{BITS, BYTES, MIN, MAX};
int_module!(i32) int_module!(i32)

View file

@ -13,11 +13,6 @@
#![unstable] #![unstable]
#![doc(primitive = "i64")] #![doc(primitive = "i64")]
use from_str::FromStr;
use num::FromStrRadix;
use num::strconv;
use option::Option;
pub use core::i64::{BITS, BYTES, MIN, MAX}; pub use core::i64::{BITS, BYTES, MIN, MAX};
int_module!(i64) int_module!(i64)

View file

@ -13,11 +13,6 @@
#![unstable] #![unstable]
#![doc(primitive = "i8")] #![doc(primitive = "i8")]
use from_str::FromStr;
use num::FromStrRadix;
use num::strconv;
use option::Option;
pub use core::i8::{BITS, BYTES, MIN, MAX}; pub use core::i8::{BITS, BYTES, MIN, MAX};
int_module!(i8) int_module!(i8)

View file

@ -13,11 +13,6 @@
#![unstable] #![unstable]
#![doc(primitive = "int")] #![doc(primitive = "int")]
use from_str::FromStr;
use num::FromStrRadix;
use num::strconv;
use option::Option;
pub use core::int::{BITS, BYTES, MIN, MAX}; pub use core::int::{BITS, BYTES, MIN, MAX};
int_module!(int) int_module!(int)

View file

@ -14,131 +14,4 @@
macro_rules! int_module (($T:ty) => ( macro_rules! int_module (($T:ty) => (
#[experimental = "might need to return Result"]
impl FromStr for $T {
#[inline]
fn from_str(s: &str) -> Option<$T> {
strconv::from_str_radix_int(s, 10)
}
}
#[experimental = "might need to return Result"]
impl FromStrRadix for $T {
#[inline]
fn from_str_radix(s: &str, radix: uint) -> Option<$T> {
strconv::from_str_radix_int(s, radix)
}
}
#[cfg(test)]
mod tests {
use prelude::*;
use num::FromStrRadix;
#[test]
fn test_from_str() {
assert_eq!(from_str::<$T>("0"), Some(0 as $T));
assert_eq!(from_str::<$T>("3"), Some(3 as $T));
assert_eq!(from_str::<$T>("10"), Some(10 as $T));
assert_eq!(from_str::<i32>("123456789"), Some(123456789 as i32));
assert_eq!(from_str::<$T>("00100"), Some(100 as $T));
assert_eq!(from_str::<$T>("-1"), Some(-1 as $T));
assert_eq!(from_str::<$T>("-3"), Some(-3 as $T));
assert_eq!(from_str::<$T>("-10"), Some(-10 as $T));
assert_eq!(from_str::<i32>("-123456789"), Some(-123456789 as i32));
assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T));
assert_eq!(from_str::<$T>(""), None);
assert_eq!(from_str::<$T>(" "), None);
assert_eq!(from_str::<$T>("x"), None);
}
#[test]
fn test_from_str_radix() {
assert_eq!(FromStrRadix::from_str_radix("123", 10), Some(123 as $T));
assert_eq!(FromStrRadix::from_str_radix("1001", 2), Some(9 as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 8), Some(83 as $T));
assert_eq!(FromStrRadix::from_str_radix("123", 16), Some(291 as i32));
assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Some(65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("FFFF", 16), Some(65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("z", 36), Some(35 as $T));
assert_eq!(FromStrRadix::from_str_radix("Z", 36), Some(35 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 10), Some(-123 as $T));
assert_eq!(FromStrRadix::from_str_radix("-1001", 2), Some(-9 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 8), Some(-83 as $T));
assert_eq!(FromStrRadix::from_str_radix("-123", 16), Some(-291 as i32));
assert_eq!(FromStrRadix::from_str_radix("-ffff", 16), Some(-65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("-FFFF", 16), Some(-65535 as i32));
assert_eq!(FromStrRadix::from_str_radix("-z", 36), Some(-35 as $T));
assert_eq!(FromStrRadix::from_str_radix("-Z", 36), Some(-35 as $T));
assert_eq!(FromStrRadix::from_str_radix("Z", 35), None::<$T>);
assert_eq!(FromStrRadix::from_str_radix("-9", 2), None::<$T>);
}
#[test]
fn test_int_to_str_overflow() {
let mut i8_val: i8 = 127_i8;
assert_eq!(i8_val.to_string(), "127".to_string());
i8_val += 1 as i8;
assert_eq!(i8_val.to_string(), "-128".to_string());
let mut i16_val: i16 = 32_767_i16;
assert_eq!(i16_val.to_string(), "32767".to_string());
i16_val += 1 as i16;
assert_eq!(i16_val.to_string(), "-32768".to_string());
let mut i32_val: i32 = 2_147_483_647_i32;
assert_eq!(i32_val.to_string(), "2147483647".to_string());
i32_val += 1 as i32;
assert_eq!(i32_val.to_string(), "-2147483648".to_string());
let mut i64_val: i64 = 9_223_372_036_854_775_807_i64;
assert_eq!(i64_val.to_string(), "9223372036854775807".to_string());
i64_val += 1 as i64;
assert_eq!(i64_val.to_string(), "-9223372036854775808".to_string());
}
#[test]
fn test_int_from_str_overflow() {
let mut i8_val: i8 = 127_i8;
assert_eq!(from_str::<i8>("127"), Some(i8_val));
assert_eq!(from_str::<i8>("128"), None);
i8_val += 1 as i8;
assert_eq!(from_str::<i8>("-128"), Some(i8_val));
assert_eq!(from_str::<i8>("-129"), None);
let mut i16_val: i16 = 32_767_i16;
assert_eq!(from_str::<i16>("32767"), Some(i16_val));
assert_eq!(from_str::<i16>("32768"), None);
i16_val += 1 as i16;
assert_eq!(from_str::<i16>("-32768"), Some(i16_val));
assert_eq!(from_str::<i16>("-32769"), None);
let mut i32_val: i32 = 2_147_483_647_i32;
assert_eq!(from_str::<i32>("2147483647"), Some(i32_val));
assert_eq!(from_str::<i32>("2147483648"), None);
i32_val += 1 as i32;
assert_eq!(from_str::<i32>("-2147483648"), Some(i32_val));
assert_eq!(from_str::<i32>("-2147483649"), None);
let mut i64_val: i64 = 9_223_372_036_854_775_807_i64;
assert_eq!(from_str::<i64>("9223372036854775807"), Some(i64_val));
assert_eq!(from_str::<i64>("9223372036854775808"), None);
i64_val += 1 as i64;
assert_eq!(from_str::<i64>("-9223372036854775808"), Some(i64_val));
assert_eq!(from_str::<i64>("-9223372036854775809"), None);
}
}
)) ))

View file

@ -16,8 +16,6 @@
#![experimental] #![experimental]
#![allow(missing_docs)] #![allow(missing_docs)]
use option::Option;
#[cfg(test)] use cmp::PartialEq; #[cfg(test)] use cmp::PartialEq;
#[cfg(test)] use fmt::Show; #[cfg(test)] use fmt::Show;
#[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem}; #[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem};
@ -31,6 +29,7 @@ pub use core::num::{checked_next_power_of_two};
pub use core::num::{from_int, from_i8, from_i16, from_i32, from_i64}; pub use core::num::{from_int, from_i8, from_i16, from_i32, from_i64};
pub use core::num::{from_uint, from_u8, from_u16, from_u32, from_u64}; pub use core::num::{from_uint, from_u8, from_u16, from_u32, from_u64};
pub use core::num::{from_f32, from_f64}; pub use core::num::{from_f32, from_f64};
pub use core::num::{FromStrRadix, from_str_radix};
pub use core::num::{FPCategory, FPNaN, FPInfinite, FPZero, FPSubnormal}; pub use core::num::{FPCategory, FPNaN, FPInfinite, FPZero, FPSubnormal};
pub use core::num::{FPNormal, Float}; pub use core::num::{FPNormal, Float};
@ -115,18 +114,6 @@ pub trait FloatMath: Float {
fn atanh(self) -> Self; fn atanh(self) -> Self;
} }
/// A generic trait for converting a string with a radix (base) to a value
#[experimental = "might need to return Result"]
pub trait FromStrRadix {
fn from_str_radix(str: &str, radix: uint) -> Option<Self>;
}
/// A utility function that just calls FromStrRadix::from_str_radix.
#[experimental = "might need to return Result"]
pub fn from_str_radix<T: FromStrRadix>(str: &str, radix: uint) -> Option<T> {
FromStrRadix::from_str_radix(str, radix)
}
// DEPRECATED // DEPRECATED
#[deprecated = "Use `FloatMath::abs_sub`"] #[deprecated = "Use `FloatMath::abs_sub`"]
@ -764,8 +751,9 @@ mod tests {
#[test] #[test]
fn test_pow() { fn test_pow() {
fn naive_pow<T: One + Mul<T, T>>(base: T, exp: uint) -> T { fn naive_pow<T: Int>(base: T, exp: uint) -> T {
range(0, exp).fold(one::<T>(), |acc, _| acc * base) let one: T = Int::one();
range(0, exp).fold(one, |acc, _| acc * base)
} }
macro_rules! assert_pow( macro_rules! assert_pow(
(($num:expr, $exp:expr) => $expected:expr) => {{ (($num:expr, $exp:expr) => $expected:expr) => {{

View file

@ -13,12 +13,8 @@
#![allow(missing_docs)] #![allow(missing_docs)]
use char; use char;
use char::Char;
use from_str::from_str;
use iter::Iterator;
use num; use num;
use num::{Int, Float, FPNaN, FPInfinite, ToPrimitive}; use num::{Int, Float, FPNaN, FPInfinite, ToPrimitive};
use option::{None, Option, Some};
use slice::{SlicePrelude, CloneSliceAllocPrelude}; use slice::{SlicePrelude, CloneSliceAllocPrelude};
use str::StrPrelude; use str::StrPrelude;
use string::String; use string::String;
@ -425,242 +421,35 @@ pub fn float_to_str_common<T: Float>(
static DIGIT_P_RADIX: uint = ('p' as uint) - ('a' as uint) + 11u; static DIGIT_P_RADIX: uint = ('p' as uint) - ('a' as uint) + 11u;
static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u; static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
pub fn from_str_radix_float<T: Float>(src: &str, radix: uint) -> Option<T> {
assert!(radix >= 2 && radix <= 36,
"from_str_radix_float: must lie in the range `[2, 36]` - found {}",
radix);
let _0: T = Float::zero();
let _1: T = Float::one();
let radix_t: T = num::cast(radix as int).unwrap();
// Special values
match src {
"inf" => return Some(Float::infinity()),
"-inf" => return Some(Float::neg_infinity()),
"NaN" => return Some(Float::nan()),
_ => {},
}
let (is_positive, src) = match src.slice_shift_char() {
(None, _) => return None,
(Some('-'), "") => return None,
(Some('-'), src) => (false, src),
(Some(_), _) => (true, src),
};
// The significand to accumulate
let mut sig = if is_positive { _0 } else { -_0 };
// Necessary to detect overflow
let mut prev_sig = sig;
let mut cs = src.chars().enumerate();
// Exponent prefix and exponent index offset
let mut exp_info = None::<(char, uint)>;
// Parse the integer part of the significand
for (i, c) in cs {
match c.to_digit(radix) {
Some(digit) => {
// shift significand one digit left
sig = sig * radix_t;
// add/subtract current digit depending on sign
if is_positive {
sig = sig + num::cast(digit as int).unwrap();
} else {
sig = sig - num::cast(digit as int).unwrap();
}
// Detect overflow by comparing to last value, except
// if we've not seen any non-zero digits.
if prev_sig != _0 {
if is_positive && sig <= prev_sig
{ return Some(Float::infinity()); }
if !is_positive && sig >= prev_sig
{ return Some(Float::neg_infinity()); }
// Detect overflow by reversing the shift-and-add process
let digit: T = num::cast(digit as int).unwrap();
if is_positive && (prev_sig != ((sig - digit) / radix_t))
{ return Some(Float::infinity()); }
if !is_positive && (prev_sig != ((sig + digit) / radix_t))
{ return Some(Float::neg_infinity()); }
}
prev_sig = sig;
},
None => match c {
'e' | 'E' | 'p' | 'P' => {
exp_info = Some((c, i + 1));
break; // start of exponent
},
'.' => {
break; // start of fractional part
},
_ => {
return None;
},
},
}
}
// If we are not yet at the exponent parse the fractional
// part of the significand
if exp_info.is_none() {
let mut power = _1;
for (i, c) in cs {
match c.to_digit(radix) {
Some(digit) => {
let digit: T = num::cast(digit).unwrap();
// Decrease power one order of magnitude
power = power / radix_t;
// add/subtract current digit depending on sign
sig = if is_positive {
sig + digit * power
} else {
sig - digit * power
};
// Detect overflow by comparing to last value
if is_positive && sig < prev_sig
{ return Some(Float::infinity()); }
if !is_positive && sig > prev_sig
{ return Some(Float::neg_infinity()); }
prev_sig = sig;
},
None => match c {
'e' | 'E' | 'p' | 'P' => {
exp_info = Some((c, i + 1));
break; // start of exponent
},
_ => {
return None; // invalid number
},
},
}
}
}
// Parse and calculate the exponent
let exp = match exp_info {
Some((c, offset)) => {
let base: T = match c {
'E' | 'e' if radix == 10 => num::cast(10u).unwrap(),
'P' | 'p' if radix == 16 => num::cast(2u).unwrap(),
_ => return None,
};
// Parse the exponent as decimal integer
let src = src[offset..];
let (is_positive, exp) = match src.slice_shift_char() {
(Some('-'), src) => (false, from_str::<uint>(src)),
(Some('+'), src) => (true, from_str::<uint>(src)),
(Some(_), _) => (true, from_str::<uint>(src)),
(None, _) => return None,
};
match (is_positive, exp) {
(true, Some(exp)) => base.powi(exp as i32),
(false, Some(exp)) => _1 / base.powi(exp as i32),
(_, None) => return None,
}
},
None => _1, // no exponent
};
Some(sig * exp)
}
pub fn from_str_radix_int<T: Int>(src: &str, radix: uint) -> Option<T> {
assert!(radix >= 2 && radix <= 36,
"from_str_radix_int: must lie in the range `[2, 36]` - found {}",
radix);
fn cast<T: Int>(x: uint) -> T {
num::cast(x).unwrap()
}
let _0: T = Int::zero();
let _1: T = Int::one();
let is_signed = _0 > Int::min_value();
let (is_positive, src) = match src.slice_shift_char() {
(Some('-'), src) if is_signed => (false, src),
(Some(_), _) => (true, src),
(None, _) => return None,
};
let mut xs = src.chars().map(|c| {
c.to_digit(radix).map(cast)
});
let radix = cast(radix);
let mut result = _0;
if is_positive {
for x in xs {
let x = match x {
Some(x) => x,
None => return None,
};
result = match result.checked_mul(radix) {
Some(result) => result,
None => return None,
};
result = match result.checked_add(x) {
Some(result) => result,
None => return None,
};
}
} else {
for x in xs {
let x = match x {
Some(x) => x,
None => return None,
};
result = match result.checked_mul(radix) {
Some(result) => result,
None => return None,
};
result = match result.checked_sub(x) {
Some(result) => result,
None => return None,
};
}
}
Some(result)
}
#[cfg(test)] #[cfg(test)]
mod test { mod tests {
use super::*; use string::ToString;
use option::*;
use num::Float;
#[test] #[test]
fn from_str_issue7588() { fn test_int_to_str_overflow() {
let u : Option<u8> = from_str_radix_int("1000", 10); let mut i8_val: i8 = 127_i8;
assert_eq!(u, None); assert_eq!(i8_val.to_string(), "127".to_string());
let s : Option<i16> = from_str_radix_int("80000", 10);
assert_eq!(s, None);
let f : Option<f32> = from_str_radix_float("10000000000000000000000000000000000000000", 10);
assert_eq!(f, Some(Float::infinity()))
let fe : Option<f32> = from_str_radix_float("1e40", 10);
assert_eq!(fe, Some(Float::infinity()))
}
#[test] i8_val += 1 as i8;
fn test_from_str_radix_float() { assert_eq!(i8_val.to_string(), "-128".to_string());
let x1 : Option<f64> = from_str_radix_float("-123.456", 10);
assert_eq!(x1, Some(-123.456)); let mut i16_val: i16 = 32_767_i16;
let x2 : Option<f32> = from_str_radix_float("123.456", 10); assert_eq!(i16_val.to_string(), "32767".to_string());
assert_eq!(x2, Some(123.456));
let x3 : Option<f32> = from_str_radix_float("-0.0", 10); i16_val += 1 as i16;
assert_eq!(x3, Some(-0.0)); assert_eq!(i16_val.to_string(), "-32768".to_string());
let x4 : Option<f32> = from_str_radix_float("0.0", 10);
assert_eq!(x4, Some(0.0)); let mut i32_val: i32 = 2_147_483_647_i32;
let x4 : Option<f32> = from_str_radix_float("1.0", 10); assert_eq!(i32_val.to_string(), "2147483647".to_string());
assert_eq!(x4, Some(1.0));
let x5 : Option<f32> = from_str_radix_float("-1.0", 10); i32_val += 1 as i32;
assert_eq!(x5, Some(-1.0)); assert_eq!(i32_val.to_string(), "-2147483648".to_string());
let mut i64_val: i64 = 9_223_372_036_854_775_807_i64;
assert_eq!(i64_val.to_string(), "9223372036854775807".to_string());
i64_val += 1 as i64;
assert_eq!(i64_val.to_string(), "-9223372036854775808".to_string());
} }
} }

View file

@ -13,11 +13,6 @@
#![unstable] #![unstable]
#![doc(primitive = "u16")] #![doc(primitive = "u16")]
use from_str::FromStr;
use num::FromStrRadix;
use num::strconv;
use option::Option;
pub use core::u16::{BITS, BYTES, MIN, MAX}; pub use core::u16::{BITS, BYTES, MIN, MAX};
uint_module!(u16) uint_module!(u16)

View file

@ -13,11 +13,6 @@
#![unstable] #![unstable]
#![doc(primitive = "u32")] #![doc(primitive = "u32")]
use from_str::FromStr;
use num::FromStrRadix;
use num::strconv;
use option::Option;
pub use core::u32::{BITS, BYTES, MIN, MAX}; pub use core::u32::{BITS, BYTES, MIN, MAX};
uint_module!(u32) uint_module!(u32)

View file

@ -13,11 +13,6 @@
#![unstable] #![unstable]
#![doc(primitive = "u64")] #![doc(primitive = "u64")]
use from_str::FromStr;
use num::FromStrRadix;
use num::strconv;
use option::Option;
pub use core::u64::{BITS, BYTES, MIN, MAX}; pub use core::u64::{BITS, BYTES, MIN, MAX};
uint_module!(u64) uint_module!(u64)

View file

@ -13,11 +13,6 @@
#![unstable] #![unstable]
#![doc(primitive = "u8")] #![doc(primitive = "u8")]
use from_str::FromStr;
use num::FromStrRadix;
use num::strconv;
use option::Option;
pub use core::u8::{BITS, BYTES, MIN, MAX}; pub use core::u8::{BITS, BYTES, MIN, MAX};
uint_module!(u8) uint_module!(u8)

View file

@ -13,11 +13,6 @@
#![unstable] #![unstable]
#![doc(primitive = "uint")] #![doc(primitive = "uint")]
use from_str::FromStr;
use num::FromStrRadix;
use num::strconv;
use option::Option;
pub use core::uint::{BITS, BYTES, MIN, MAX}; pub use core::uint::{BITS, BYTES, MIN, MAX};
uint_module!(uint) uint_module!(uint)

View file

@ -15,22 +15,6 @@
macro_rules! uint_module (($T:ty) => ( macro_rules! uint_module (($T:ty) => (
#[experimental = "might need to return Result"]
impl FromStr for $T {
#[inline]
fn from_str(s: &str) -> Option<$T> {
strconv::from_str_radix_int(s, 10)
}
}
#[experimental = "might need to return Result"]
impl FromStrRadix for $T {
#[inline]
fn from_str_radix(s: &str, radix: uint) -> Option<$T> {
strconv::from_str_radix_int(s, radix)
}
}
// String conversion functions and impl num -> str // String conversion functions and impl num -> str
/// Convert to a string as a byte slice in a given base. /// Convert to a string as a byte slice in a given base.

View file

@ -51,8 +51,7 @@ use result::{Err, Ok, Result};
use slice::{AsSlice, SlicePrelude, PartialEqSlicePrelude}; use slice::{AsSlice, SlicePrelude, PartialEqSlicePrelude};
use slice::CloneSliceAllocPrelude; use slice::CloneSliceAllocPrelude;
use str::{Str, StrPrelude, StrAllocating}; use str::{Str, StrPrelude, StrAllocating};
use string::String; use string::{String, ToString};
use to_string::ToString;
use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst}; use sync::atomic::{AtomicInt, INIT_ATOMIC_INT, SeqCst};
use vec::Vec; use vec::Vec;

View file

@ -13,12 +13,11 @@
use c_str::{CString, ToCStr}; use c_str::{CString, ToCStr};
use clone::Clone; use clone::Clone;
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use from_str::FromStr;
use hash; use hash;
use io::Writer; use io::Writer;
use iter::{DoubleEndedIterator, AdditiveIterator, Extend, Iterator, Map}; use iter::{DoubleEndedIterator, AdditiveIterator, Extend, Iterator, Map};
use option::{Option, None, Some}; use option::{Option, None, Some};
use str::Str; use str::{FromStr, Str};
use str; use str;
use slice::{CloneSliceAllocPrelude, Splits, AsSlice, VectorVector, use slice::{CloneSliceAllocPrelude, Splits, AsSlice, VectorVector,
PartialEqSlicePrelude, SlicePrelude}; PartialEqSlicePrelude, SlicePrelude};

View file

@ -16,14 +16,13 @@ use ascii::AsciiCast;
use c_str::{CString, ToCStr}; use c_str::{CString, ToCStr};
use clone::Clone; use clone::Clone;
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use from_str::FromStr;
use hash; use hash;
use io::Writer; use io::Writer;
use iter::{AdditiveIterator, DoubleEndedIterator, Extend, Iterator, Map}; use iter::{AdditiveIterator, DoubleEndedIterator, Extend, Iterator, Map};
use mem; use mem;
use option::{Option, Some, None}; use option::{Option, Some, None};
use slice::{AsSlice, SlicePrelude}; use slice::{AsSlice, SlicePrelude};
use str::{CharSplits, Str, StrAllocating, StrVector, StrPrelude}; use str::{CharSplits, FromStr, Str, StrAllocating, StrVector, StrPrelude};
use string::String; use string::String;
use unicode::char::UnicodeChar; use unicode::char::UnicodeChar;
use vec::Vec; use vec::Vec;

View file

@ -50,9 +50,9 @@
#[doc(no_inline)] pub use ops::{Fn, FnMut, FnOnce}; #[doc(no_inline)] pub use ops::{Fn, FnMut, FnOnce};
// Reexported functions // Reexported functions
#[doc(no_inline)] pub use from_str::from_str;
#[doc(no_inline)] pub use iter::{range, repeat}; #[doc(no_inline)] pub use iter::{range, repeat};
#[doc(no_inline)] pub use mem::drop; #[doc(no_inline)] pub use mem::drop;
#[doc(no_inline)] pub use str::from_str;
// Reexported types and traits // Reexported types and traits
@ -76,14 +76,13 @@
#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek, BufferPrelude}; #[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek, BufferPrelude};
#[doc(no_inline)] pub use str::{Str, StrVector, StrPrelude}; #[doc(no_inline)] pub use str::{Str, StrVector, StrPrelude};
#[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating, UnicodeStrPrelude}; #[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating, UnicodeStrPrelude};
#[doc(no_inline)] pub use to_string::{ToString, IntoStr};
#[doc(no_inline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4}; #[doc(no_inline)] pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
#[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8}; #[doc(no_inline)] pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
#[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12}; #[doc(no_inline)] pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
#[doc(no_inline)] pub use slice::{SlicePrelude, AsSlice, CloneSlicePrelude}; #[doc(no_inline)] pub use slice::{SlicePrelude, AsSlice, CloneSlicePrelude};
#[doc(no_inline)] pub use slice::{VectorVector, PartialEqSlicePrelude, OrdSlicePrelude}; #[doc(no_inline)] pub use slice::{VectorVector, PartialEqSlicePrelude, OrdSlicePrelude};
#[doc(no_inline)] pub use slice::{CloneSliceAllocPrelude, OrdSliceAllocPrelude, SliceAllocPrelude}; #[doc(no_inline)] pub use slice::{CloneSliceAllocPrelude, OrdSliceAllocPrelude, SliceAllocPrelude};
#[doc(no_inline)] pub use string::String; #[doc(no_inline)] pub use string::{IntoString, String, ToString};
#[doc(no_inline)] pub use vec::Vec; #[doc(no_inline)] pub use vec::Vec;
// Reexported runtime types // Reexported runtime types

View file

@ -12,13 +12,12 @@
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
use from_str::from_str;
use io::{IoResult, Writer}; use io::{IoResult, Writer};
use iter::Iterator; use iter::Iterator;
use option::{Some, None}; use option::{Some, None};
use os; use os;
use result::{Ok, Err}; use result::{Ok, Err};
use str::StrPrelude; use str::{StrPrelude, from_str};
use sync::atomic; use sync::atomic;
use unicode::char::UnicodeChar; use unicode::char::UnicodeChar;

View file

@ -8,12 +8,10 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use from_str::FromStr;
use from_str::from_str;
use libc::uintptr_t; use libc::uintptr_t;
use option::{Some, None, Option}; use option::{Some, None, Option};
use os; use os;
use str::Str; use str::{FromStr, from_str, Str};
use sync::atomic; use sync::atomic;
/// Dynamically inquire about whether we're running under V. /// Dynamically inquire about whether we're running under V.

View file

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at // file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT. // http://rust-lang.org/COPYRIGHT.
// //
@ -12,91 +12,195 @@
use core::prelude::*; use core::prelude::*;
use task;
use task::spawn; use task::spawn;
use vec::Vec; use comm::{channel, Sender, Receiver};
use comm::{channel, Sender}; use sync::{Arc, Mutex};
enum Msg<T> { struct Sentinel<'a> {
Execute(proc(&T):Send), jobs: &'a Arc<Mutex<Receiver<proc(): Send>>>,
Quit active: bool
} }
/// A task pool used to execute functions in parallel. impl<'a> Sentinel<'a> {
pub struct TaskPool<T> { fn new(jobs: &Arc<Mutex<Receiver<proc(): Send>>>) -> Sentinel {
channels: Vec<Sender<Msg<T>>>, Sentinel {
next_index: uint, jobs: jobs,
active: true
}
}
// Cancel and destroy this sentinel.
fn cancel(mut self) {
self.active = false;
}
} }
#[unsafe_destructor] #[unsafe_destructor]
impl<T> Drop for TaskPool<T> { impl<'a> Drop for Sentinel<'a> {
fn drop(&mut self) { fn drop(&mut self) {
for channel in self.channels.iter_mut() { if self.active {
channel.send(Quit); spawn_in_pool(self.jobs.clone())
} }
} }
} }
impl<T> TaskPool<T> { /// A task pool used to execute functions in parallel.
/// Spawns a new task pool with `n_tasks` tasks. The provided ///
/// `init_fn_factory` returns a function which, given the index of the /// Spawns `n` worker tasks and replenishes the pool if any worker tasks
/// task, should return local data to be kept around in that task. /// panic.
///
/// # Example
///
/// ```rust
/// # use std::sync::TaskPool;
/// # use std::iter::AdditiveIterator;
///
/// let pool = TaskPool::new(4u);
///
/// let (tx, rx) = channel();
/// for _ in range(0, 8u) {
/// let tx = tx.clone();
/// pool.execute(proc() {
/// tx.send(1u);
/// });
/// }
///
/// assert_eq!(rx.iter().take(8u).sum(), 8u);
/// ```
pub struct TaskPool {
// How the taskpool communicates with subtasks.
//
// This is the only such Sender, so when it is dropped all subtasks will
// quit.
jobs: Sender<proc(): Send>
}
impl TaskPool {
/// Spawns a new task pool with `tasks` tasks.
/// ///
/// # Panics /// # Panics
/// ///
/// This function will panic if `n_tasks` is less than 1. /// This function will panic if `tasks` is 0.
pub fn new(n_tasks: uint, pub fn new(tasks: uint) -> TaskPool {
init_fn_factory: || -> proc(uint):Send -> T) assert!(tasks >= 1);
-> TaskPool<T> {
assert!(n_tasks >= 1);
let channels = Vec::from_fn(n_tasks, |i| { let (tx, rx) = channel::<proc(): Send>();
let (tx, rx) = channel::<Msg<T>>(); let rx = Arc::new(Mutex::new(rx));
let init_fn = init_fn_factory();
let task_body = proc() { // Taskpool tasks.
let local_data = init_fn(i); for _ in range(0, tasks) {
loop { spawn_in_pool(rx.clone());
match rx.recv() { }
Execute(f) => f(&local_data),
Quit => break TaskPool { jobs: tx }
} }
}
/// Executes the function `job` on a task in the pool.
pub fn execute(&self, job: proc():Send) {
self.jobs.send(job);
}
}
fn spawn_in_pool(jobs: Arc<Mutex<Receiver<proc(): Send>>>) {
spawn(proc() {
// Will spawn a new task on panic unless it is cancelled.
let sentinel = Sentinel::new(&jobs);
loop {
let message = {
// Only lock jobs for the time it takes
// to get a job, not run it.
let lock = jobs.lock();
lock.recv_opt()
}; };
// Run on this scheduler. match message {
task::spawn(task_body); Ok(job) => job(),
tx // The Taskpool was dropped.
}); Err(..) => break
}
}
return TaskPool { sentinel.cancel();
channels: channels, })
next_index: 0, }
};
#[cfg(test)]
mod test {
use core::prelude::*;
use super::*;
use comm::channel;
use iter::range;
const TEST_TASKS: uint = 4u;
#[test]
fn test_works() {
use iter::AdditiveIterator;
let pool = TaskPool::new(TEST_TASKS);
let (tx, rx) = channel();
for _ in range(0, TEST_TASKS) {
let tx = tx.clone();
pool.execute(proc() {
tx.send(1u);
});
}
assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS);
} }
/// Executes the function `f` on a task in the pool. The function #[test]
/// receives a reference to the local data returned by the `init_fn`. #[should_fail]
pub fn execute(&mut self, f: proc(&T):Send) { fn test_zero_tasks_panic() {
self.channels[self.next_index].send(Execute(f)); TaskPool::new(0);
self.next_index += 1; }
if self.next_index == self.channels.len() { self.next_index = 0; }
#[test]
fn test_recovery_from_subtask_panic() {
use iter::AdditiveIterator;
let pool = TaskPool::new(TEST_TASKS);
// Panic all the existing tasks.
for _ in range(0, TEST_TASKS) {
pool.execute(proc() { panic!() });
}
// Ensure new tasks were spawned to compensate.
let (tx, rx) = channel();
for _ in range(0, TEST_TASKS) {
let tx = tx.clone();
pool.execute(proc() {
tx.send(1u);
});
}
assert_eq!(rx.iter().take(TEST_TASKS).sum(), TEST_TASKS);
}
#[test]
fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() {
use sync::{Arc, Barrier};
let pool = TaskPool::new(TEST_TASKS);
let waiter = Arc::new(Barrier::new(TEST_TASKS + 1));
// Panic all the existing tasks in a bit.
for _ in range(0, TEST_TASKS) {
let waiter = waiter.clone();
pool.execute(proc() {
waiter.wait();
panic!();
});
}
drop(pool);
// Kick off the failure.
waiter.wait();
} }
} }
#[test]
fn test_task_pool() {
let f: || -> proc(uint):Send -> uint = || { proc(i) i };
let mut pool = TaskPool::new(4, f);
for _ in range(0u, 8) {
pool.execute(proc(i) println!("Hello from thread {}!", *i));
}
}
#[test]
#[should_fail]
fn test_zero_tasks_panic() {
let f: || -> proc(uint):Send -> uint = || { proc(i) i };
TaskPool::new(0, f);
}

View file

@ -105,9 +105,8 @@ use rt::local::Local;
use rt::task; use rt::task;
use rt::task::Task; use rt::task::Task;
use str::{Str, SendStr, IntoMaybeOwned}; use str::{Str, SendStr, IntoMaybeOwned};
use string::String; use string::{String, ToString};
use sync::Future; use sync::Future;
use to_string::ToString;
/// A means of spawning a task /// A means of spawning a task
pub trait Spawner { pub trait Spawner {

View file

@ -388,7 +388,7 @@ mod tests {
use super::{Duration, MIN, MAX}; use super::{Duration, MIN, MAX};
use {i32, i64}; use {i32, i64};
use option::{Some, None}; use option::{Some, None};
use to_string::ToString; use string::ToString;
#[test] #[test]
fn test_duration() { fn test_duration() {

View file

@ -1,66 +0,0 @@
// 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.
/*!
The `ToString` trait for converting to strings
*/
#![experimental]
use fmt;
use string::String;
/// A generic trait for converting a value to a string
pub trait ToString {
/// Converts the value of `self` to an owned string
fn to_string(&self) -> String;
}
/// Trait for converting a type to a string, consuming it in the process.
pub trait IntoStr {
/// Consume and convert to a string.
fn into_string(self) -> String;
}
impl<T: fmt::Show> ToString for T {
fn to_string(&self) -> String {
format!("{}", *self)
}
}
#[cfg(test)]
mod tests {
use prelude::*;
use super::*;
#[test]
fn test_simple_types() {
assert_eq!(1i.to_string(), "1".to_string());
assert_eq!((-1i).to_string(), "-1".to_string());
assert_eq!(200u.to_string(), "200".to_string());
assert_eq!(2u8.to_string(), "2".to_string());
assert_eq!(true.to_string(), "true".to_string());
assert_eq!(false.to_string(), "false".to_string());
assert_eq!(().to_string(), "()".to_string());
assert_eq!(("hi".to_string()).to_string(), "hi".to_string());
}
#[test]
fn test_vectors() {
let x: Vec<int> = vec![];
assert_eq!(x.to_string(), "[]".to_string());
assert_eq!((vec![1i]).to_string(), "[1]".to_string());
assert_eq!((vec![1i, 2, 3]).to_string(), "[1, 2, 3]".to_string());
assert!((vec![vec![], vec![1i], vec![1i, 1]]).to_string() ==
"[[], [1], [1, 1]]".to_string());
}
}

View file

@ -22,19 +22,23 @@
//! would generate two implementations like: //! would generate two implementations like:
//! //!
//! ```ignore //! ```ignore
//! impl<S:serialize::Encoder> Encodable<S> for Node { //! impl<S: Encoder<E>, E> Encodable<S, E> for Node {
//! fn encode(&self, s: &S) { //! fn encode(&self, s: &mut S) -> Result<(), E> {
//! s.emit_struct("Node", 1, || { //! s.emit_struct("Node", 1, |this| {
//! s.emit_field("id", 0, || s.emit_uint(self.id)) //! this.emit_struct_field("id", 0, |this| {
//! Encodable::encode(&self.id, this)
//! /* this.emit_uint(self.id) can also be used */
//! })
//! }) //! })
//! } //! }
//! } //! }
//! //!
//! impl<D:Decoder> Decodable for node_id { //! impl<D: Decoder<E>, E> Decodable<D, E> for Node {
//! fn decode(d: &D) -> Node { //! fn decode(d: &mut D) -> Result<Node, E> {
//! d.read_struct("Node", 1, || { //! d.read_struct("Node", 1, |this| {
//! Node { //! match this.read_struct_field("id", 0, |this| Decodable::decode(this)) {
//! id: d.read_field("x".to_string(), 0, || decode(d)) //! Ok(id) => Ok(Node { id: id }),
//! Err(e) => Err(e),
//! } //! }
//! }) //! })
//! } //! }
@ -46,37 +50,42 @@
//! //!
//! ```ignore //! ```ignore
//! #[deriving(Encodable, Decodable)] //! #[deriving(Encodable, Decodable)]
//! struct spanned<T> { node: T, span: Span } //! struct Spanned<T> { node: T, span: Span }
//! ``` //! ```
//! //!
//! would yield functions like: //! would yield functions like:
//! //!
//! ```ignore //! ```ignore
//! impl< //! impl<
//! S: Encoder, //! S: Encoder<E>,
//! T: Encodable<S> //! E,
//! > spanned<T>: Encodable<S> { //! T: Encodable<S, E>
//! fn encode<S:Encoder>(s: &S) { //! > Encodable<S, E> for Spanned<T> {
//! s.emit_rec(|| { //! fn encode(&self, s: &mut S) -> Result<(), E> {
//! s.emit_field("node", 0, || self.node.encode(s)); //! s.emit_struct("Spanned", 2, |this| {
//! s.emit_field("span", 1, || self.span.encode(s)); //! this.emit_struct_field("node", 0, |this| self.node.encode(this))
//! }) //! .ok().unwrap();
//! } //! this.emit_struct_field("span", 1, |this| self.span.encode(this))
//! })
//! } //! }
//! }
//! //!
//! impl< //! impl<
//! D: Decoder, //! D: Decoder<E>,
//! T: Decodable<D> //! E,
//! > spanned<T>: Decodable<D> { //! T: Decodable<D, E>
//! fn decode(d: &D) -> spanned<T> { //! > Decodable<D, E> for Spanned<T> {
//! d.read_rec(|| { //! fn decode(d: &mut D) -> Result<Spanned<T>, E> {
//! { //! d.read_struct("Spanned", 2, |this| {
//! node: d.read_field("node".to_string(), 0, || decode(d)), //! Ok(Spanned {
//! span: d.read_field("span".to_string(), 1, || decode(d)), //! node: this.read_struct_field("node", 0, |this| Decodable::decode(this))
//! } //! .ok().unwrap(),
//! span: this.read_struct_field("span", 1, |this| Decodable::decode(this))
//! .ok().unwrap(),
//! }) //! })
//! } //! })
//! } //! }
//! }
//! ``` //! ```
use ast::{MetaItem, Item, Expr, ExprRet, MutMutable, LitNil}; use ast::{MetaItem, Item, Expr, ExprRet, MutMutable, LitNil};

View file

@ -53,13 +53,13 @@ use std::cmp;
use std::f64; use std::f64;
use std::fmt::Show; use std::fmt::Show;
use std::fmt; use std::fmt;
use std::from_str::FromStr;
use std::io::fs::PathExtensions; use std::io::fs::PathExtensions;
use std::io::stdio::StdWriter; use std::io::stdio::StdWriter;
use std::io::{File, ChanReader, ChanWriter}; use std::io::{File, ChanReader, ChanWriter};
use std::io; use std::io;
use std::num::{Float, FloatMath, Int}; use std::num::{Float, FloatMath, Int};
use std::os; use std::os;
use std::str::FromStr;
use std::string::String; use std::string::String;
use std::task::TaskBuilder; use std::task::TaskBuilder;
use std::time::Duration; use std::time::Duration;

View file

@ -0,0 +1,24 @@
-include ../tools.mk
all:
#Option taking a number
$(RUSTC) -C codegen-units dummy.rs 2>&1 | \
grep 'codegen option `codegen-units` requires a number'
$(RUSTC) -C codegen-units= dummy.rs 2>&1 | \
grep 'incorrect value `` for codegen option `codegen-units` - a number was expected'
$(RUSTC) -C codegen-units=foo dummy.rs 2>&1 | \
grep 'incorrect value `foo` for codegen option `codegen-units` - a number was expected'
$(RUSTC) -C codegen-units=1 dummy.rs
#Option taking a string
$(RUSTC) -C extra-filename dummy.rs 2>&1 | \
grep 'codegen option `extra-filename` requires a string'
$(RUSTC) -C extra-filename= dummy.rs 2>&1
$(RUSTC) -C extra-filename=foo dummy.rs 2>&1
#Option taking no argument
$(RUSTC) -C lto= dummy.rs 2>&1 | \
grep 'codegen option `lto` takes no value'
$(RUSTC) -C lto=1 dummy.rs 2>&1 | \
grep 'codegen option `lto` takes no value'
$(RUSTC) -C lto=foo dummy.rs 2>&1 | \
grep 'codegen option `lto` takes no value'
$(RUSTC) -C lto dummy.rs

View file

@ -0,0 +1,11 @@
// 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.
fn main() {}

View file

@ -11,7 +11,7 @@
// aux-build:cci_class_cast.rs // aux-build:cci_class_cast.rs
extern crate cci_class_cast; extern crate cci_class_cast;
use std::to_string::ToString; use std::string::ToString;
use cci_class_cast::kitty::cat; use cci_class_cast::kitty::cat;
fn print_out(thing: Box<ToString>, expected: String) { fn print_out(thing: Box<ToString>, expected: String) {

View file

@ -11,7 +11,7 @@
extern crate collections; extern crate collections;
use std::str::{SendStr, Owned, Slice}; use std::str::{SendStr, Owned, Slice};
use std::to_string::ToString; use std::string::ToString;
use self::collections::TreeMap; use self::collections::TreeMap;
use std::option::Some; use std::option::Some;