Merge remote-tracking branch 'remotes/origin/master' into remove-str-trailing-nulls
This commit is contained in:
commit
a54476b0aa
41 changed files with 918 additions and 882 deletions
|
@ -297,7 +297,7 @@ COMPILER_INPUTS := $(wildcard $(addprefix $(S)src/librustc/, \
|
|||
|
||||
LIBSYNTAX_CRATE := $(S)src/libsyntax/syntax.rs
|
||||
LIBSYNTAX_INPUTS := $(wildcard $(addprefix $(S)src/libsyntax/, \
|
||||
*.rs */*.rs */*/*.rs))
|
||||
*.rs */*.rs */*/*.rs */*/*/*.rs))
|
||||
|
||||
DRIVER_CRATE := $(S)src/driver/driver.rs
|
||||
|
||||
|
|
|
@ -544,7 +544,7 @@ an intermediate generation has already exited:
|
|||
~~~
|
||||
# use std::task;
|
||||
# fn sleep_forever() { loop { task::yield() } }
|
||||
# fn wait_for_a_while() { do 1000.times { task::yield() } }
|
||||
# fn wait_for_a_while() { for _ in range(0, 1000u) { task::yield() } }
|
||||
# do task::try::<int> {
|
||||
do task::spawn_supervised {
|
||||
do task::spawn_supervised {
|
||||
|
@ -563,7 +563,7 @@ other at all, using `task::spawn_unlinked` for _isolated failure_.
|
|||
~~~
|
||||
# use std::task;
|
||||
# fn random() -> uint { 100 }
|
||||
# fn sleep_for(i: uint) { do i.times { task::yield() } }
|
||||
# fn sleep_for(i: uint) { for _ in range(0, i) { task::yield() } }
|
||||
# do task::try::<()> {
|
||||
let (time1, time2) = (random(), random());
|
||||
do task::spawn_unlinked {
|
||||
|
|
|
@ -1894,7 +1894,7 @@ struct TimeBomb {
|
|||
|
||||
impl Drop for TimeBomb {
|
||||
fn drop(&self) {
|
||||
do self.explosivity.times {
|
||||
for _ in range(0, self.explosivity) {
|
||||
println("blam!");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
//! Base64 binary-to-text encoding
|
||||
use std::str;
|
||||
|
||||
/// Available encoding character sets
|
||||
pub enum CharacterSet {
|
||||
|
@ -40,21 +41,13 @@ pub static URL_SAFE: Config =
|
|||
pub static MIME: Config =
|
||||
Config {char_set: Standard, pad: true, line_length: Some(76)};
|
||||
|
||||
static STANDARD_CHARS: [char, ..64] = [
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
||||
];
|
||||
static STANDARD_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
"abcdefghijklmnopqrstuvwxyz",
|
||||
"0123456789+/");
|
||||
|
||||
static URLSAFE_CHARS: [char, ..64] = [
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
|
||||
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
|
||||
];
|
||||
static URLSAFE_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||
"abcdefghijklmnopqrstuvwxyz",
|
||||
"0123456789-_");
|
||||
|
||||
/// A trait for converting a value to base64 encoding.
|
||||
pub trait ToBase64 {
|
||||
|
@ -80,12 +73,12 @@ impl<'self> ToBase64 for &'self [u8] {
|
|||
* ~~~
|
||||
*/
|
||||
fn to_base64(&self, config: Config) -> ~str {
|
||||
let chars = match config.char_set {
|
||||
let bytes = match config.char_set {
|
||||
Standard => STANDARD_CHARS,
|
||||
UrlSafe => URLSAFE_CHARS
|
||||
};
|
||||
|
||||
let mut s = ~"";
|
||||
let mut v: ~[u8] = ~[];
|
||||
let mut i = 0;
|
||||
let mut cur_length = 0;
|
||||
let len = self.len();
|
||||
|
@ -93,7 +86,8 @@ impl<'self> ToBase64 for &'self [u8] {
|
|||
match config.line_length {
|
||||
Some(line_length) =>
|
||||
if cur_length >= line_length {
|
||||
s.push_str("\r\n");
|
||||
v.push('\r' as u8);
|
||||
v.push('\n' as u8);
|
||||
cur_length = 0;
|
||||
},
|
||||
None => ()
|
||||
|
@ -104,10 +98,10 @@ impl<'self> ToBase64 for &'self [u8] {
|
|||
(self[i + 2] as u32);
|
||||
|
||||
// This 24-bit number gets separated into four 6-bit numbers.
|
||||
s.push_char(chars[(n >> 18) & 63]);
|
||||
s.push_char(chars[(n >> 12) & 63]);
|
||||
s.push_char(chars[(n >> 6 ) & 63]);
|
||||
s.push_char(chars[n & 63]);
|
||||
v.push(bytes[(n >> 18) & 63]);
|
||||
v.push(bytes[(n >> 12) & 63]);
|
||||
v.push(bytes[(n >> 6 ) & 63]);
|
||||
v.push(bytes[n & 63]);
|
||||
|
||||
cur_length += 4;
|
||||
i += 3;
|
||||
|
@ -117,7 +111,8 @@ impl<'self> ToBase64 for &'self [u8] {
|
|||
match config.line_length {
|
||||
Some(line_length) =>
|
||||
if cur_length >= line_length {
|
||||
s.push_str("\r\n");
|
||||
v.push('\r' as u8);
|
||||
v.push('\n' as u8);
|
||||
},
|
||||
None => ()
|
||||
}
|
||||
|
@ -129,48 +124,29 @@ impl<'self> ToBase64 for &'self [u8] {
|
|||
0 => (),
|
||||
1 => {
|
||||
let n = (self[i] as u32) << 16;
|
||||
s.push_char(chars[(n >> 18) & 63]);
|
||||
s.push_char(chars[(n >> 12) & 63]);
|
||||
v.push(bytes[(n >> 18) & 63]);
|
||||
v.push(bytes[(n >> 12) & 63]);
|
||||
if config.pad {
|
||||
s.push_str("==");
|
||||
v.push('=' as u8);
|
||||
v.push('=' as u8);
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
let n = (self[i] as u32) << 16 |
|
||||
(self[i + 1u] as u32) << 8;
|
||||
s.push_char(chars[(n >> 18) & 63]);
|
||||
s.push_char(chars[(n >> 12) & 63]);
|
||||
s.push_char(chars[(n >> 6 ) & 63]);
|
||||
v.push(bytes[(n >> 18) & 63]);
|
||||
v.push(bytes[(n >> 12) & 63]);
|
||||
v.push(bytes[(n >> 6 ) & 63]);
|
||||
if config.pad {
|
||||
s.push_char('=');
|
||||
v.push('=' as u8);
|
||||
}
|
||||
}
|
||||
_ => fail!("Algebra is broken, please alert the math police")
|
||||
}
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self> ToBase64 for &'self str {
|
||||
/**
|
||||
* Convert any string (literal, `@`, `&`, or `~`) to base64 encoding.
|
||||
*
|
||||
*
|
||||
* # Example
|
||||
*
|
||||
* ~~~ {.rust}
|
||||
* extern mod extra;
|
||||
* use extra::base64::{ToBase64, standard};
|
||||
*
|
||||
* fn main () {
|
||||
* let str = "Hello, World".to_base64(standard);
|
||||
* printfln!("%s", str);
|
||||
* }
|
||||
* ~~~
|
||||
*
|
||||
*/
|
||||
fn to_base64(&self, config: Config) -> ~str {
|
||||
self.as_bytes().to_base64(config)
|
||||
unsafe {
|
||||
str::raw::from_bytes_owned(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -181,76 +157,6 @@ pub trait FromBase64 {
|
|||
fn from_base64(&self) -> Result<~[u8], ~str>;
|
||||
}
|
||||
|
||||
impl<'self> FromBase64 for &'self [u8] {
|
||||
/**
|
||||
* Convert base64 `u8` vector into u8 byte values.
|
||||
* Every 4 encoded characters is converted into 3 octets, modulo padding.
|
||||
*
|
||||
* # Example
|
||||
*
|
||||
* ~~~ {.rust}
|
||||
* extern mod extra;
|
||||
* use extra::base64::{ToBase64, FromBase64, standard};
|
||||
*
|
||||
* fn main () {
|
||||
* let str = [52,32].to_base64(standard);
|
||||
* printfln!("%s", str);
|
||||
* let bytes = str.from_base64();
|
||||
* printfln!("%?", bytes);
|
||||
* }
|
||||
* ~~~
|
||||
*/
|
||||
fn from_base64(&self) -> Result<~[u8], ~str> {
|
||||
let mut r = ~[];
|
||||
let mut buf: u32 = 0;
|
||||
let mut modulus = 0;
|
||||
|
||||
let mut it = self.iter();
|
||||
for &byte in it {
|
||||
let ch = byte as char;
|
||||
let val = byte as u32;
|
||||
|
||||
match ch {
|
||||
'A'..'Z' => buf |= val - 0x41,
|
||||
'a'..'z' => buf |= val - 0x47,
|
||||
'0'..'9' => buf |= val + 0x04,
|
||||
'+'|'-' => buf |= 0x3E,
|
||||
'/'|'_' => buf |= 0x3F,
|
||||
'\r'|'\n' => loop,
|
||||
'=' => break,
|
||||
_ => return Err(~"Invalid Base64 character")
|
||||
}
|
||||
|
||||
buf <<= 6;
|
||||
modulus += 1;
|
||||
if modulus == 4 {
|
||||
modulus = 0;
|
||||
r.push((buf >> 22) as u8);
|
||||
r.push((buf >> 14) as u8);
|
||||
r.push((buf >> 6 ) as u8);
|
||||
}
|
||||
}
|
||||
|
||||
if !it.all(|&byte| {byte as char == '='}) {
|
||||
return Err(~"Invalid Base64 character");
|
||||
}
|
||||
|
||||
match modulus {
|
||||
2 => {
|
||||
r.push((buf >> 10) as u8);
|
||||
}
|
||||
3 => {
|
||||
r.push((buf >> 16) as u8);
|
||||
r.push((buf >> 8 ) as u8);
|
||||
}
|
||||
0 => (),
|
||||
_ => return Err(~"Invalid Base64 length")
|
||||
}
|
||||
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'self> FromBase64 for &'self str {
|
||||
/**
|
||||
* Convert any base64 encoded string (literal, `@`, `&`, or `~`)
|
||||
|
@ -280,7 +186,56 @@ impl<'self> FromBase64 for &'self str {
|
|||
* ~~~
|
||||
*/
|
||||
fn from_base64(&self) -> Result<~[u8], ~str> {
|
||||
self.as_bytes().from_base64()
|
||||
let mut r = ~[];
|
||||
let mut buf: u32 = 0;
|
||||
let mut modulus = 0;
|
||||
|
||||
let mut it = self.byte_iter().enumerate();
|
||||
for (idx, byte) in it {
|
||||
let val = byte as u32;
|
||||
|
||||
match byte as char {
|
||||
'A'..'Z' => buf |= val - 0x41,
|
||||
'a'..'z' => buf |= val - 0x47,
|
||||
'0'..'9' => buf |= val + 0x04,
|
||||
'+'|'-' => buf |= 0x3E,
|
||||
'/'|'_' => buf |= 0x3F,
|
||||
'\r'|'\n' => loop,
|
||||
'=' => break,
|
||||
_ => return Err(fmt!("Invalid character '%c' at position %u",
|
||||
self.char_at(idx), idx))
|
||||
}
|
||||
|
||||
buf <<= 6;
|
||||
modulus += 1;
|
||||
if modulus == 4 {
|
||||
modulus = 0;
|
||||
r.push((buf >> 22) as u8);
|
||||
r.push((buf >> 14) as u8);
|
||||
r.push((buf >> 6 ) as u8);
|
||||
}
|
||||
}
|
||||
|
||||
for (idx, byte) in it {
|
||||
if (byte as char) != '=' {
|
||||
return Err(fmt!("Invalid character '%c' at position %u",
|
||||
self.char_at(idx), idx));
|
||||
}
|
||||
}
|
||||
|
||||
match modulus {
|
||||
2 => {
|
||||
r.push((buf >> 10) as u8);
|
||||
}
|
||||
3 => {
|
||||
r.push((buf >> 16) as u8);
|
||||
r.push((buf >> 8 ) as u8);
|
||||
}
|
||||
0 => (),
|
||||
_ => return Err(~"Invalid Base64 length")
|
||||
}
|
||||
|
||||
Ok(r)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,27 +246,28 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn test_to_base64_basic() {
|
||||
assert_eq!("".to_base64(STANDARD), ~"");
|
||||
assert_eq!("f".to_base64(STANDARD), ~"Zg==");
|
||||
assert_eq!("fo".to_base64(STANDARD), ~"Zm8=");
|
||||
assert_eq!("foo".to_base64(STANDARD), ~"Zm9v");
|
||||
assert_eq!("foob".to_base64(STANDARD), ~"Zm9vYg==");
|
||||
assert_eq!("fooba".to_base64(STANDARD), ~"Zm9vYmE=");
|
||||
assert_eq!("foobar".to_base64(STANDARD), ~"Zm9vYmFy");
|
||||
assert_eq!("".as_bytes().to_base64(STANDARD), ~"");
|
||||
assert_eq!("f".as_bytes().to_base64(STANDARD), ~"Zg==");
|
||||
assert_eq!("fo".as_bytes().to_base64(STANDARD), ~"Zm8=");
|
||||
assert_eq!("foo".as_bytes().to_base64(STANDARD), ~"Zm9v");
|
||||
assert_eq!("foob".as_bytes().to_base64(STANDARD), ~"Zm9vYg==");
|
||||
assert_eq!("fooba".as_bytes().to_base64(STANDARD), ~"Zm9vYmE=");
|
||||
assert_eq!("foobar".as_bytes().to_base64(STANDARD), ~"Zm9vYmFy");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_base64_line_break() {
|
||||
assert!(![0u8, 1000].to_base64(Config {line_length: None, ..STANDARD})
|
||||
.contains("\r\n"));
|
||||
assert_eq!("foobar".to_base64(Config {line_length: Some(4), ..STANDARD}),
|
||||
assert_eq!("foobar".as_bytes().to_base64(Config {line_length: Some(4),
|
||||
..STANDARD}),
|
||||
~"Zm9v\r\nYmFy");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_base64_padding() {
|
||||
assert_eq!("f".to_base64(Config {pad: false, ..STANDARD}), ~"Zg");
|
||||
assert_eq!("fo".to_base64(Config {pad: false, ..STANDARD}), ~"Zm8");
|
||||
assert_eq!("f".as_bytes().to_base64(Config {pad: false, ..STANDARD}), ~"Zg");
|
||||
assert_eq!("fo".as_bytes().to_base64(Config {pad: false, ..STANDARD}), ~"Zm8");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -345,7 +301,7 @@ mod test {
|
|||
#[test]
|
||||
fn test_from_base64_invalid_char() {
|
||||
assert!("Zm$=".from_base64().is_err())
|
||||
assert!("Zg==$".from_base64().is_err());
|
||||
assert!("Zg==$".from_base64().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -369,20 +325,20 @@ mod test {
|
|||
}
|
||||
|
||||
#[bench]
|
||||
pub fn to_base64(bh: & mut BenchHarness) {
|
||||
pub fn bench_to_base64(bh: & mut BenchHarness) {
|
||||
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
|
||||
ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
|
||||
do bh.iter {
|
||||
s.to_base64(STANDARD);
|
||||
s.as_bytes().to_base64(STANDARD);
|
||||
}
|
||||
bh.bytes = s.len() as u64;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn from_base64(bh: & mut BenchHarness) {
|
||||
pub fn bench_from_base64(bh: & mut BenchHarness) {
|
||||
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
|
||||
ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
|
||||
let b = s.to_base64(STANDARD);
|
||||
let b = s.as_bytes().to_base64(STANDARD);
|
||||
do bh.iter {
|
||||
b.from_base64();
|
||||
}
|
||||
|
|
|
@ -102,6 +102,7 @@ pub mod stats;
|
|||
pub mod semver;
|
||||
pub mod fileinput;
|
||||
pub mod flate;
|
||||
pub mod hex;
|
||||
|
||||
#[cfg(unicode)]
|
||||
mod unicode;
|
||||
|
|
193
src/libextra/hex.rs
Normal file
193
src/libextra/hex.rs
Normal file
|
@ -0,0 +1,193 @@
|
|||
// Copyright 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.
|
||||
|
||||
//! Hex binary-to-text encoding
|
||||
use std::str;
|
||||
use std::vec;
|
||||
|
||||
/// A trait for converting a value to hexadecimal encoding
|
||||
pub trait ToHex {
|
||||
/// Converts the value of `self` to a hex value, returning the owned
|
||||
/// string.
|
||||
fn to_hex(&self) -> ~str;
|
||||
}
|
||||
|
||||
static CHARS: &'static[u8] = bytes!("0123456789abcdef");
|
||||
|
||||
impl<'self> ToHex for &'self [u8] {
|
||||
/**
|
||||
* Turn a vector of `u8` bytes into a hexadecimal string.
|
||||
*
|
||||
* # Example
|
||||
*
|
||||
* ~~~ {.rust}
|
||||
* extern mod extra;
|
||||
* use extra::hex::ToHex;
|
||||
*
|
||||
* fn main () {
|
||||
* let str = [52,32].to_hex();
|
||||
* printfln!("%s", str);
|
||||
* }
|
||||
* ~~~
|
||||
*/
|
||||
fn to_hex(&self) -> ~str {
|
||||
let mut v = vec::with_capacity(self.len() * 2);
|
||||
for &byte in self.iter() {
|
||||
v.push(CHARS[byte >> 4]);
|
||||
v.push(CHARS[byte & 0xf]);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
str::raw::from_bytes_owned(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for converting hexadecimal encoded values
|
||||
pub trait FromHex {
|
||||
/// Converts the value of `self`, interpreted as hexadecimal encoded data,
|
||||
/// into an owned vector of bytes, returning the vector.
|
||||
fn from_hex(&self) -> Result<~[u8], ~str>;
|
||||
}
|
||||
|
||||
impl<'self> FromHex for &'self str {
|
||||
/**
|
||||
* Convert any hexadecimal encoded string (literal, `@`, `&`, or `~`)
|
||||
* to the byte values it encodes.
|
||||
*
|
||||
* You can use the `from_bytes` function in `std::str`
|
||||
* to turn a `[u8]` into a string with characters corresponding to those
|
||||
* values.
|
||||
*
|
||||
* # Example
|
||||
*
|
||||
* This converts a string literal to hexadecimal and back.
|
||||
*
|
||||
* ~~~ {.rust}
|
||||
* extern mod extra;
|
||||
* use extra::hex::{FromHex, ToHex};
|
||||
* use std::str;
|
||||
*
|
||||
* fn main () {
|
||||
* let hello_str = "Hello, World".to_hex();
|
||||
* printfln!("%s", hello_str);
|
||||
* let bytes = hello_str.from_hex().unwrap();
|
||||
* printfln!("%?", bytes);
|
||||
* let result_str = str::from_bytes(bytes);
|
||||
* printfln!("%s", result_str);
|
||||
* }
|
||||
* ~~~
|
||||
*/
|
||||
fn from_hex(&self) -> Result<~[u8], ~str> {
|
||||
// This may be an overestimate if there is any whitespace
|
||||
let mut b = vec::with_capacity(self.len() / 2);
|
||||
let mut modulus = 0;
|
||||
let mut buf = 0u8;
|
||||
|
||||
for (idx, byte) in self.byte_iter().enumerate() {
|
||||
buf <<= 4;
|
||||
|
||||
match byte as char {
|
||||
'A'..'F' => buf |= byte - ('A' as u8) + 10,
|
||||
'a'..'f' => buf |= byte - ('a' as u8) + 10,
|
||||
'0'..'9' => buf |= byte - ('0' as u8),
|
||||
' '|'\r'|'\n'|'\t' => {
|
||||
buf >>= 4;
|
||||
loop
|
||||
}
|
||||
_ => return Err(fmt!("Invalid character '%c' at position %u",
|
||||
self.char_at(idx), idx))
|
||||
}
|
||||
|
||||
modulus += 1;
|
||||
if modulus == 2 {
|
||||
modulus = 0;
|
||||
b.push(buf);
|
||||
}
|
||||
}
|
||||
|
||||
match modulus {
|
||||
0 => Ok(b),
|
||||
_ => Err(~"Invalid input length")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use test::BenchHarness;
|
||||
use hex::*;
|
||||
|
||||
#[test]
|
||||
pub fn test_to_hex() {
|
||||
assert_eq!("foobar".as_bytes().to_hex(), ~"666f6f626172");
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_from_hex_okay() {
|
||||
assert_eq!("666f6f626172".from_hex().unwrap(),
|
||||
"foobar".as_bytes().to_owned());
|
||||
assert_eq!("666F6F626172".from_hex().unwrap(),
|
||||
"foobar".as_bytes().to_owned());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_from_hex_odd_len() {
|
||||
assert!("666".from_hex().is_err());
|
||||
assert!("66 6".from_hex().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_from_hex_invalid_char() {
|
||||
assert!("66y6".from_hex().is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_from_hex_ignores_whitespace() {
|
||||
assert_eq!("666f 6f6\r\n26172 ".from_hex().unwrap(),
|
||||
"foobar".as_bytes().to_owned());
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_to_hex_all_bytes() {
|
||||
for i in range(0, 256) {
|
||||
assert_eq!([i as u8].to_hex(), fmt!("%02x", i as uint));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_from_hex_all_bytes() {
|
||||
for i in range(0, 256) {
|
||||
assert_eq!(fmt!("%02x", i as uint).from_hex().unwrap(), ~[i as u8]);
|
||||
assert_eq!(fmt!("%02X", i as uint).from_hex().unwrap(), ~[i as u8]);
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn bench_to_hex(bh: & mut BenchHarness) {
|
||||
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
|
||||
ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
|
||||
do bh.iter {
|
||||
s.as_bytes().to_hex();
|
||||
}
|
||||
bh.bytes = s.len() as u64;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn bench_from_hex(bh: & mut BenchHarness) {
|
||||
let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
|
||||
ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
|
||||
let b = s.as_bytes().to_hex();
|
||||
do bh.iter {
|
||||
b.from_hex();
|
||||
}
|
||||
bh.bytes = b.len() as u64;
|
||||
}
|
||||
}
|
|
@ -1,331 +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.
|
||||
|
||||
/*! Composable internal iterators
|
||||
|
||||
Internal iterators are functions implementing the protocol used by the `for` loop.
|
||||
|
||||
An internal iterator takes `fn(...) -> bool` as a parameter, with returning `false` used to signal
|
||||
breaking out of iteration. The adaptors in the module work with any such iterator, not just ones
|
||||
tied to specific traits. For example:
|
||||
|
||||
~~~ {.rust}
|
||||
println(iter::to_vec(|f| uint::range(0, 20, f)).to_str());
|
||||
~~~
|
||||
|
||||
An external iterator object implementing the interface in the `iterator` module can be used as an
|
||||
internal iterator by calling the `advance` method. For example:
|
||||
|
||||
~~~ {.rust}
|
||||
let xs = [0u, 1, 2, 3, 4, 5];
|
||||
let ys = [30, 40, 50, 60];
|
||||
let mut it = xs.iter().chain(ys.iter());
|
||||
for &x: &uint in it {
|
||||
println(x.to_str());
|
||||
}
|
||||
~~~
|
||||
|
||||
Internal iterators provide a subset of the functionality of an external iterator. It's not possible
|
||||
to interleave them to implement algorithms like `zip`, `union` and `merge`. However, they're often
|
||||
much easier to implement.
|
||||
|
||||
*/
|
||||
|
||||
use std::vec;
|
||||
use std::cmp::Ord;
|
||||
use std::option::{Option, Some, None};
|
||||
use std::num::{One, Zero};
|
||||
use std::ops::{Add, Mul};
|
||||
|
||||
#[allow(missing_doc)]
|
||||
pub trait FromIter<T> {
|
||||
/// Build a container with elements from an internal iterator.
|
||||
///
|
||||
/// # Example:
|
||||
///
|
||||
/// ~~~ {.rust}
|
||||
/// let xs = ~[1, 2, 3];
|
||||
/// let ys: ~[int] = do FromIter::from_iter |f| { xs.iter().advance(|x| f(*x)) };
|
||||
/// assert_eq!(xs, ys);
|
||||
/// ~~~
|
||||
pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> Self;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if `predicate` is true for any values yielded by an internal iterator.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ~~~ {.rust}
|
||||
* let xs = ~[1u, 2, 3, 4, 5];
|
||||
* assert!(any(|&x: &uint| x > 2, |f| xs.iter().advance(f)));
|
||||
* assert!(!any(|&x: &uint| x > 5, |f| xs.iter().advance(f)));
|
||||
* ~~~
|
||||
*/
|
||||
#[inline]
|
||||
pub fn any<T>(predicate: &fn(T) -> bool,
|
||||
iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
|
||||
do iter |x| {
|
||||
predicate(x)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if `predicate` is true for all values yielded by an internal iterator.
|
||||
*
|
||||
* # Example:
|
||||
*
|
||||
* ~~~ {.rust}
|
||||
* assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f)));
|
||||
* assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f)));
|
||||
* ~~~
|
||||
*/
|
||||
#[inline]
|
||||
pub fn all<T>(predicate: &fn(T) -> bool,
|
||||
iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
|
||||
// If we ever break, iter will return false, so this will only return true
|
||||
// if predicate returns true for everything.
|
||||
iter(|x| predicate(x))
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first element where `predicate` returns `true`. Return `None` if no element is found.
|
||||
*
|
||||
* # Example:
|
||||
*
|
||||
* ~~~ {.rust}
|
||||
* let xs = ~[1u, 2, 3, 4, 5, 6];
|
||||
* assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.iter().advance(f)).unwrap(), 4);
|
||||
* ~~~
|
||||
*/
|
||||
#[inline]
|
||||
pub fn find<T>(predicate: &fn(&T) -> bool,
|
||||
iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
|
||||
let mut ret = None;
|
||||
do iter |x| {
|
||||
if predicate(&x) {
|
||||
ret = Some(x);
|
||||
false
|
||||
} else { true }
|
||||
};
|
||||
ret
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the largest item yielded by an iterator. Return `None` if the iterator is empty.
|
||||
*
|
||||
* # Example:
|
||||
*
|
||||
* ~~~ {.rust}
|
||||
* let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
|
||||
* assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &15);
|
||||
* ~~~
|
||||
*/
|
||||
#[inline]
|
||||
pub fn max<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
|
||||
let mut result = None;
|
||||
do iter |x| {
|
||||
match result {
|
||||
Some(ref mut y) => {
|
||||
if x > *y {
|
||||
*y = x;
|
||||
}
|
||||
}
|
||||
None => result = Some(x)
|
||||
}
|
||||
true
|
||||
};
|
||||
result
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the smallest item yielded by an iterator. Return `None` if the iterator is empty.
|
||||
*
|
||||
* # Example:
|
||||
*
|
||||
* ~~~ {.rust}
|
||||
* let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
|
||||
* assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &-5);
|
||||
* ~~~
|
||||
*/
|
||||
#[inline]
|
||||
pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
|
||||
let mut result = None;
|
||||
do iter |x| {
|
||||
match result {
|
||||
Some(ref mut y) => {
|
||||
if x < *y {
|
||||
*y = x;
|
||||
}
|
||||
}
|
||||
None => result = Some(x)
|
||||
}
|
||||
true
|
||||
};
|
||||
result
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce an iterator to an accumulated value.
|
||||
*
|
||||
* # Example:
|
||||
*
|
||||
* ~~~ {.rust}
|
||||
* assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
|
||||
* ~~~
|
||||
*/
|
||||
#[inline]
|
||||
pub fn fold<T, U>(start: T, iter: &fn(f: &fn(U) -> bool) -> bool, f: &fn(&mut T, U)) -> T {
|
||||
let mut result = start;
|
||||
do iter |x| {
|
||||
f(&mut result, x);
|
||||
true
|
||||
};
|
||||
result
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce an iterator to an accumulated value.
|
||||
*
|
||||
* `fold_ref` is usable in some generic functions where `fold` is too lenient to type-check, but it
|
||||
* forces the iterator to yield borrowed pointers.
|
||||
*
|
||||
* # Example:
|
||||
*
|
||||
* ~~~ {.rust}
|
||||
* fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
|
||||
* fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
|
||||
* }
|
||||
* ~~~
|
||||
*/
|
||||
#[inline]
|
||||
pub fn fold_ref<T, U>(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&mut T, &U)) -> T {
|
||||
let mut result = start;
|
||||
do iter |x| {
|
||||
f(&mut result, x);
|
||||
true
|
||||
};
|
||||
result
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the sum of the items yielding by an iterator.
|
||||
*
|
||||
* # Example:
|
||||
*
|
||||
* ~~~ {.rust}
|
||||
* let xs: ~[int] = ~[1, 2, 3, 4];
|
||||
* assert_eq!(do sum |f| { xs.iter().advance(f) }, 10);
|
||||
* ~~~
|
||||
*/
|
||||
#[inline]
|
||||
pub fn sum<T: Zero + Add<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
|
||||
fold_ref(Zero::zero::<T>(), iter, |a, x| *a = a.add(x))
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the product of the items yielded by an iterator.
|
||||
*
|
||||
* # Example:
|
||||
*
|
||||
* ~~~ {.rust}
|
||||
* let xs: ~[int] = ~[1, 2, 3, 4];
|
||||
* assert_eq!(do product |f| { xs.iter().advance(f) }, 24);
|
||||
* ~~~
|
||||
*/
|
||||
#[inline]
|
||||
pub fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
|
||||
fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
|
||||
}
|
||||
|
||||
impl<T> FromIter<T> for ~[T]{
|
||||
#[inline]
|
||||
pub fn from_iter(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] {
|
||||
let mut v = ~[];
|
||||
do iter |x| { v.push(x); true };
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use prelude::*;
|
||||
|
||||
use int;
|
||||
use uint;
|
||||
|
||||
#[test]
|
||||
fn test_from_iter() {
|
||||
let xs = ~[1, 2, 3];
|
||||
let ys: ~[int] = do FromIter::from_iter |f| { xs.iter().advance(|x| f(*x)) };
|
||||
assert_eq!(xs, ys);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_any() {
|
||||
let xs = ~[1u, 2, 3, 4, 5];
|
||||
assert!(any(|&x: &uint| x > 2, |f| xs.iter().advance(f)));
|
||||
assert!(!any(|&x: &uint| x > 5, |f| xs.iter().advance(f)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_all() {
|
||||
assert!(all(|x: uint| x < 6, |f| uint::range(1, 6, f)));
|
||||
assert!(!all(|x: uint| x < 5, |f| uint::range(1, 6, f)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_find() {
|
||||
let xs = ~[1u, 2, 3, 4, 5, 6];
|
||||
assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.iter().advance(f)).unwrap(), 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_max() {
|
||||
let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
|
||||
assert_eq!(max(|f| xs.iter().advance(f)).unwrap(), &15);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_min() {
|
||||
let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
|
||||
assert_eq!(min(|f| xs.iter().advance(f)).unwrap(), &-5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fold() {
|
||||
assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sum() {
|
||||
let xs: ~[int] = ~[1, 2, 3, 4];
|
||||
assert_eq!(do sum |f| { xs.iter().advance(f) }, 10);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_sum() {
|
||||
let xs: ~[int] = ~[];
|
||||
assert_eq!(do sum |f| { xs.iter().advance(f) }, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_product() {
|
||||
let xs: ~[int] = ~[1, 2, 3, 4];
|
||||
assert_eq!(do product |f| { xs.iter().advance(f) }, 24);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_empty_product() {
|
||||
let xs: ~[int] = ~[];
|
||||
assert_eq!(do product |f| { xs.iter().advance(f) }, 1);
|
||||
}
|
||||
}
|
|
@ -696,7 +696,7 @@ mod tests {
|
|||
let u: ~[int] = deq.iter().transform(|&x| x).collect();
|
||||
assert_eq!(u, v);
|
||||
|
||||
let mut seq = iterator::Counter::new(0u, 2).take_(256);
|
||||
let mut seq = iterator::count(0u, 2).take_(256);
|
||||
let deq: RingBuf<uint> = seq.collect();
|
||||
for (i, &x) in deq.iter().enumerate() {
|
||||
assert_eq!(2*i, x);
|
||||
|
|
|
@ -888,6 +888,11 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
|
|||
let offset = get_param(decl, first_real_arg + 1);
|
||||
Ret(bcx, GEP(bcx, ptr, [offset]));
|
||||
}
|
||||
"offset_inbounds" => {
|
||||
let ptr = get_param(decl, first_real_arg);
|
||||
let offset = get_param(decl, first_real_arg + 1);
|
||||
Ret(bcx, InBoundsGEP(bcx, ptr, [offset]));
|
||||
}
|
||||
"memcpy32" => memcpy_intrinsic(bcx, "llvm.memcpy.p0i8.p0i8.i32", substs.tys[0], 32),
|
||||
"memcpy64" => memcpy_intrinsic(bcx, "llvm.memcpy.p0i8.p0i8.i64", substs.tys[0], 64),
|
||||
"memmove32" => memcpy_intrinsic(bcx, "llvm.memmove.p0i8.p0i8.i32", substs.tys[0], 32),
|
||||
|
|
|
@ -148,7 +148,8 @@ pub fn type_uses_for(ccx: @mut CrateContext, fn_id: def_id, n_tps: uint)
|
|||
"visit_tydesc" | "forget" | "frame_address" |
|
||||
"morestack_addr" => 0,
|
||||
|
||||
"offset" | "memcpy32" | "memcpy64" | "memmove32" | "memmove64" |
|
||||
"offset" | "offset_inbounds" |
|
||||
"memcpy32" | "memcpy64" | "memmove32" | "memmove64" |
|
||||
"memset32" | "memset64" => use_repr,
|
||||
|
||||
"sqrtf32" | "sqrtf64" | "powif32" | "powif64" |
|
||||
|
|
|
@ -3481,6 +3481,20 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) {
|
|||
mutbl: ast::m_imm
|
||||
}))
|
||||
}
|
||||
"offset_inbounds" => {
|
||||
(1,
|
||||
~[
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_imm
|
||||
}),
|
||||
ty::mk_int()
|
||||
],
|
||||
ty::mk_ptr(tcx, ty::mt {
|
||||
ty: param(ccx, 0),
|
||||
mutbl: ast::m_imm
|
||||
}))
|
||||
}
|
||||
"memcpy32" => {
|
||||
(1,
|
||||
~[
|
||||
|
|
|
@ -637,7 +637,7 @@ mod test {
|
|||
let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc);
|
||||
write_markdown(doc, writer_factory);
|
||||
// We expect two pages to have been written
|
||||
do 2.times {
|
||||
for _ in range(0, 2u) {
|
||||
po.recv();
|
||||
}
|
||||
}
|
||||
|
@ -649,7 +649,7 @@ mod test {
|
|||
~"#[link(name = \"core\")]; mod a { }");
|
||||
let doc = (page_pass::mk_pass(config::DocPerMod).f)(srv, doc);
|
||||
write_markdown(doc, writer_factory);
|
||||
do 2.times {
|
||||
for _ in range(0, 2u) {
|
||||
let (page, markdown) = po.recv();
|
||||
match page {
|
||||
doc::CratePage(_) => {
|
||||
|
|
|
@ -565,7 +565,10 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_word_size = "32"))]
|
||||
// FIXME: #7220 rusti on 32bit mac doesn't work.
|
||||
// FIXME: #7641 rusti on 32bit linux cross compile doesn't work
|
||||
// FIXME: #7115 re-enable once LLVM has been upgraded
|
||||
#[cfg(thiswillneverbeacfgflag)]
|
||||
fn run_program(prog: &str) {
|
||||
let mut r = repl();
|
||||
for cmd in prog.split_iter('\n') {
|
||||
|
@ -574,9 +577,6 @@ mod tests {
|
|||
"the command '%s' failed", cmd);
|
||||
}
|
||||
}
|
||||
// FIXME: #7220 rusti on 32bit mac doesn't work
|
||||
// FIXME: #7641 rusti on 32bit linux cross compile doesn't work
|
||||
#[cfg(target_word_size = "32")]
|
||||
fn run_program(_: &str) {}
|
||||
|
||||
#[test]
|
||||
|
@ -594,12 +594,13 @@ mod tests {
|
|||
run_program("let a = 3;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[test] #[ignore]
|
||||
fn new_tasks() {
|
||||
// XXX: can't spawn new tasks because the JIT code is cleaned up
|
||||
// after the main function is done.
|
||||
run_program("
|
||||
use std::task::try;
|
||||
try( || println(\"Please don't segfault\") );
|
||||
do try { println(\"Please?\"); }
|
||||
spawn( || println(\"Please don't segfault\") );
|
||||
do spawn { println(\"Please?\"); }
|
||||
");
|
||||
}
|
||||
|
||||
|
|
|
@ -58,3 +58,15 @@ impl<'self, T: Ord> Ord for &'self T {
|
|||
*(*self) > *(*other)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl<'self, T: TotalOrd> TotalOrd for &'self T {
|
||||
#[inline]
|
||||
fn cmp(&self, other: & &'self T) -> Ordering { (**self).cmp(*other) }
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl<'self, T: TotalEq> TotalEq for &'self T {
|
||||
#[inline]
|
||||
fn equals(&self, other: & &'self T) -> bool { (**self).equals(*other) }
|
||||
}
|
||||
|
|
|
@ -153,7 +153,6 @@ pub fn cmp2<A:TotalOrd,B:TotalOrd>(
|
|||
Return `o1` if it is not `Equal`, otherwise `o2`. Simulates the
|
||||
lexical ordering on a type `(int, int)`.
|
||||
*/
|
||||
// used in deriving code in libsyntax
|
||||
#[inline]
|
||||
pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
|
||||
match o1 {
|
||||
|
|
|
@ -18,7 +18,7 @@ implementing the `Iterator` trait.
|
|||
*/
|
||||
|
||||
use cmp;
|
||||
use num::{Zero, One};
|
||||
use num::{Zero, One, Saturating};
|
||||
use option::{Option, Some, None};
|
||||
use ops::{Add, Mul};
|
||||
use cmp::Ord;
|
||||
|
@ -313,7 +313,7 @@ pub trait IteratorUtil<A> {
|
|||
/// ~~~ {.rust}
|
||||
/// let xs = [2u, 3];
|
||||
/// let ys = [0u, 1, 0, 1, 2];
|
||||
/// let mut it = xs.iter().flat_map_(|&x| Counter::new(0u, 1).take_(x));
|
||||
/// let mut it = xs.iter().flat_map_(|&x| count(0u, 1).take_(x));
|
||||
/// // Check that `it` has the same elements as `ys`
|
||||
/// let mut i = 0;
|
||||
/// for x: uint in it {
|
||||
|
@ -351,7 +351,7 @@ pub trait IteratorUtil<A> {
|
|||
/// ~~~ {.rust}
|
||||
/// use std::iterator::Counter;
|
||||
///
|
||||
/// for i in Counter::new(0, 10) {
|
||||
/// for i in count(0, 10) {
|
||||
/// printfln!("%d", i);
|
||||
/// }
|
||||
/// ~~~
|
||||
|
@ -723,7 +723,7 @@ pub trait MultiplicativeIterator<A> {
|
|||
/// use std::iterator::Counter;
|
||||
///
|
||||
/// fn factorial(n: uint) -> uint {
|
||||
/// Counter::new(1u, 1).take_while(|&i| i <= n).product()
|
||||
/// count(1u, 1).take_while(|&i| i <= n).product()
|
||||
/// }
|
||||
/// assert!(factorial(0) == 1);
|
||||
/// assert!(factorial(1) == 1);
|
||||
|
@ -790,7 +790,7 @@ pub trait ClonableIterator {
|
|||
/// # Example
|
||||
///
|
||||
/// ~~~ {.rust}
|
||||
/// let a = Counter::new(1,1).take_(1);
|
||||
/// let a = count(1,1).take_(1);
|
||||
/// let mut cy = a.cycle();
|
||||
/// assert_eq!(cy.next(), Some(1));
|
||||
/// assert_eq!(cy.next(), Some(1));
|
||||
|
@ -884,15 +884,10 @@ impl<A, T: Iterator<A>, U: Iterator<A>> Iterator<A> for Chain<T, U> {
|
|||
let (a_lower, a_upper) = self.a.size_hint();
|
||||
let (b_lower, b_upper) = self.b.size_hint();
|
||||
|
||||
let lower = if uint::max_value - a_lower < b_lower {
|
||||
uint::max_value
|
||||
} else {
|
||||
a_lower + b_lower
|
||||
};
|
||||
let lower = a_lower.saturating_add(b_lower);
|
||||
|
||||
let upper = match (a_upper, b_upper) {
|
||||
(Some(x), Some(y)) if uint::max_value - x < y => Some(uint::max_value),
|
||||
(Some(x), Some(y)) => Some(x + y),
|
||||
(Some(x), Some(y)) => Some(x.saturating_add(y)),
|
||||
_ => None
|
||||
};
|
||||
|
||||
|
@ -916,12 +911,7 @@ for Chain<T, U> {
|
|||
#[inline]
|
||||
fn indexable(&self) -> uint {
|
||||
let (a, b) = (self.a.indexable(), self.b.indexable());
|
||||
let total = a + b;
|
||||
if total < a || total < b {
|
||||
uint::max_value
|
||||
} else {
|
||||
total
|
||||
}
|
||||
a.saturating_add(b)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -1273,11 +1263,10 @@ impl<A, T: Iterator<A>> Iterator<A> for Skip<T> {
|
|||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let (lower, upper) = self.iter.size_hint();
|
||||
|
||||
let lower = if lower >= self.n { lower - self.n } else { 0 };
|
||||
let lower = lower.saturating_sub(self.n);
|
||||
|
||||
let upper = match upper {
|
||||
Some(x) if x >= self.n => Some(x - self.n),
|
||||
Some(_) => Some(0),
|
||||
Some(x) => Some(x.saturating_sub(self.n)),
|
||||
None => None
|
||||
};
|
||||
|
||||
|
@ -1288,12 +1277,7 @@ impl<A, T: Iterator<A>> Iterator<A> for Skip<T> {
|
|||
impl<A, T: RandomAccessIterator<A>> RandomAccessIterator<A> for Skip<T> {
|
||||
#[inline]
|
||||
fn indexable(&self) -> uint {
|
||||
let N = self.iter.indexable();
|
||||
if N < self.n {
|
||||
0
|
||||
} else {
|
||||
N - self.n
|
||||
}
|
||||
self.iter.indexable().saturating_sub(self.n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -1316,10 +1300,9 @@ pub struct Take<T> {
|
|||
impl<A, T: Iterator<A>> Iterator<A> for Take<T> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
let next = self.iter.next();
|
||||
if self.n != 0 {
|
||||
self.n -= 1;
|
||||
next
|
||||
self.iter.next()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -1410,9 +1393,10 @@ impl<'self, A, T: Iterator<A>, B, U: Iterator<B>> Iterator<B> for
|
|||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
let (flo, fhi) = self.frontiter.map_default((0, Some(0)), |it| it.size_hint());
|
||||
let (blo, bhi) = self.backiter.map_default((0, Some(0)), |it| it.size_hint());
|
||||
let lo = flo.saturating_add(blo);
|
||||
match (self.iter.size_hint(), fhi, bhi) {
|
||||
((0, Some(0)), Some(a), Some(b)) => (flo + blo, Some(a + b)),
|
||||
_ => (flo + blo, None)
|
||||
((0, Some(0)), Some(a), Some(b)) => (lo, Some(a.saturating_add(b))),
|
||||
_ => (lo, None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1527,12 +1511,10 @@ pub struct Counter<A> {
|
|||
step: A
|
||||
}
|
||||
|
||||
impl<A> Counter<A> {
|
||||
/// Creates a new counter with the specified start/step
|
||||
#[inline]
|
||||
pub fn new(start: A, step: A) -> Counter<A> {
|
||||
Counter{state: start, step: step}
|
||||
}
|
||||
/// Creates a new counter with the specified start/step
|
||||
#[inline]
|
||||
pub fn count<A>(start: A, step: A) -> Counter<A> {
|
||||
Counter{state: start, step: step}
|
||||
}
|
||||
|
||||
/// A range of numbers from [0, N)
|
||||
|
@ -1619,7 +1601,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_counter_from_iter() {
|
||||
let mut it = Counter::new(0, 5).take_(10);
|
||||
let mut it = count(0, 5).take_(10);
|
||||
let xs: ~[int] = FromIterator::from_iterator(&mut it);
|
||||
assert_eq!(xs, ~[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
|
||||
}
|
||||
|
@ -1637,7 +1619,7 @@ mod tests {
|
|||
}
|
||||
assert_eq!(i, expected.len());
|
||||
|
||||
let ys = Counter::new(30u, 10).take_(4);
|
||||
let ys = count(30u, 10).take_(4);
|
||||
let mut it = xs.iter().transform(|&x| x).chain_(ys);
|
||||
let mut i = 0;
|
||||
for x in it {
|
||||
|
@ -1649,7 +1631,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_filter_map() {
|
||||
let mut it = Counter::new(0u, 1u).take_(10)
|
||||
let mut it = count(0u, 1u).take_(10)
|
||||
.filter_map(|x| if x.is_even() { Some(x*x) } else { None });
|
||||
assert_eq!(it.collect::<~[uint]>(), ~[0*0, 2*2, 4*4, 6*6, 8*8]);
|
||||
}
|
||||
|
@ -1738,7 +1720,7 @@ mod tests {
|
|||
fn test_iterator_flat_map() {
|
||||
let xs = [0u, 3, 6];
|
||||
let ys = [0u, 1, 2, 3, 4, 5, 6, 7, 8];
|
||||
let mut it = xs.iter().flat_map_(|&x| Counter::new(x, 1).take_(3));
|
||||
let mut it = xs.iter().flat_map_(|&x| count(x, 1).take_(3));
|
||||
let mut i = 0;
|
||||
for x in it {
|
||||
assert_eq!(x, ys[i]);
|
||||
|
@ -1785,13 +1767,13 @@ mod tests {
|
|||
#[test]
|
||||
fn test_cycle() {
|
||||
let cycle_len = 3;
|
||||
let it = Counter::new(0u, 1).take_(cycle_len).cycle();
|
||||
let it = count(0u, 1).take_(cycle_len).cycle();
|
||||
assert_eq!(it.size_hint(), (uint::max_value, None));
|
||||
for (i, x) in it.take_(100).enumerate() {
|
||||
assert_eq!(i % cycle_len, x);
|
||||
}
|
||||
|
||||
let mut it = Counter::new(0u, 1).take_(0).cycle();
|
||||
let mut it = count(0u, 1).take_(0).cycle();
|
||||
assert_eq!(it.size_hint(), (0, Some(0)));
|
||||
assert_eq!(it.next(), None);
|
||||
}
|
||||
|
@ -1853,7 +1835,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_iterator_size_hint() {
|
||||
let c = Counter::new(0, 1);
|
||||
let c = count(0, 1);
|
||||
let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
let v2 = &[10, 11, 12];
|
||||
let vi = v.iter();
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
use ptr::to_unsafe_ptr;
|
||||
|
||||
#[cfg(not(test))] use cmp::{Eq, Ord};
|
||||
#[cfg(not(test))] use cmp::*;
|
||||
|
||||
pub static RC_MANAGED_UNIQUE : uint = (-2) as uint;
|
||||
pub static RC_IMMORTAL : uint = 0x77777777;
|
||||
|
@ -71,6 +71,29 @@ impl<T:Ord> Ord for @mut T {
|
|||
fn gt(&self, other: &@mut T) -> bool { *(*self) > *(*other) }
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl<T: TotalOrd> TotalOrd for @T {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &@T) -> Ordering { (**self).cmp(*other) }
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl<T: TotalOrd> TotalOrd for @mut T {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &@mut T) -> Ordering { (**self).cmp(*other) }
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl<T: TotalEq> TotalEq for @T {
|
||||
#[inline]
|
||||
fn equals(&self, other: &@T) -> bool { (**self).equals(*other) }
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl<T: TotalEq> TotalEq for @mut T {
|
||||
#[inline]
|
||||
fn equals(&self, other: &@mut T) -> bool { (**self).equals(*other) }
|
||||
}
|
||||
#[test]
|
||||
fn test() {
|
||||
let x = @3;
|
||||
|
|
|
@ -466,6 +466,56 @@ impl<T: Zero> Zero for ~T {
|
|||
fn is_zero(&self) -> bool { (**self).is_zero() }
|
||||
}
|
||||
|
||||
/// Saturating math operations
|
||||
pub trait Saturating: Int {
|
||||
/// Saturating addition operator.
|
||||
/// Returns a+b, saturating at the numeric bounds instead of overflowing.
|
||||
#[inline]
|
||||
fn saturating_add(self, v: Self) -> Self {
|
||||
let x = self + v;
|
||||
if v >= Zero::zero() {
|
||||
if x < self {
|
||||
// overflow
|
||||
Bounded::max_value::<Self>()
|
||||
} else { x }
|
||||
} else {
|
||||
if x > self {
|
||||
// underflow
|
||||
Bounded::min_value::<Self>()
|
||||
} else { x }
|
||||
}
|
||||
}
|
||||
|
||||
/// Saturating subtraction operator.
|
||||
/// Returns a-b, saturating at the numeric bounds instead of overflowing.
|
||||
#[inline]
|
||||
fn saturating_sub(self, v: Self) -> Self {
|
||||
let x = self - v;
|
||||
if v >= Zero::zero() {
|
||||
if x > self {
|
||||
// underflow
|
||||
Bounded::min_value::<Self>()
|
||||
} else { x }
|
||||
} else {
|
||||
if x < self {
|
||||
// overflow
|
||||
Bounded::max_value::<Self>()
|
||||
} else { x }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Saturating for int {}
|
||||
impl Saturating for i8 {}
|
||||
impl Saturating for i16 {}
|
||||
impl Saturating for i32 {}
|
||||
impl Saturating for i64 {}
|
||||
impl Saturating for uint {}
|
||||
impl Saturating for u8 {}
|
||||
impl Saturating for u16 {}
|
||||
impl Saturating for u32 {}
|
||||
impl Saturating for u64 {}
|
||||
|
||||
/// Helper function for testing numeric operations
|
||||
#[cfg(test)]
|
||||
pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
|
||||
|
@ -482,64 +532,111 @@ pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
|
|||
assert_eq!(ten.rem(&two), ten % two);
|
||||
}
|
||||
|
||||
macro_rules! test_cast_20(
|
||||
($_20:expr) => ({
|
||||
let _20 = $_20;
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
assert_eq!(20u, _20.to_uint());
|
||||
assert_eq!(20u8, _20.to_u8());
|
||||
assert_eq!(20u16, _20.to_u16());
|
||||
assert_eq!(20u32, _20.to_u32());
|
||||
assert_eq!(20u64, _20.to_u64());
|
||||
assert_eq!(20i, _20.to_int());
|
||||
assert_eq!(20i8, _20.to_i8());
|
||||
assert_eq!(20i16, _20.to_i16());
|
||||
assert_eq!(20i32, _20.to_i32());
|
||||
assert_eq!(20i64, _20.to_i64());
|
||||
assert_eq!(20f, _20.to_float());
|
||||
assert_eq!(20f32, _20.to_f32());
|
||||
assert_eq!(20f64, _20.to_f64());
|
||||
macro_rules! test_cast_20(
|
||||
($_20:expr) => ({
|
||||
let _20 = $_20;
|
||||
|
||||
assert_eq!(_20, NumCast::from(20u));
|
||||
assert_eq!(_20, NumCast::from(20u8));
|
||||
assert_eq!(_20, NumCast::from(20u16));
|
||||
assert_eq!(_20, NumCast::from(20u32));
|
||||
assert_eq!(_20, NumCast::from(20u64));
|
||||
assert_eq!(_20, NumCast::from(20i));
|
||||
assert_eq!(_20, NumCast::from(20i8));
|
||||
assert_eq!(_20, NumCast::from(20i16));
|
||||
assert_eq!(_20, NumCast::from(20i32));
|
||||
assert_eq!(_20, NumCast::from(20i64));
|
||||
assert_eq!(_20, NumCast::from(20f));
|
||||
assert_eq!(_20, NumCast::from(20f32));
|
||||
assert_eq!(_20, NumCast::from(20f64));
|
||||
assert_eq!(20u, _20.to_uint());
|
||||
assert_eq!(20u8, _20.to_u8());
|
||||
assert_eq!(20u16, _20.to_u16());
|
||||
assert_eq!(20u32, _20.to_u32());
|
||||
assert_eq!(20u64, _20.to_u64());
|
||||
assert_eq!(20i, _20.to_int());
|
||||
assert_eq!(20i8, _20.to_i8());
|
||||
assert_eq!(20i16, _20.to_i16());
|
||||
assert_eq!(20i32, _20.to_i32());
|
||||
assert_eq!(20i64, _20.to_i64());
|
||||
assert_eq!(20f, _20.to_float());
|
||||
assert_eq!(20f32, _20.to_f32());
|
||||
assert_eq!(20f64, _20.to_f64());
|
||||
|
||||
assert_eq!(_20, cast(20u));
|
||||
assert_eq!(_20, cast(20u8));
|
||||
assert_eq!(_20, cast(20u16));
|
||||
assert_eq!(_20, cast(20u32));
|
||||
assert_eq!(_20, cast(20u64));
|
||||
assert_eq!(_20, cast(20i));
|
||||
assert_eq!(_20, cast(20i8));
|
||||
assert_eq!(_20, cast(20i16));
|
||||
assert_eq!(_20, cast(20i32));
|
||||
assert_eq!(_20, cast(20i64));
|
||||
assert_eq!(_20, cast(20f));
|
||||
assert_eq!(_20, cast(20f32));
|
||||
assert_eq!(_20, cast(20f64));
|
||||
})
|
||||
)
|
||||
assert_eq!(_20, NumCast::from(20u));
|
||||
assert_eq!(_20, NumCast::from(20u8));
|
||||
assert_eq!(_20, NumCast::from(20u16));
|
||||
assert_eq!(_20, NumCast::from(20u32));
|
||||
assert_eq!(_20, NumCast::from(20u64));
|
||||
assert_eq!(_20, NumCast::from(20i));
|
||||
assert_eq!(_20, NumCast::from(20i8));
|
||||
assert_eq!(_20, NumCast::from(20i16));
|
||||
assert_eq!(_20, NumCast::from(20i32));
|
||||
assert_eq!(_20, NumCast::from(20i64));
|
||||
assert_eq!(_20, NumCast::from(20f));
|
||||
assert_eq!(_20, NumCast::from(20f32));
|
||||
assert_eq!(_20, NumCast::from(20f64));
|
||||
|
||||
#[test] fn test_u8_cast() { test_cast_20!(20u8) }
|
||||
#[test] fn test_u16_cast() { test_cast_20!(20u16) }
|
||||
#[test] fn test_u32_cast() { test_cast_20!(20u32) }
|
||||
#[test] fn test_u64_cast() { test_cast_20!(20u64) }
|
||||
#[test] fn test_uint_cast() { test_cast_20!(20u) }
|
||||
#[test] fn test_i8_cast() { test_cast_20!(20i8) }
|
||||
#[test] fn test_i16_cast() { test_cast_20!(20i16) }
|
||||
#[test] fn test_i32_cast() { test_cast_20!(20i32) }
|
||||
#[test] fn test_i64_cast() { test_cast_20!(20i64) }
|
||||
#[test] fn test_int_cast() { test_cast_20!(20i) }
|
||||
#[test] fn test_f32_cast() { test_cast_20!(20f32) }
|
||||
#[test] fn test_f64_cast() { test_cast_20!(20f64) }
|
||||
#[test] fn test_float_cast() { test_cast_20!(20f) }
|
||||
assert_eq!(_20, cast(20u));
|
||||
assert_eq!(_20, cast(20u8));
|
||||
assert_eq!(_20, cast(20u16));
|
||||
assert_eq!(_20, cast(20u32));
|
||||
assert_eq!(_20, cast(20u64));
|
||||
assert_eq!(_20, cast(20i));
|
||||
assert_eq!(_20, cast(20i8));
|
||||
assert_eq!(_20, cast(20i16));
|
||||
assert_eq!(_20, cast(20i32));
|
||||
assert_eq!(_20, cast(20i64));
|
||||
assert_eq!(_20, cast(20f));
|
||||
assert_eq!(_20, cast(20f32));
|
||||
assert_eq!(_20, cast(20f64));
|
||||
})
|
||||
)
|
||||
|
||||
#[test] fn test_u8_cast() { test_cast_20!(20u8) }
|
||||
#[test] fn test_u16_cast() { test_cast_20!(20u16) }
|
||||
#[test] fn test_u32_cast() { test_cast_20!(20u32) }
|
||||
#[test] fn test_u64_cast() { test_cast_20!(20u64) }
|
||||
#[test] fn test_uint_cast() { test_cast_20!(20u) }
|
||||
#[test] fn test_i8_cast() { test_cast_20!(20i8) }
|
||||
#[test] fn test_i16_cast() { test_cast_20!(20i16) }
|
||||
#[test] fn test_i32_cast() { test_cast_20!(20i32) }
|
||||
#[test] fn test_i64_cast() { test_cast_20!(20i64) }
|
||||
#[test] fn test_int_cast() { test_cast_20!(20i) }
|
||||
#[test] fn test_f32_cast() { test_cast_20!(20f32) }
|
||||
#[test] fn test_f64_cast() { test_cast_20!(20f64) }
|
||||
#[test] fn test_float_cast() { test_cast_20!(20f) }
|
||||
|
||||
#[test]
|
||||
fn test_saturating_add_uint() {
|
||||
use uint::max_value;
|
||||
assert_eq!(3u.saturating_add(5u), 8u);
|
||||
assert_eq!(3u.saturating_add(max_value-1), max_value);
|
||||
assert_eq!(max_value.saturating_add(max_value), max_value);
|
||||
assert_eq!((max_value-2).saturating_add(1), max_value-1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_saturating_sub_uint() {
|
||||
use uint::max_value;
|
||||
assert_eq!(5u.saturating_sub(3u), 2u);
|
||||
assert_eq!(3u.saturating_sub(5u), 0u);
|
||||
assert_eq!(0u.saturating_sub(1u), 0u);
|
||||
assert_eq!((max_value-1).saturating_sub(max_value), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_saturating_add_int() {
|
||||
use int::{min_value,max_value};
|
||||
assert_eq!(3i.saturating_add(5i), 8i);
|
||||
assert_eq!(3i.saturating_add(max_value-1), max_value);
|
||||
assert_eq!(max_value.saturating_add(max_value), max_value);
|
||||
assert_eq!((max_value-2).saturating_add(1), max_value-1);
|
||||
assert_eq!(3i.saturating_add(-5i), -2i);
|
||||
assert_eq!(min_value.saturating_add(-1i), min_value);
|
||||
assert_eq!((-2i).saturating_add(-max_value), min_value);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_saturating_sub_int() {
|
||||
use int::{min_value,max_value};
|
||||
assert_eq!(3i.saturating_sub(5i), -2i);
|
||||
assert_eq!(min_value.saturating_sub(1i), min_value);
|
||||
assert_eq!((-2i).saturating_sub(max_value), min_value);
|
||||
assert_eq!(3i.saturating_sub(-5i), 8i);
|
||||
assert_eq!(3i.saturating_sub(-(max_value-1)), max_value);
|
||||
assert_eq!(max_value.saturating_sub(-max_value), max_value);
|
||||
assert_eq!((max_value-2).saturating_sub(-1), max_value-1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
//! Operations on unique pointer types
|
||||
|
||||
#[cfg(not(test))] use cmp::{Eq, Ord};
|
||||
#[cfg(not(test))] use cmp::*;
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl<T:Eq> Eq for ~T {
|
||||
|
@ -31,3 +31,15 @@ impl<T:Ord> Ord for ~T {
|
|||
#[inline]
|
||||
fn gt(&self, other: &~T) -> bool { *(*self) > *(*other) }
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl<T: TotalOrd> TotalOrd for ~T {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &~T) -> Ordering { (**self).cmp(*other) }
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl<T: TotalEq> TotalEq for ~T {
|
||||
#[inline]
|
||||
fn equals(&self, other: &~T) -> bool { (**self).equals(*other) }
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ pub use char::Char;
|
|||
pub use container::{Container, Mutable, Map, MutableMap, Set, MutableSet};
|
||||
pub use hash::Hash;
|
||||
pub use iter::Times;
|
||||
pub use iterator::Extendable;
|
||||
pub use iterator::{Iterator, IteratorUtil, DoubleEndedIterator, DoubleEndedIteratorUtil};
|
||||
pub use iterator::{ClonableIterator, OrdIterator};
|
||||
pub use num::{Num, NumCast};
|
||||
|
@ -65,7 +66,7 @@ pub use path::WindowsPath;
|
|||
pub use ptr::RawPtr;
|
||||
pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr, ToBytesConsume};
|
||||
pub use str::{Str, StrVector, StrSlice, OwnedStr};
|
||||
pub use from_str::{FromStr};
|
||||
pub use from_str::FromStr;
|
||||
pub use to_bytes::IterBytes;
|
||||
pub use to_str::{ToStr, ToStrConsume};
|
||||
pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
|
||||
|
|
|
@ -272,6 +272,7 @@ pub trait RawPtr<T> {
|
|||
fn is_not_null(&self) -> bool;
|
||||
unsafe fn to_option(&self) -> Option<&T>;
|
||||
fn offset(&self, count: int) -> Self;
|
||||
unsafe fn offset_inbounds(self, count: int) -> Self;
|
||||
}
|
||||
|
||||
/// Extension methods for immutable pointers
|
||||
|
@ -304,6 +305,22 @@ impl<T> RawPtr<T> for *T {
|
|||
/// Calculates the offset from a pointer.
|
||||
#[inline]
|
||||
fn offset(&self, count: int) -> *T { offset(*self, count) }
|
||||
|
||||
/// Calculates the offset from a pointer. The offset *must* be in-bounds of
|
||||
/// the object, or one-byte-past-the-end.
|
||||
#[inline]
|
||||
#[cfg(stage0)]
|
||||
unsafe fn offset_inbounds(self, count: int) -> *T {
|
||||
intrinsics::offset(self, count)
|
||||
}
|
||||
|
||||
/// Calculates the offset from a pointer. The offset *must* be in-bounds of
|
||||
/// the object, or one-byte-past-the-end.
|
||||
#[inline]
|
||||
#[cfg(not(stage0))]
|
||||
unsafe fn offset_inbounds(self, count: int) -> *T {
|
||||
intrinsics::offset_inbounds(self, count)
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension methods for mutable pointers
|
||||
|
@ -336,6 +353,30 @@ impl<T> RawPtr<T> for *mut T {
|
|||
/// Calculates the offset from a mutable pointer.
|
||||
#[inline]
|
||||
fn offset(&self, count: int) -> *mut T { mut_offset(*self, count) }
|
||||
|
||||
/// Calculates the offset from a pointer. The offset *must* be in-bounds of
|
||||
/// the object, or one-byte-past-the-end. An arithmetic overflow is also
|
||||
/// undefined behaviour.
|
||||
///
|
||||
/// This method should be preferred over `offset` when the guarantee can be
|
||||
/// satisfied, to enable better optimization.
|
||||
#[inline]
|
||||
#[cfg(stage0)]
|
||||
unsafe fn offset_inbounds(self, count: int) -> *mut T {
|
||||
intrinsics::offset(self as *T, count) as *mut T
|
||||
}
|
||||
|
||||
/// Calculates the offset from a pointer. The offset *must* be in-bounds of
|
||||
/// the object, or one-byte-past-the-end. An arithmetic overflow is also
|
||||
/// undefined behaviour.
|
||||
///
|
||||
/// This method should be preferred over `offset` when the guarantee can be
|
||||
/// satisfied, to enable better optimization.
|
||||
#[inline]
|
||||
#[cfg(not(stage0))]
|
||||
unsafe fn offset_inbounds(self, count: int) -> *mut T {
|
||||
intrinsics::offset_inbounds(self as *T, count) as *mut T
|
||||
}
|
||||
}
|
||||
|
||||
// Equality for pointers
|
||||
|
|
|
@ -3483,19 +3483,22 @@ mod tests {
|
|||
fn test_add() {
|
||||
#[allow(unnecessary_allocation)];
|
||||
macro_rules! t (
|
||||
($s1:expr, $s2:expr, $e:expr) => {
|
||||
assert_eq!($s1 + $s2, $e);
|
||||
assert_eq!($s1.to_owned() + $s2, $e);
|
||||
assert_eq!($s1.to_managed() + $s2, $e);
|
||||
}
|
||||
($s1:expr, $s2:expr, $e:expr) => { {
|
||||
let s1 = $s1;
|
||||
let s2 = $s2;
|
||||
let e = $e;
|
||||
assert_eq!(s1 + s2, e.to_owned());
|
||||
assert_eq!(s1.to_owned() + s2, e.to_owned());
|
||||
assert_eq!(s1.to_managed() + s2, e.to_owned());
|
||||
} }
|
||||
);
|
||||
|
||||
t!("foo", "bar", ~"foobar");
|
||||
t!("foo", @"bar", ~"foobar");
|
||||
t!("foo", ~"bar", ~"foobar");
|
||||
t!("ศไทย中", "华Việt Nam", ~"ศไทย中华Việt Nam");
|
||||
t!("ศไทย中", @"华Việt Nam", ~"ศไทย中华Việt Nam");
|
||||
t!("ศไทย中", ~"华Việt Nam", ~"ศไทย中华Việt Nam");
|
||||
t!("foo", "bar", "foobar");
|
||||
t!("foo", @"bar", "foobar");
|
||||
t!("foo", ~"bar", "foobar");
|
||||
t!("ศไทย中", "华Việt Nam", "ศไทย中华Việt Nam");
|
||||
t!("ศไทย中", @"华Việt Nam", "ศไทย中华Việt Nam");
|
||||
t!("ศไทย中", ~"华Việt Nam", "ศไทย中华Việt Nam");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -13,7 +13,10 @@
|
|||
use to_str::{ToStr,ToStrConsume};
|
||||
use str;
|
||||
use str::StrSlice;
|
||||
use str::OwnedStr;
|
||||
use container::Container;
|
||||
use cast;
|
||||
use ptr;
|
||||
use iterator::{Iterator, IteratorUtil};
|
||||
use vec::{CopyableVector, ImmutableVector};
|
||||
#[cfg(stage0)]
|
||||
|
@ -41,27 +44,19 @@ impl Ascii {
|
|||
/// Convert to lowercase.
|
||||
#[inline]
|
||||
pub fn to_lower(self) -> Ascii {
|
||||
if self.chr >= 65 && self.chr <= 90 {
|
||||
Ascii{chr: self.chr | 0x20 }
|
||||
} else {
|
||||
self
|
||||
}
|
||||
Ascii{chr: ASCII_LOWER_MAP[self.chr]}
|
||||
}
|
||||
|
||||
/// Convert to uppercase.
|
||||
#[inline]
|
||||
pub fn to_upper(self) -> Ascii {
|
||||
if self.chr >= 97 && self.chr <= 122 {
|
||||
Ascii{chr: self.chr & !0x20 }
|
||||
} else {
|
||||
self
|
||||
}
|
||||
Ascii{chr: ASCII_UPPER_MAP[self.chr]}
|
||||
}
|
||||
|
||||
/// Compares two ascii characters of equality, ignoring case.
|
||||
#[inline]
|
||||
pub fn eq_ignore_case(self, other: Ascii) -> bool {
|
||||
self.to_lower().chr == other.to_lower().chr
|
||||
ASCII_LOWER_MAP[self.chr] == ASCII_LOWER_MAP[other.chr]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -292,10 +287,124 @@ impl ToBytesConsume for ~[Ascii] {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/// Convert the string to ASCII upper case:
|
||||
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
#[inline]
|
||||
pub fn to_ascii_upper(string: &str) -> ~str {
|
||||
map_bytes(string, ASCII_UPPER_MAP)
|
||||
}
|
||||
|
||||
/// Convert the string to ASCII lower case:
|
||||
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
#[inline]
|
||||
pub fn to_ascii_lower(string: &str) -> ~str {
|
||||
map_bytes(string, ASCII_LOWER_MAP)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
priv fn map_bytes(string: &str, map: &'static [u8]) -> ~str {
|
||||
let len = string.len();
|
||||
let mut result = str::with_capacity(len);
|
||||
unsafe {
|
||||
do result.as_mut_buf |mut buf, _| {
|
||||
for c in string.as_bytes().iter() {
|
||||
*buf = map[*c];
|
||||
buf = ptr::mut_offset(buf, 1)
|
||||
}
|
||||
}
|
||||
str::raw::set_len(&mut result, len);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Check that two strings are an ASCII case-insensitive match.
|
||||
/// Same as `to_ascii_lower(a) == to_ascii_lower(b)`,
|
||||
/// but without allocating and copying temporary strings.
|
||||
#[inline]
|
||||
pub fn eq_ignore_ascii_case(a: &str, b: &str) -> bool {
|
||||
a.len() == b.len() && a.as_bytes().iter().zip(b.as_bytes().iter()).all(
|
||||
|(byte_a, byte_b)| ASCII_LOWER_MAP[*byte_a] == ASCII_LOWER_MAP[*byte_b])
|
||||
}
|
||||
|
||||
priv static ASCII_LOWER_MAP: &'static [u8] = &[
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
|
||||
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
|
||||
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
|
||||
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||||
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
||||
];
|
||||
|
||||
priv static ASCII_UPPER_MAP: &'static [u8] = &[
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
|
||||
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
|
||||
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
|
||||
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||||
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
||||
];
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use to_bytes::ToBytes;
|
||||
use str::from_char;
|
||||
|
||||
macro_rules! v2ascii (
|
||||
( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]);
|
||||
|
@ -378,4 +487,53 @@ mod tests {
|
|||
|
||||
#[test] #[should_fail]
|
||||
fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
|
||||
|
||||
#[test]
|
||||
fn test_to_ascii_upper() {
|
||||
assert_eq!(to_ascii_upper("url()URL()uRl()ürl"), ~"URL()URL()URL()üRL");
|
||||
assert_eq!(to_ascii_upper("hıKß"), ~"HıKß");
|
||||
|
||||
let mut i = 0;
|
||||
while i <= 500 {
|
||||
let c = i as char;
|
||||
let upper = if 'a' <= c && c <= 'z' { c + 'A' - 'a' } else { c };
|
||||
assert_eq!(to_ascii_upper(from_char(i as char)), from_char(upper))
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_ascii_lower() {
|
||||
assert_eq!(to_ascii_lower("url()URL()uRl()Ürl"), ~"url()url()url()Ürl");
|
||||
// Dotted capital I, Kelvin sign, Sharp S.
|
||||
assert_eq!(to_ascii_lower("HİKß"), ~"hİKß");
|
||||
|
||||
let mut i = 0;
|
||||
while i <= 500 {
|
||||
let c = i as char;
|
||||
let lower = if 'A' <= c && c <= 'Z' { c + 'a' - 'A' } else { c };
|
||||
assert_eq!(to_ascii_lower(from_char(i as char)), from_char(lower))
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn test_eq_ignore_ascii_case() {
|
||||
assert!(eq_ignore_ascii_case("url()URL()uRl()Ürl", "url()url()url()Ürl"));
|
||||
assert!(!eq_ignore_ascii_case("Ürl", "ürl"));
|
||||
// Dotted capital I, Kelvin sign, Sharp S.
|
||||
assert!(eq_ignore_ascii_case("HİKß", "hİKß"));
|
||||
assert!(!eq_ignore_ascii_case("İ", "i"));
|
||||
assert!(!eq_ignore_ascii_case("K", "k"));
|
||||
assert!(!eq_ignore_ascii_case("ß", "s"));
|
||||
|
||||
let mut i = 0;
|
||||
while i <= 500 {
|
||||
let c = i as char;
|
||||
let lower = if 'A' <= c && c <= 'Z' { c + 'a' - 'A' } else { c };
|
||||
assert!(eq_ignore_ascii_case(from_char(i as char), from_char(lower)));
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -317,12 +317,21 @@ extern "rust-intrinsic" {
|
|||
/// Get the address of the `__morestack` stack growth function.
|
||||
pub fn morestack_addr() -> *();
|
||||
|
||||
/// Adjust a pointer by an offset.
|
||||
/// Calculates the offset from a pointer.
|
||||
///
|
||||
/// This is implemented as an intrinsic to avoid converting to and from an
|
||||
/// integer, since the conversion would throw away aliasing information.
|
||||
pub fn offset<T>(dst: *T, offset: int) -> *T;
|
||||
|
||||
/// Calculates the offset from a pointer. The offset *must* be in-bounds of
|
||||
/// the object, or one-byte-past-the-end. An arithmetic overflow is also
|
||||
/// undefined behaviour.
|
||||
///
|
||||
/// This intrinsic should be preferred over `offset` when the guarantee can
|
||||
/// be satisfied, to enable better optimization.
|
||||
#[cfg(not(stage0))]
|
||||
pub fn offset_inbounds<T>(dst: *T, offset: int) -> *T;
|
||||
|
||||
/// Equivalent to the `llvm.memcpy.p0i8.0i8.i32` intrinsic, with a size of
|
||||
/// `count` * `size_of::<T>()` and an alignment of `min_align_of::<T>()`
|
||||
pub fn memcpy32<T>(dst: *mut T, src: *T, count: u32);
|
||||
|
|
|
@ -849,10 +849,15 @@ impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
|
|||
fn iter(self) -> VecIterator<'self, T> {
|
||||
unsafe {
|
||||
let p = vec::raw::to_ptr(self);
|
||||
VecIterator{ptr: p,
|
||||
end: (p as uint + self.len() *
|
||||
sys::nonzero_size_of::<T>()) as *T,
|
||||
lifetime: cast::transmute(p)}
|
||||
if sys::size_of::<T>() == 0 {
|
||||
VecIterator{ptr: p,
|
||||
end: (p as uint + self.len()) as *T,
|
||||
lifetime: cast::transmute(p)}
|
||||
} else {
|
||||
VecIterator{ptr: p,
|
||||
end: p.offset_inbounds(self.len() as int),
|
||||
lifetime: cast::transmute(p)}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1826,10 +1831,15 @@ impl<'self,T> MutableVector<'self, T> for &'self mut [T] {
|
|||
fn mut_iter(self) -> VecMutIterator<'self, T> {
|
||||
unsafe {
|
||||
let p = vec::raw::to_mut_ptr(self);
|
||||
VecMutIterator{ptr: p,
|
||||
end: (p as uint + self.len() *
|
||||
sys::nonzero_size_of::<T>()) as *mut T,
|
||||
lifetime: cast::transmute(p)}
|
||||
if sys::size_of::<T>() == 0 {
|
||||
VecMutIterator{ptr: p,
|
||||
end: (p as uint + self.len()) as *mut T,
|
||||
lifetime: cast::transmute(p)}
|
||||
} else {
|
||||
VecMutIterator{ptr: p,
|
||||
end: p.offset_inbounds(self.len() as int),
|
||||
lifetime: cast::transmute(p)}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2183,7 +2193,7 @@ macro_rules! iterator {
|
|||
// same pointer.
|
||||
cast::transmute(self.ptr as uint + 1)
|
||||
} else {
|
||||
self.ptr.offset(1)
|
||||
self.ptr.offset_inbounds(1)
|
||||
};
|
||||
|
||||
Some(cast::transmute(old))
|
||||
|
@ -2215,7 +2225,7 @@ macro_rules! double_ended_iterator {
|
|||
// See above for why 'ptr.offset' isn't used
|
||||
cast::transmute(self.end as uint - 1)
|
||||
} else {
|
||||
self.end.offset(-1)
|
||||
self.end.offset_inbounds(-1)
|
||||
};
|
||||
Some(cast::transmute(self.end))
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use ast;
|
||||
use ast::{MetaItem, item, expr};
|
||||
use codemap::span;
|
||||
use ext::base::ExtCtxt;
|
||||
|
@ -40,40 +41,70 @@ pub fn expand_deriving_totalord(cx: @ExtCtxt,
|
|||
}
|
||||
|
||||
|
||||
pub fn ordering_const(cx: @ExtCtxt, span: span, cnst: Ordering) -> @expr {
|
||||
pub fn ordering_const(cx: @ExtCtxt, span: span, cnst: Ordering) -> ast::Path {
|
||||
let cnst = match cnst {
|
||||
Less => "Less",
|
||||
Equal => "Equal",
|
||||
Greater => "Greater"
|
||||
};
|
||||
cx.expr_path(
|
||||
cx.path_global(span,
|
||||
~[cx.ident_of("std"),
|
||||
cx.ident_of("cmp"),
|
||||
cx.ident_of(cnst)]))
|
||||
cx.path_global(span,
|
||||
~[cx.ident_of("std"),
|
||||
cx.ident_of("cmp"),
|
||||
cx.ident_of(cnst)])
|
||||
}
|
||||
|
||||
pub fn cs_cmp(cx: @ExtCtxt, span: span,
|
||||
substr: &Substructure) -> @expr {
|
||||
let test_id = cx.ident_of("__test");
|
||||
let equals_path = ordering_const(cx, span, Equal);
|
||||
|
||||
/*
|
||||
Builds:
|
||||
|
||||
let __test = self_field1.cmp(&other_field2);
|
||||
if other == ::std::cmp::Equal {
|
||||
let __test = self_field2.cmp(&other_field2);
|
||||
if __test == ::std::cmp::Equal {
|
||||
...
|
||||
} else {
|
||||
__test
|
||||
}
|
||||
} else {
|
||||
__test
|
||||
}
|
||||
|
||||
FIXME #6449: These `if`s could/should be `match`es.
|
||||
*/
|
||||
cs_same_method_fold(
|
||||
// foldr (possibly) nests the matches in lexical_ordering better
|
||||
// foldr nests the if-elses correctly, leaving the first field
|
||||
// as the outermost one, and the last as the innermost.
|
||||
false,
|
||||
|cx, span, old, new| {
|
||||
cx.expr_call_global(span,
|
||||
~[cx.ident_of("std"),
|
||||
cx.ident_of("cmp"),
|
||||
cx.ident_of("lexical_ordering")],
|
||||
~[old, new])
|
||||
// let __test = new;
|
||||
// if __test == ::std::cmp::Equal {
|
||||
// old
|
||||
// } else {
|
||||
// __test
|
||||
// }
|
||||
|
||||
let assign = cx.stmt_let(span, false, test_id, new);
|
||||
|
||||
let cond = cx.expr_binary(span, ast::eq,
|
||||
cx.expr_ident(span, test_id),
|
||||
cx.expr_path(equals_path.clone()));
|
||||
let if_ = cx.expr_if(span,
|
||||
cond,
|
||||
old, Some(cx.expr_ident(span, test_id)));
|
||||
cx.expr_block(cx.block(span, ~[assign], Some(if_)))
|
||||
},
|
||||
ordering_const(cx, span, Equal),
|
||||
cx.expr_path(equals_path.clone()),
|
||||
|cx, span, list, _| {
|
||||
match list {
|
||||
// an earlier nonmatching variant is Less than a
|
||||
// later one
|
||||
// later one.
|
||||
[(self_var, _, _),
|
||||
(other_var, _, _)] => ordering_const(cx, span,
|
||||
self_var.cmp(&other_var)),
|
||||
(other_var, _, _)] => cx.expr_path(ordering_const(cx, span,
|
||||
self_var.cmp(&other_var))),
|
||||
_ => cx.span_bug(span, "Not exactly 2 arguments in `deriving(TotalOrd)`")
|
||||
}
|
||||
},
|
||||
|
|
|
@ -59,7 +59,7 @@ impl Results {
|
|||
{
|
||||
let mut set = f();
|
||||
do timed(&mut self.random_ints) {
|
||||
do num_keys.times {
|
||||
for _ in range(0, num_keys) {
|
||||
set.insert((rng.next() as uint) % rand_cap);
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ impl Results {
|
|||
{
|
||||
let mut set = f();
|
||||
do timed(&mut self.random_strings) {
|
||||
do num_keys.times {
|
||||
for _ in range(0, num_keys) {
|
||||
let s = uint::to_str(rng.next() as uint);
|
||||
set.insert(s);
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ fn main() {
|
|||
let symbols = [" ", "░", "▒", "▓", "█", "█"];
|
||||
let mut pixels = [0f32, ..256*256];
|
||||
let n2d = ~Noise2DContext::new();
|
||||
do 100.times {
|
||||
for _ in range(0, 100u) {
|
||||
for y in range(0, 256) {
|
||||
for x in range(0, 256) {
|
||||
let v = n2d.get(
|
||||
|
|
|
@ -169,7 +169,7 @@ fn rendezvous(nn: uint, set: ~[color]) {
|
|||
let mut creatures_met = 0;
|
||||
|
||||
// set up meetings...
|
||||
do nn.times {
|
||||
for _ in range(0, nn) {
|
||||
let fst_creature: CreatureInfo = from_creatures.recv();
|
||||
let snd_creature: CreatureInfo = from_creatures.recv();
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ impl RandomFasta {
|
|||
let chars_left = n % LINE_LEN;
|
||||
let mut buf = [0, ..LINE_LEN + 1];
|
||||
|
||||
do lines.times {
|
||||
for _ in range(0, lines) {
|
||||
for i in range(0u, LINE_LEN) {
|
||||
buf[i] = self.nextc();
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ impl Code {
|
|||
fn unpack(&self, frame: i32) -> ~str {
|
||||
let mut key = **self;
|
||||
let mut result = ~[];
|
||||
do (frame as uint).times {
|
||||
for _ in range(0, frame) {
|
||||
result.push(unpack_symbol((key as u8) & 3));
|
||||
key >>= 2;
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ fn generate_frequencies(frequencies: &mut Table,
|
|||
let mut code = Code(0);
|
||||
|
||||
// Pull first frame.
|
||||
do (frame as uint).times {
|
||||
for _ in range(0, frame) {
|
||||
code = code.push_char(input[0]);
|
||||
input = next_char(input);
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ struct Planet {
|
|||
|
||||
fn advance(bodies: &mut [Planet, ..N_BODIES], dt: f64, steps: i32) {
|
||||
let mut d = [ 0.0, ..3 ];
|
||||
do (steps as uint).times {
|
||||
for _ in range(0, steps) {
|
||||
for i in range(0u, N_BODIES) {
|
||||
for j in range(i + 1, N_BODIES) {
|
||||
d[0] = bodies[i].x[0] - bodies[j].x[0];
|
||||
|
|
|
@ -56,7 +56,7 @@ fn main() {
|
|||
let mut u = vec::from_elem(n, 1f64);
|
||||
let mut v = u.clone();
|
||||
let mut tmp = u.clone();
|
||||
do 8.times {
|
||||
for _ in range(0, 8u) {
|
||||
mult_AtAv(u, v, tmp);
|
||||
mult_AtAv(v, u, tmp);
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ fn main() {
|
|||
}
|
||||
|
||||
fn run(repeat: int, depth: int) {
|
||||
do (repeat as uint).times {
|
||||
for _ in range(0, repeat) {
|
||||
info!("starting %.4f", precise_time_s());
|
||||
do task::try {
|
||||
recurse_or_fail(depth, None)
|
||||
|
|
|
@ -32,7 +32,7 @@ fn grandchild_group(num_tasks: uint) {
|
|||
let (po, ch) = stream();
|
||||
let ch = SharedChan::new(ch);
|
||||
|
||||
do num_tasks.times {
|
||||
for _ in range(0, num_tasks) {
|
||||
let ch = ch.clone();
|
||||
do task::spawn { // linked
|
||||
ch.send(());
|
||||
|
@ -41,7 +41,7 @@ fn grandchild_group(num_tasks: uint) {
|
|||
}
|
||||
}
|
||||
error!("Grandchild group getting started");
|
||||
do num_tasks.times {
|
||||
for _ in range(0, num_tasks) {
|
||||
// Make sure all above children are fully spawned; i.e., enlisted in
|
||||
// their ancestor groups.
|
||||
po.recv();
|
||||
|
|
|
@ -1,83 +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.
|
||||
|
||||
// xfail-test FIXME #7307
|
||||
// xfail-fast
|
||||
|
||||
extern mod extra;
|
||||
use extra::oldmap::*;
|
||||
|
||||
class cat : map<int, bool> {
|
||||
priv {
|
||||
// Yes, you can have negative meows
|
||||
let mut meows : int;
|
||||
fn meow() {
|
||||
self.meows += 1;
|
||||
error!("Meow %d", self.meows);
|
||||
if self.meows % 5 == 0 {
|
||||
self.how_hungry += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut how_hungry : int;
|
||||
let name : str;
|
||||
|
||||
new(in_x : int, in_y : int, in_name: str)
|
||||
{ self.meows = in_x; self.how_hungry = in_y; self.name = in_name; }
|
||||
|
||||
fn speak() { self.meow(); }
|
||||
|
||||
fn eat() -> bool {
|
||||
if self.how_hungry > 0 {
|
||||
error!("OM NOM NOM");
|
||||
self.how_hungry -= 2;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
error!("Not hungry!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
fn size() -> uint { self.meows as uint }
|
||||
fn insert(+k: int, +v: bool) -> bool {
|
||||
if v { self.meows += k; } else { self.meows -= k; };
|
||||
true
|
||||
}
|
||||
fn contains_key(&&k: int) -> bool { k <= self.meows }
|
||||
fn get(&&k:int) -> bool { k <= self.meows }
|
||||
fn [](&&k:int) -> bool { k <= self.meows }
|
||||
fn find(&&k:int) -> Option<bool> { Some(self.get(k)) }
|
||||
fn remove(&&k:int) -> Option<bool> { self.meows -= k; Some(true) }
|
||||
fn each(f: &fn(&&int, &&bool) -> bool) {
|
||||
let mut n = num::abs(self.meows);
|
||||
while n > 0 {
|
||||
if !f(n, true) { break; }
|
||||
n -= 1;
|
||||
}
|
||||
}
|
||||
fn each_key(&&f: &fn(&&int) -> bool) {
|
||||
for self.each |k, _v| { if !f(k) { break; } again;};
|
||||
}
|
||||
fn each_value(&&f: &fn(&&bool) -> bool) {
|
||||
for self.each |_k, v| { if !f(v) { break; } again;};
|
||||
}
|
||||
fn clear() { }
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let nyan : cat = cat(0, 2, "nyan");
|
||||
for _ in range(1u, 5u) { nyan.speak(); }
|
||||
// cat returns true if uint input is greater than
|
||||
// the number of meows so far
|
||||
assert!((nyan.get(1)));
|
||||
assert!((!nyan.get(10)));
|
||||
}
|
|
@ -1,129 +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.
|
||||
|
||||
// xfail-test FIXME #7305
|
||||
|
||||
extern mod extra;
|
||||
use extra::oldmap::*;
|
||||
use vec::*;
|
||||
use dvec::{dvec, extensions};
|
||||
|
||||
enum furniture { chair, couch, bed }
|
||||
enum body_part { finger, toe, nose, ear }
|
||||
|
||||
trait noisy {
|
||||
fn speak() -> int;
|
||||
}
|
||||
|
||||
trait scratchy {
|
||||
fn scratch() -> Option<furniture>;
|
||||
}
|
||||
|
||||
trait bitey {
|
||||
fn bite() -> body_part;
|
||||
}
|
||||
|
||||
fn vec_includes<T>(xs: ~[T], x: T) -> bool {
|
||||
for each(xs) |y| { if y == x { return true; }}
|
||||
return false;
|
||||
}
|
||||
|
||||
// vtables other than the 1st one don't seem to work
|
||||
class cat : noisy, scratchy, bitey {
|
||||
priv {
|
||||
let meows : @mut uint;
|
||||
let scratched : dvec<furniture>;
|
||||
let bite_counts : hashmap<body_part, uint>;
|
||||
|
||||
fn meow() -> uint {
|
||||
info!("Meow: %u", *self.meows);
|
||||
*self.meows += 1u;
|
||||
if *self.meows % 5u == 0u {
|
||||
*self.how_hungry += 1;
|
||||
}
|
||||
*self.meows
|
||||
}
|
||||
}
|
||||
|
||||
let how_hungry : @mut int;
|
||||
let name : str;
|
||||
|
||||
new(in_x : uint, in_y : int, in_name: str)
|
||||
{ self.meows = @mut in_x; self.how_hungry = @mut in_y;
|
||||
self.name = in_name; self.scratched = dvec();
|
||||
let hsher: hashfn<body_part> = |p| int::hash(p as int);
|
||||
let eqer : eqfn<body_part> = |p, q| p == q;
|
||||
let t : hashmap<body_part, uint> =
|
||||
hashmap::<body_part, uint>(hsher, eqer);
|
||||
self.bite_counts = t;
|
||||
do iter(~[finger, toe, nose, ear]) |p| {
|
||||
self.bite_counts.insert(p, 0u);
|
||||
};
|
||||
}
|
||||
|
||||
fn speak() -> int { self.meow() as int }
|
||||
fn meow_count() -> uint { *self.meows }
|
||||
fn scratch() -> Option<furniture> {
|
||||
let all = ~[chair, couch, bed];
|
||||
log(error, self.scratched);
|
||||
let mut rslt = None;
|
||||
for each(all) |thing| { if !self.scratched.contains(thing) {
|
||||
self.scratched.push(thing);
|
||||
return Some(thing); }}
|
||||
rslt
|
||||
}
|
||||
fn bite() -> body_part {
|
||||
error!("In bite()");
|
||||
let all = ~[toe, nose, ear];
|
||||
let mut min = finger;
|
||||
do iter(all) |next| {
|
||||
info!("min = %?", min);
|
||||
if self.bite_counts.get(next) < self.bite_counts.get(min) {
|
||||
min = next;
|
||||
}};
|
||||
self.bite_counts.insert(min, self.bite_counts.get(min) + 1u);
|
||||
info!("Bit %?", min);
|
||||
min
|
||||
}
|
||||
}
|
||||
|
||||
fn annoy_neighbors<T:noisy>(critter: T) {
|
||||
for i in range(0u, 10u) {
|
||||
let what = critter.speak();
|
||||
info!("%u %d", i, what);
|
||||
}
|
||||
}
|
||||
|
||||
fn bite_everything<T:bitey>(critter: T) -> bool {
|
||||
let mut left : ~[body_part] = ~[finger, toe, nose, ear];
|
||||
while left.len() > 0u {
|
||||
let part = critter.bite();
|
||||
info!("%? %?", left, part);
|
||||
if vec_includes(left, part) {
|
||||
left = vec::filter(left, |p| p != part );
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn scratched_something<T:scratchy>(critter: T) -> bool {
|
||||
option::is_some(critter.scratch())
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let nyan : cat = cat(0u, 2, "nyan");
|
||||
annoy_neighbors(nyan as noisy);
|
||||
assert_eq!(nyan.meow_count(), 10u);
|
||||
assert!((bite_everything(nyan as bitey)));
|
||||
assert!((scratched_something(nyan as scratchy)));
|
||||
}
|
|
@ -12,10 +12,4 @@ fn sum_imm(y: &[int]) -> int {
|
|||
sum(y)
|
||||
}
|
||||
|
||||
/* FIXME #7304
|
||||
fn sum_const(y: &const [int]) -> int {
|
||||
sum(y)
|
||||
}
|
||||
*/
|
||||
|
||||
pub fn main() {}
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
/* FIXME #7302
|
||||
fn foo(v: &const [uint]) -> ~[uint] {
|
||||
v.to_owned()
|
||||
}
|
||||
*/
|
||||
|
||||
fn bar(v: &mut [uint]) -> ~[uint] {
|
||||
v.to_owned()
|
||||
}
|
||||
|
@ -14,7 +8,6 @@ fn bip(v: &[uint]) -> ~[uint] {
|
|||
|
||||
pub fn main() {
|
||||
let mut the_vec = ~[1u, 2, 3, 100];
|
||||
// assert_eq!(the_vec.clone(), foo(the_vec));
|
||||
assert_eq!(the_vec.clone(), bar(the_vec));
|
||||
assert_eq!(the_vec.clone(), bip(the_vec));
|
||||
}
|
||||
|
|
46
src/test/run-pass/deriving-cmp-shortcircuit.rs
Normal file
46
src/test/run-pass/deriving-cmp-shortcircuit.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
// Copyright 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.
|
||||
|
||||
// check that the derived impls for the comparison traits shortcircuit
|
||||
// where possible, by having a type that fails when compared as the
|
||||
// second element, so this passes iff the instances shortcircuit.
|
||||
|
||||
pub struct FailCmp;
|
||||
impl Eq for FailCmp {
|
||||
fn eq(&self, _: &FailCmp) -> bool { fail!("eq") }
|
||||
}
|
||||
|
||||
impl Ord for FailCmp {
|
||||
fn lt(&self, _: &FailCmp) -> bool { fail!("lt") }
|
||||
}
|
||||
|
||||
impl TotalEq for FailCmp {
|
||||
fn equals(&self, _: &FailCmp) -> bool { fail!("equals") }
|
||||
}
|
||||
|
||||
impl TotalOrd for FailCmp {
|
||||
fn cmp(&self, _: &FailCmp) -> Ordering { fail!("cmp") }
|
||||
}
|
||||
|
||||
#[deriving(Eq,Ord,TotalEq,TotalOrd)]
|
||||
struct ShortCircuit {
|
||||
x: int,
|
||||
y: FailCmp
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let a = ShortCircuit { x: 1, y: FailCmp };
|
||||
let b = ShortCircuit { x: 2, y: FailCmp };
|
||||
|
||||
assert!(a != b);
|
||||
assert!(a < b);
|
||||
assert!(!a.equals(&b));
|
||||
assert_eq!(a.cmp(&b), ::std::cmp::Less);
|
||||
}
|
|
@ -12,7 +12,9 @@ trait get {
|
|||
fn get(self) -> int;
|
||||
}
|
||||
|
||||
// FIXME #7302: Note: impl on a slice
|
||||
// Note: impl on a slice; we're checking that the pointers below
|
||||
// correctly get borrowed to `&`. (similar to impling for `int`, with
|
||||
// `&self` instead of `self`.)
|
||||
impl<'self> get for &'self int {
|
||||
fn get(self) -> int {
|
||||
return *self;
|
||||
|
@ -34,11 +36,6 @@ pub fn main() {
|
|||
info!("y=%d", y);
|
||||
assert_eq!(y, 6);
|
||||
|
||||
let x = ~6;
|
||||
let y = x.get();
|
||||
info!("y=%d", y);
|
||||
assert_eq!(y, 6);
|
||||
|
||||
let x = &6;
|
||||
let y = x.get();
|
||||
info!("y=%d", y);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue