still in scope".
This issue was fixed by PR #12828 and #5781. All that was left was to
add tests.
Closes #12223.
Next, we'll learn more about Rust itself, by starting to write a more complicated
program. We hope you want to do more with Rust than just print "Hello, world!"
-## If
+## Guessing Game
-## Functions
+Let's write a bigger program in Rust. We could just go through a laundry list
+of Rust features, but that's boring. Instead, we'll learn more about how to
+code in Rust by writing a few example projects.
-return
+For our first project, we'll implement a classic beginner programming problem:
+the guessing game. Here's how it works: Our program will generate a random
+integer between one and a hundred. It will then prompt us to enter a guess.
+Upon entering our guess, it will tell us if we're too low or too high. Once we
+guess correctly, it will congratulate us, and print the number of guesses we've
+taken to the screen. Sound good? It sounds easy, but it'll end up showing off a
+number of basic features of Rust.
-comments
+### Set up
-## Testing
+Let's set up a new project. Go to your projects directory, and make a new
+directory for the project, as well as a `src` directory for our code:
-attributes
+```{bash}
+$ cd ~/projects
+$ mkdir guessing_game
+$ cd guessing_game
+$ mkdir src
+```
-stability markers
+Great. Next, let's make a `Cargo.toml` file so Cargo knows how to build our
+project:
-## Crates and Modules
+```{ignore}
+[package]
-visibility
+name = "guessing_game"
+version = "0.1.0"
+authors = [ "someone@example.com" ]
+
+[[bin]]
+
+name = "guessing_game"
+```
+
+Finally, we need our source file. Let's just make it hello world for now, so we
+can check that our setup works. In `src/guessing_game.rs`:
+
+```{rust}
+fn main() {
+ println!("Hello world!");
+}
+```
+
+Let's make sure that worked:
+
+```{bash}
+$ cargo build
+ Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
+$
+```
+
+Excellent! Open up your `src/guessing_game.rs` again. We'll be writing all of
+our code in this file. The next section of the tutorial will show you how to
+build multiple-file projects.
+
+## Variable bindings
+
+The first thing we'll learn about are 'variable bindings.' They look like this:
+
+```{rust}
+let x = 5i;
+```
+
+In many languages, this is called a 'variable.' But Rust's variable bindings
+have a few tricks up their sleeves. Rust has a very powerful feature called
+'pattern matching' that we'll get into detail with later, but the left
+hand side of a `let` expression is a full pattern, not just a variable name.
+This means we can do things like:
+
+```{rust}
+let (x, y) = (1i, 2i);
+```
+
+After this expression is evaluated, `x` will be one, and `y` will be two.
+Patterns are really powerful, but this is about all we can do with them so far.
+So let's just keep this in the back of our minds as we go forward.
+
+By the way, in these examples, `i` indicates that the number is an integer.
+
+Rust is a statically typed language, which means that we specify our types up
+front. So why does our first example compile? Well, Rust has this thing called
+"[Hindley-Milner type
+inference](http://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system)",
+named after some really smart type theorists. If you clicked that link, don't
+be scared: what this means for you is that Rust will attempt to infer the types
+in your program, and it's pretty good at it. If it can infer the type, Rust
+doesn't require you to actually type it out.
+
+We can add the type if we want to. Types come after a colon (`:`):
+
+```{rust}
+let x: int = 5;
+```
+
+If I asked you to read this out loud to the rest of the class, you'd say "`x`
+is a binding with the type `int` and the value `five`." Rust requires you to
+initialize the binding with a value before you're allowed to use it. If
+we try...
+
+```{ignore}
+let x;
+```
+
+...we'll get an error:
+
+```{ignore}
+src/guessing_game.rs:2:9: 2:10 error: cannot determine a type for this local variable: unconstrained type
+src/guessing_game.rs:2 let x;
+ ^
+```
+
+Giving it a type will compile, though:
+
+```{ignore}
+let x: int;
+```
+
+Let's try it out. Change your `src/guessing_game.rs` file to look like this:
+
+```{rust}
+fn main() {
+ let x: int;
+
+ println!("Hello world!");
+}
+```
+
+You can use `cargo build` on the command line to build it. You'll get a warning,
+but it will still print "Hello, world!":
+
+```{ignore,notrust}
+ Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
+src/guessing_game.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variable)] on by default
+src/guessing_game.rs:2 let x: int;
+ ^
+```
+
+Rust warns us that we never use the variable binding, but since we never use it,
+no harm, no foul. Things change if we try to actually use this `x`, however. Let's
+do that. Change your program to look like this:
+
+```{rust,ignore}
+fn main() {
+ let x: int;
+
+ println!("The value of x is: {}", x);
+}
+```
+
+And try to build it. You'll get an error:
+
+```{bash}
+$ cargo build
+ Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
+src/guessing_game.rs:4:39: 4:40 error: use of possibly uninitialized variable: `x`
+src/guessing_game.rs:4 println!("The value of x is: {}", x);
+ ^
+note: in expansion of format_args!
+<std macros>:2:23: 2:77 note: expansion site
+<std macros>:1:1: 3:2 note: in expansion of println!
+src/guessing_game.rs:4:5: 4:42 note: expansion site
+error: aborting due to previous error
+Could not execute process `rustc src/guessing_game.rs --crate-type bin --out-dir /home/you/projects/guessing_game/target -L /home/you/projects/guessing_game/target -L /home/you/projects/guessing_game/target/deps` (status=101)
+```
+
+Rust will not let us use a value that has not been initialized. So why let us
+declare a binding without initializing it? You'd think our first example would
+have errored. Well, Rust is smarter than that. Before we get to that, let's talk
+about this stuff we've added to `println!`.
+
+If you include two curly braces (`{}`, some call them moustaches...) in your
+string to print, Rust will interpret this as a request to interpolate some sort
+of value. **String interpolation** is a computer science term that means "stick
+in the middle of a string." We add a comma, and then `x`, to indicate that we
+want `x` to be the value we're interpolating. The comma is used to separate
+arguments we pass to functions and macros, if you're passing more than one.
+
+When you just use the double curly braces, Rust will attempt to display the
+value in a meaningful way by checking out its type. If you want to specify the
+format in a more detailed manner, there are a [wide number of options
+available](/std/fmt/index.html). Fow now, we'll just stick to the default:
+integers aren't very complicated to print.
+
+So, we've cleared up all of the confusion around bindings, with one exception:
+why does Rust let us declare a variable binding without an initial value if we
+must initialize the binding before we use it? And how does it know that we have
+or have not initialized the binding? For that, we need to learn our next
+concept: `if`.
+
+## If
+
+## Functions
+
+return
+
+comments
## Compound Data Types
break/continue
-iterators
+## Guessing Game: complete
+
+At this point, you have successfully built the Guessing Game! Congratulations!
+For reference, [We've placed the sample code on
+GitHub](https://github.com/steveklabnik/guessing_game).
+
+You've now learned the basic syntax of Rust. All of this is relatively close to
+various other programming languages you have used in the past. These
+fundamental syntactical and semantic elements will form the foundation for the
+rest of your Rust education.
+
+Now that you're an expert at the basics, it's time to learn about some of
+Rust's more unique features.
+
+## iterators
## Lambdas
+## Testing
+
+attributes
+
+stability markers
+
+## Crates and Modules
+
+visibility
+
+
## Generics
## Traits
}
```
-This will result an error indicating that the value is no longer in scope:
+The compiler will produce an error indicating that the value is no longer in scope:
```text
concurrency.rs:12:20: 12:27 error: use of moved value: 'numbers'
"libsync/mpsc_intrusive.rs", # BSD
"test/bench/shootout-binarytrees.rs", # BSD
"test/bench/shootout-fannkuch-redux.rs", # BSD
+ "test/bench/shootout-mandelbrot.rs", # BSD
"test/bench/shootout-meteor.rs", # BSD
"test/bench/shootout-pidigits.rs", # BSD
"test/bench/shootout-regex-dna.rs", # BSD
"syn keyword rustFunction drop
" Types and traits {{{3
-syn keyword rustTrait Ascii AsciiCast OwnedAsciiCast AsciiStr IntoBytes
+syn keyword rustTrait Ascii AsciiCast OwnedAsciiCast AsciiStr
+syn keyword rustTrait IntoBytes
syn keyword rustTrait ToCStr
syn keyword rustTrait Char
syn keyword rustTrait Clone
-syn keyword rustTrait Eq Ord PartialEq PartialOrd Ordering Equiv
+syn keyword rustTrait PartialEq PartialOrd Eq Ord Equiv
+syn keyword rustEnum Ordering
syn keyword rustEnumVariant Less Equal Greater
-syn keyword rustTrait Container Mutable Map MutableMap Set MutableSet
-syn keyword rustTrait FromIterator Extendable
-syn keyword rustTrait Iterator DoubleEndedIterator RandomAccessIterator CloneableIterator
-syn keyword rustTrait OrdIterator MutableDoubleEndedIterator ExactSize
-syn keyword rustTrait Num NumCast CheckedAdd CheckedSub CheckedMul
-syn keyword rustTrait Signed Unsigned
-syn keyword rustTrait Primitive Int Float FloatMath ToPrimitive FromPrimitive
-"syn keyword rustTrait Expect
+syn keyword rustTrait Collection Mutable Map MutableMap
+syn keyword rustTrait Set MutableSet
+syn keyword rustTrait FromIterator Extendable ExactSize
+syn keyword rustTrait Iterator DoubleEndedIterator
+syn keyword rustTrait RandomAccessIterator CloneableIterator
+syn keyword rustTrait OrdIterator MutableDoubleEndedIterator
+syn keyword rustTrait Num NumCast CheckedAdd CheckedSub CheckedMul CheckedDiv
+syn keyword rustTrait Signed Unsigned Primitive Int Float
+syn keyword rustTrait FloatMath ToPrimitive FromPrimitive
syn keyword rustTrait Box
syn keyword rustTrait GenericPath Path PosixPath WindowsPath
syn keyword rustTrait RawPtr
syn keyword rustTrait Buffer Writer Reader Seek
-syn keyword rustTrait Str StrVector StrSlice OwnedStr IntoMaybeOwned
-syn keyword rustTrait StrAllocating
+syn keyword rustTrait Str StrVector StrSlice OwnedStr
+syn keyword rustTrait IntoMaybeOwned StrAllocating
syn keyword rustTrait ToStr IntoStr
syn keyword rustTrait Tuple1 Tuple2 Tuple3 Tuple4
syn keyword rustTrait Tuple5 Tuple6 Tuple7 Tuple8
syn keyword rustTrait Tuple9 Tuple10 Tuple11 Tuple12
-syn keyword rustTrait CloneableVector ImmutableCloneableVector MutableCloneableVector
+syn keyword rustTrait CloneableVector ImmutableCloneableVector
+syn keyword rustTrait MutableCloneableVector MutableOrdVector
syn keyword rustTrait ImmutableVector MutableVector
-syn keyword rustTrait ImmutableEqVector ImmutableOrdVector MutableOrdVector
-syn keyword rustTrait Vector VectorVector OwnedVector MutableVectorAllocating
+syn keyword rustTrait ImmutableEqVector ImmutableOrdVector
+syn keyword rustTrait Vector VectorVector
+syn keyword rustTrait MutableVectorAllocating
syn keyword rustTrait String
syn keyword rustTrait Vec
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
/*! Task-local reference-counted boxes (`Rc` type)
-The `Rc` type provides shared ownership of an immutable value. Destruction is deterministic, and
-will occur as soon as the last owner is gone. It is marked as non-sendable because it avoids the
-overhead of atomic reference counting.
+The `Rc` type provides shared ownership of an immutable value. Destruction is
+deterministic, and will occur as soon as the last owner is gone. It is marked
+as non-sendable because it avoids the overhead of atomic reference counting.
-The `downgrade` method can be used to create a non-owning `Weak` pointer to the box. A `Weak`
-pointer can be upgraded to an `Rc` pointer, but will return `None` if the value has already been
-freed.
+The `downgrade` method can be used to create a non-owning `Weak` pointer to the
+box. A `Weak` pointer can be upgraded to an `Rc` pointer, but will return
+`None` if the value has already been freed.
-For example, a tree with parent pointers can be represented by putting the nodes behind `Strong`
-pointers, and then storing the parent pointers as `Weak` pointers.
+For example, a tree with parent pointers can be represented by putting the
+nodes behind strong `Rc` pointers, and then storing the parent pointers as
+`Weak` pointers.
+
+
+## Examples
+
+Consider a scenario where a set of Gadgets are owned by a given Owner. We want
+to have our Gadgets point to their Owner. We can't do this with unique
+ownership, because more than one gadget may belong to the same Owner. Rc
+allows us to share an Owner between multiple Gadgets, and have the Owner kept
+alive as long as any Gadget points at it.
+
+```rust
+use std::rc::Rc;
+
+struct Owner {
+ name: String
+ // ...other fields
+}
+
+struct Gadget {
+ id: int,
+ owner: Rc<Owner>
+ // ...other fields
+}
+
+fn main() {
+ // Create a reference counted Owner.
+ let gadget_owner : Rc<Owner> = Rc::new(
+ Owner { name: String::from_str("Gadget Man") }
+ );
+
+ // Create Gadgets belonging to gadget_owner. To increment the reference
+ // count we clone the Rc object.
+ let gadget1 = Gadget { id: 1, owner: gadget_owner.clone() };
+ let gadget2 = Gadget { id: 2, owner: gadget_owner.clone() };
+
+ drop(gadget_owner);
+
+ // Despite dropping gadget_owner, we're still able to print out the name of
+ // the Owner of the Gadgets. This is because we've only dropped the
+ // reference count object, not the Owner it wraps. As long as there are
+ // other Rc objects pointing at the same Owner, it will stay alive. Notice
+ // that the Rc wrapper around Gadget.owner gets automatically dereferenced
+ // for us.
+ println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name);
+ println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name);
+
+ // At the end of the method, gadget1 and gadget2 get destroyed, and with
+ // them the last counted references to our Owner. Gadget Man now gets
+ // destroyed as well.
+}
+```
+
+If our requirements change, and we also need to be able to traverse from
+Owner->Gadget, we will run into problems: an Rc pointer from Owner->Gadget
+introduces a cycle between the objects. This means that their reference counts
+can never reach 0, and the objects will stay alive: a memory leak. In order to
+get around this, we can use `Weak` pointers. These are reference counted
+pointers that don't keep an object alive if there are no normal `Rc` (or
+*strong*) pointers left.
+
+Rust actually makes it somewhat difficult to produce this loop in the first
+place: in order to end up with two objects that point at each other, one of
+them needs to be mutable. This is problematic because Rc enforces memory
+safety by only giving out shared references to the object it wraps, and these
+don't allow direct mutation. We need to wrap the part of the object we wish to
+mutate in a `RefCell`, which provides *interior mutability*: a method to
+achieve mutability through a shared reference. `RefCell` enforces Rust's
+borrowing rules at runtime. Read the `Cell` documentation for more details on
+interior mutability.
+
+```rust
+use std::rc::Rc;
+use std::rc::Weak;
+use std::cell::RefCell;
+
+struct Owner {
+ name: String,
+ gadgets: RefCell<Vec<Weak<Gadget>>>
+ // ...other fields
+}
+
+struct Gadget {
+ id: int,
+ owner: Rc<Owner>
+ // ...other fields
+}
+
+fn main() {
+ // Create a reference counted Owner. Note the fact that we've put the
+ // Owner's vector of Gadgets inside a RefCell so that we can mutate it
+ // through a shared reference.
+ let gadget_owner : Rc<Owner> = Rc::new(
+ Owner {
+ name: "Gadget Man".to_string(),
+ gadgets: RefCell::new(Vec::new())
+ }
+ );
+
+ // Create Gadgets belonging to gadget_owner as before.
+ let gadget1 = Rc::new(Gadget{id: 1, owner: gadget_owner.clone()});
+ let gadget2 = Rc::new(Gadget{id: 2, owner: gadget_owner.clone()});
+
+ // Add the Gadgets to their Owner. To do this we mutably borrow from
+ // the RefCell holding the Owner's Gadgets.
+ gadget_owner.gadgets.borrow_mut().push(gadget1.clone().downgrade());
+ gadget_owner.gadgets.borrow_mut().push(gadget2.clone().downgrade());
+
+ // Iterate over our Gadgets, printing their details out
+ for gadget_opt in gadget_owner.gadgets.borrow().iter() {
+
+ // gadget_opt is a Weak<Gadget>. Since weak pointers can't guarantee
+ // that their object is still alive, we need to call upgrade() on them
+ // to turn them into a strong reference. This returns an Option, which
+ // contains a reference to our object if it still exists.
+ let gadget = gadget_opt.upgrade().unwrap();
+ println!("Gadget {} owned by {}", gadget.id, gadget.owner.name);
+ }
+
+ // At the end of the method, gadget_owner, gadget1 and gadget2 get
+ // destroyed. There are now no strong (Rc) references to the gadgets.
+ // Once they get destroyed, the Gadgets get destroyed. This zeroes the
+ // reference count on Gadget Man, so he gets destroyed as well.
+}
+```
*/
let n2: uint = v.len();
assert_eq!(n1, n2);
while i < n1 {
- let a: u8 = s1.as_slice()[i];
- let b: u8 = s2.as_slice()[i];
+ let a: u8 = s1.as_bytes()[i];
+ let b: u8 = s2.as_bytes()[i];
debug!("{}", a);
debug!("{}", b);
assert_eq!(a, b);
return None
}
- let byte = self.as_slice()[len - 1];
+ let byte = self.as_bytes()[len - 1];
self.vec.set_len(len - 1);
Some(byte)
}
fn lines_any(&self) -> AnyLines<'a> {
self.lines().map(|line| {
let l = line.len();
- if l > 0 && line[l - 1] == '\r' as u8 { line.slice(0, l - 1) }
+ if l > 0 && line.as_bytes()[l - 1] == '\r' as u8 { line.slice(0, l - 1) }
else { line }
})
}
fn is_char_boundary(&self, index: uint) -> bool {
if index == self.len() { return true; }
if index > self.len() { return false; }
- let b = self[index];
+ let b = self.as_bytes()[index];
return b < 128u8 || b >= 192u8;
}
#[inline]
fn char_range_at(&self, i: uint) -> CharRange {
- if self[i] < 128u8 {
- return CharRange {ch: self[i] as char, next: i + 1 };
+ if self.as_bytes()[i] < 128u8 {
+ return CharRange {ch: self.as_bytes()[i] as char, next: i + 1 };
}
// Multibyte case is a fn to allow char_range_at to inline cleanly
fn multibyte_char_range_at(s: &str, i: uint) -> CharRange {
- let mut val = s[i] as u32;
+ let mut val = s.as_bytes()[i] as u32;
let w = UTF8_CHAR_WIDTH[val as uint] as uint;
assert!((w != 0));
val = utf8_first_byte!(val, w);
- val = utf8_acc_cont_byte!(val, s[i + 1]);
- if w > 2 { val = utf8_acc_cont_byte!(val, s[i + 2]); }
- if w > 3 { val = utf8_acc_cont_byte!(val, s[i + 3]); }
+ val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 1]);
+ if w > 2 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 2]); }
+ if w > 3 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 3]); }
return CharRange {ch: unsafe { mem::transmute(val) }, next: i + w};
}
let mut prev = start;
prev = prev.saturating_sub(1);
- if self[prev] < 128 { return CharRange{ch: self[prev] as char, next: prev} }
+ if self.as_bytes()[prev] < 128 {
+ return CharRange{ch: self.as_bytes()[prev] as char, next: prev}
+ }
// Multibyte case is a fn to allow char_range_at_reverse to inline cleanly
fn multibyte_char_range_at_reverse(s: &str, mut i: uint) -> CharRange {
// while there is a previous byte == 10......
- while i > 0 && s[i] & 192u8 == TAG_CONT_U8 {
+ while i > 0 && s.as_bytes()[i] & 192u8 == TAG_CONT_U8 {
i -= 1u;
}
- let mut val = s[i] as u32;
+ let mut val = s.as_bytes()[i] as u32;
let w = UTF8_CHAR_WIDTH[val as uint] as uint;
assert!((w != 0));
val = utf8_first_byte!(val, w);
- val = utf8_acc_cont_byte!(val, s[i + 1]);
- if w > 2 { val = utf8_acc_cont_byte!(val, s[i + 2]); }
- if w > 3 { val = utf8_acc_cont_byte!(val, s[i + 3]); }
+ val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 1]);
+ if w > 2 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 2]); }
+ if w > 3 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 3]); }
return CharRange {ch: unsafe { mem::transmute(val) }, next: i};
}
}
fn is_arg(arg: &str) -> bool {
- arg.len() > 1 && arg[0] == '-' as u8
+ arg.len() > 1 && arg.as_bytes()[0] == '-' as u8
}
fn find_opt(opts: &[Opt], nm: Name) -> Option<uint> {
} else {
let mut names;
let mut i_arg = None;
- if cur.as_slice()[1] == '-' as u8 {
+ if cur.as_bytes()[1] == '-' as u8 {
let tail = cur.as_slice().slice(2, curlen);
let tail_eq: Vec<&str> = tail.split('=').collect();
if tail_eq.len() <= 1 {
#[cfg(unix)] type msglen_t = libc::size_t;
impl rtio::RtioUdpSocket for UdpSocket {
- fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, rtio::SocketAddr)> {
+ fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(uint, rtio::SocketAddr)> {
let fd = self.fd();
let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
let storagep = &mut storage as *mut _ as *mut libc::sockaddr;
})
}
- fn sendto(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> IoResult<()> {
+ fn send_to(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> IoResult<()> {
let (dst, dstlen) = addr_to_sockaddr(dst);
let dstp = &dst as *const _ as *const libc::sockaddr;
let dstlen = dstlen as libc::socklen_t;
// Underscore-qualify anything that didn't start as an ident.
if result.len() > 0u &&
- result.as_slice()[0] != '_' as u8 &&
- ! char::is_XID_start(result.as_slice()[0] as char) {
+ result.as_bytes()[0] != '_' as u8 &&
+ ! char::is_XID_start(result.as_bytes()[0] as char) {
return format!("_{}", result.as_slice());
}
let extra2 = id % EXTRA_CHARS.len();
let id = id / EXTRA_CHARS.len();
let extra3 = id % EXTRA_CHARS.len();
- hash.push_char(EXTRA_CHARS[extra1] as char);
- hash.push_char(EXTRA_CHARS[extra2] as char);
- hash.push_char(EXTRA_CHARS[extra3] as char);
+ hash.push_char(EXTRA_CHARS.as_bytes()[extra1] as char);
+ hash.push_char(EXTRA_CHARS.as_bytes()[extra2] as char);
+ hash.push_char(EXTRA_CHARS.as_bytes()[extra3] as char);
exported_name(path,
hash.as_slice(),
fn item_method_sort(item: ebml::Doc) -> char {
let mut ret = 'r';
reader::tagged_docs(item, tag_item_trait_method_sort, |doc| {
- ret = doc.as_str_slice()[0] as char;
+ ret = doc.as_str_slice().as_bytes()[0] as char;
false
});
ret
let explicit_self_doc = reader::get_doc(item, tag_item_trait_method_explicit_self);
let string = explicit_self_doc.as_str_slice();
- let explicit_self_kind = string[0];
+ let explicit_self_kind = string.as_bytes()[0];
match explicit_self_kind as char {
's' => ast::SelfStatic,
'v' => ast::SelfValue,
'~' => ast::SelfUniq,
// FIXME(#4846) expl. region
- '&' => ast::SelfRegion(None, get_mutability(string[1])),
+ '&' => ast::SelfRegion(None, get_mutability(string.as_bytes()[1])),
_ => fail!("unknown self type code: `{}`", explicit_self_kind as char)
}
}
impl<'a> DeadVisitor<'a> {
fn should_warn_about_field(&mut self, node: &ast::StructField_) -> bool {
let (is_named, has_leading_underscore) = match node.ident() {
- Some(ref ident) => (true, token::get_ident(*ident).get()[0] == ('_' as u8)),
+ Some(ref ident) => (true, token::get_ident(*ident).get().as_bytes()[0] == ('_' as u8)),
_ => (false, false)
};
let field_type = ty::node_id_to_type(self.tcx, node.id);
fn should_warn(&self, var: Variable) -> Option<String> {
let name = self.ir.variable_name(var);
- if name.len() == 0 || name.as_slice()[0] == ('_' as u8) {
+ if name.len() == 0 || name.as_bytes()[0] == ('_' as u8) {
None
} else {
Some(name)
#[deriving(Clone, PartialEq, Eq, Hash)]
pub enum ElementKind {
VecElement,
- StrElement,
OtherElement,
}
//! - `derefs`: the deref number to be used for
//! the implicit index deref, if any (see above)
- let element_ty = match ty::index(base_cmt.ty) {
+ let element_ty = match ty::array_element_ty(base_cmt.ty) {
Some(ref mt) => mt.ty,
None => {
self.tcx().sess.span_bug(
cat_interior(_, InteriorElement(VecElement)) => {
"vec content".to_string()
}
- cat_interior(_, InteriorElement(StrElement)) => {
- "str content".to_string()
- }
cat_interior(_, InteriorElement(OtherElement)) => {
"indexed content".to_string()
}
ty::ty_rptr(_, ty::mt{ty:ty, ..}) |
ty::ty_uniq(ty) => match ty::get(ty).sty {
ty::ty_vec(_, None) => VecElement,
- ty::ty_str => StrElement,
_ => OtherElement
},
ty::ty_vec(..) => VecElement,
}
}
-fn type_is_slice(ty:t) -> bool {
+fn type_is_slice(ty: t) -> bool {
match get(ty).sty {
ty_rptr(_, mt) => match get(mt.ty).sty {
ty_vec(_, None) | ty_str => true,
}
}
+pub fn type_is_vec(ty: t) -> bool {
+ match get(ty).sty {
+ ty_vec(..) => true,
+ ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
+ ty_box(t) | ty_uniq(t) => match get(t).sty {
+ ty_vec(_, None) => true,
+ _ => false
+ },
+ _ => false
+ }
+}
+
pub fn type_is_structural(ty: t) -> bool {
match get(ty).sty {
ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) |
pub fn sequence_element_type(cx: &ctxt, ty: t) -> t {
match get(ty).sty {
- ty_vec(mt, Some(_)) => mt.ty,
+ ty_vec(mt, _) => mt.ty,
ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
ty_box(t) | ty_uniq(t) => match get(t).sty {
ty_vec(mt, None) => mt.ty,
// Returns the type of t[i]
pub fn index(t: t) -> Option<mt> {
+ match get(t).sty {
+ ty_vec(mt, Some(_)) => Some(mt),
+ ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
+ ty_box(t) | ty_uniq(t) => match get(t).sty {
+ ty_vec(mt, None) => Some(mt),
+ _ => None,
+ },
+ _ => None
+ }
+}
+
+// Returns the type of elements contained within an 'array-like' type.
+// This is exactly the same as the above, except it supports strings,
+// which can't actually be indexed.
+pub fn array_element_ty(t: t) -> Option<mt> {
match get(t).sty {
ty_vec(mt, Some(_)) => Some(mt),
ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
.span_err(span,
"cannot cast as `bool`, compare with zero instead");
} else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
- fn is_vec(t: ty::t) -> bool {
- match ty::get(t).sty {
- ty::ty_vec(..) => true,
- ty::ty_ptr(ty::mt{ty: t, ..}) |
- ty::ty_rptr(_, ty::mt{ty: t, ..}) |
- ty::ty_box(t) |
- ty::ty_uniq(t) => {
- match ty::get(t).sty {
- ty::ty_vec(_, None) => true,
- _ => false,
- }
- }
- _ => false
- }
- }
fn types_compatible(fcx: &FnCtxt, sp: Span,
t1: ty::t, t2: ty::t) -> bool {
- if !is_vec(t1) {
+ if !ty::type_is_vec(t1) {
// If the type being casted from is not a vector, this special
// case does not apply.
return false
fcx.write_ty(id, enum_type);
}
+ type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
+
+ fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
+ expected: Expectation)
+ -> (ExprCheckerWithTy, ty::t) {
+ let tcx = fcx.ccx.tcx;
+ let (coerce, t) = match expected {
+ // If we're given an expected type, we can try to coerce to it
+ ExpectHasType(t) if ty::type_is_vec(t) => (true, ty::sequence_element_type(tcx, t)),
+ // Otherwise we just leave the type to be resolved later
+ _ => (false, fcx.infcx().next_ty_var())
+ };
+ if coerce {
+ (check_expr_coercable_to_type, t)
+ } else {
+ (check_expr_has_type, t)
+ }
+ }
+
let tcx = fcx.ccx.tcx;
let id = expr.id;
match expr.node {
ast::ExprVstore(ev, vst) => {
+ let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
let typ = match ev.node {
ast::ExprVec(ref args) => {
let mutability = match vst {
};
let mut any_error = false;
let mut any_bot = false;
- let t: ty::t = fcx.infcx().next_ty_var();
for e in args.iter() {
- check_expr_has_type(fcx, &**e, t);
+ check(fcx, &**e, t);
let arg_t = fcx.expr_ty(&**e);
if ty::type_is_error(arg_t) {
any_error = true;
ast::ExprVstoreMutSlice => ast::MutMutable,
_ => ast::MutImmutable,
};
- let t = fcx.infcx().next_ty_var();
- check_expr_has_type(fcx, &**element, t);
+ check(fcx, &**element, t);
let arg_t = fcx.expr_ty(&**element);
if ty::type_is_error(arg_t) {
ty::mk_err()
check_cast(fcx, &**e, &**t, id, expr.span);
}
ast::ExprVec(ref args) => {
- let t: ty::t = fcx.infcx().next_ty_var();
+ let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
for e in args.iter() {
- check_expr_has_type(fcx, &**e, t);
+ check(fcx, &**e, t);
}
let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
Some(args.len()));
ast::ExprRepeat(ref element, ref count_expr) => {
check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
let count = ty::eval_repeat_count(fcx, &**count_expr);
- let t: ty::t = fcx.infcx().next_ty_var();
- check_expr_has_type(fcx, &**element, t);
+ let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
+ check(fcx, &**element, t);
let element_ty = fcx.expr_ty(&**element);
if ty::type_is_error(element_ty) {
fcx.write_error(id);
}
pub trait RtioUdpSocket : RtioSocket {
- fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)>;
- fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()>;
+ fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)>;
+ fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()>;
fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()>;
fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()>;
let listener = UdpWatcher::bind(local_loop(), addr2);
tx.send((listener.unwrap(), addr1));
let mut listener = UdpWatcher::bind(local_loop(), addr1).unwrap();
- listener.sendto([1, 2, 3, 4], addr2).ok().unwrap();
+ listener.send_to([1, 2, 3, 4], addr2).ok().unwrap();
});
let task = pool.task(TaskOpts::new(), proc() {
let (mut watcher, addr) = rx.recv();
let mut buf = [0, ..10];
- assert!(watcher.recvfrom(buf).ok().unwrap() == (4, addr));
+ assert!(watcher.recv_from(buf).ok().unwrap() == (4, addr));
});
pool.spawn_sched().send(sched::TaskFromFriend(task));
}
impl rtio::RtioUdpSocket for UdpWatcher {
- fn recvfrom(&mut self, buf: &mut [u8])
+ fn recv_from(&mut self, buf: &mut [u8])
-> Result<(uint, rtio::SocketAddr), IoError>
{
let loop_ = self.uv_loop();
}
}
- fn sendto(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> Result<(), IoError> {
+ fn send_to(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> Result<(), IoError> {
let m = self.fire_homing_missile();
let loop_ = self.uv_loop();
let guard = try!(self.write_access.grant(m));
Ok(mut w) => {
tx.send(());
let mut buf = [0u8, ..10];
- match w.recvfrom(buf) {
+ match w.recv_from(buf) {
Ok((10, addr)) => assert!(addr == client),
e => fail!("{:?}", e),
}
let mut w = match UdpWatcher::bind(local_loop(), client) {
Ok(w) => w, Err(e) => fail!("{:?}", e)
};
- match w.sendto([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], server) {
+ match w.send_to([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], server) {
Ok(()) => {}, Err(e) => fail!("{:?}", e)
}
}
Ok(mut w) => {
tx.send(());
let mut buf = [0u8, ..10];
- match w.recvfrom(buf) {
+ match w.recv_from(buf) {
Ok((10, addr)) => assert!(addr == client),
e => fail!("{:?}", e),
}
let mut w = match UdpWatcher::bind(local_loop(), client) {
Ok(w) => w, Err(e) => fail!("{:?}", e)
};
- match w.sendto([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], server) {
+ match w.send_to([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], server) {
Ok(()) => {}, Err(e) => fail!("{:?}", e)
}
}
spawn(proc() {
let mut client = UdpWatcher::bind(local_loop(), client_addr).unwrap();
rx.recv();
- assert!(client.sendto([1], server_addr).is_ok());
- assert!(client.sendto([2], server_addr).is_ok());
+ assert!(client.send_to([1], server_addr).is_ok());
+ assert!(client.send_to([2], server_addr).is_ok());
});
let mut server = UdpWatcher::bind(local_loop(), server_addr).unwrap();
tx.send(());
let mut buf1 = [0];
let mut buf2 = [0];
- let (nread1, src1) = server.recvfrom(buf1).ok().unwrap();
- let (nread2, src2) = server.recvfrom(buf2).ok().unwrap();
+ let (nread1, src1) = server.recv_from(buf1).ok().unwrap();
+ let (nread2, src2) = server.recv_from(buf2).ok().unwrap();
assert_eq!(nread1, 1);
assert_eq!(nread2, 1);
assert!(src1 == client_addr);
let mut buf = [1];
while buf[0] == 1 {
// send more data
- assert!(server_out.sendto(msg, client_in_addr).is_ok());
+ assert!(server_out.send_to(msg, client_in_addr).is_ok());
total_bytes_sent += msg.len();
// check if the client has received enough
- let res = server_in.recvfrom(buf);
+ let res = server_in.recv_from(buf);
assert!(res.is_ok());
let (nread, src) = res.ok().unwrap();
assert_eq!(nread, 1);
let mut buf = [0, .. 2048];
while total_bytes_recv < MAX {
// ask for more
- assert!(client_out.sendto([1], server_in_addr).is_ok());
+ assert!(client_out.send_to([1], server_in_addr).is_ok());
// wait for data
- let res = client_in.recvfrom(buf);
+ let res = client_in.recv_from(buf);
assert!(res.is_ok());
let (nread, src) = res.ok().unwrap();
assert!(src == server_out_addr);
}
}
// tell the server we're done
- assert!(client_out.sendto([0], server_in_addr).is_ok());
+ assert!(client_out.send_to([0], server_in_addr).is_ok());
}
#[test]
use default::Default;
use fmt::Show;
use fmt;
-use hash::{Hash, Hasher, sip};
+use hash::{Hash, Hasher, RandomSipHasher};
use iter::{Iterator, FilterMap, Chain, Repeat, Zip, Extendable};
use iter::{range, range_inclusive, FromIterator};
use iter;
use mem::replace;
use num;
use option::{Some, None, Option};
-use rand::Rng;
-use rand;
use result::{Ok, Err};
mod table {
/// }
/// ```
#[deriving(Clone)]
-pub struct HashMap<K, V, H = sip::SipHasher> {
+pub struct HashMap<K, V, H = RandomSipHasher> {
// All hashes are keyed on these values, to prevent hash collision attacks.
hasher: H,
}
-impl<K: Hash + Eq, V> HashMap<K, V, sip::SipHasher> {
+impl<K: Hash + Eq, V> HashMap<K, V, RandomSipHasher> {
/// Create an empty HashMap.
- pub fn new() -> HashMap<K, V, sip::SipHasher> {
+ #[inline]
+ pub fn new() -> HashMap<K, V, RandomSipHasher> {
HashMap::with_capacity(INITIAL_CAPACITY)
}
/// Creates an empty hash map with the given initial capacity.
- pub fn with_capacity(capacity: uint) -> HashMap<K, V, sip::SipHasher> {
- let mut r = rand::task_rng();
- let r0 = r.gen();
- let r1 = r.gen();
- let hasher = sip::SipHasher::new_with_keys(r0, r1);
+ #[inline]
+ pub fn with_capacity(capacity: uint) -> HashMap<K, V, RandomSipHasher> {
+ let hasher = RandomSipHasher::new();
HashMap::with_capacity_and_hasher(capacity, hasher)
}
}
/// Creates an empty hashmap which will use the given hasher to hash keys.
///
/// The creates map has the default initial capacity.
+ #[inline]
pub fn with_hasher(hasher: H) -> HashMap<K, V, H> {
HashMap::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
}
/// is designed to allow HashMaps to be resistant to attacks that
/// cause many collisions and very poor performance. Setting it
/// manually using this function can expose a DoS attack vector.
+ #[inline]
pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashMap<K, V, H> {
let cap = num::next_power_of_two(max(INITIAL_CAPACITY, capacity));
HashMap {
/// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
/// requires that the elements implement the `Eq` and `Hash` traits.
#[deriving(Clone)]
-pub struct HashSet<T, H = sip::SipHasher> {
+pub struct HashSet<T, H = RandomSipHasher> {
map: HashMap<T, (), H>
}
fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
}
-impl<T: Hash + Eq> HashSet<T, sip::SipHasher> {
+impl<T: Hash + Eq> HashSet<T, RandomSipHasher> {
/// Create an empty HashSet
- pub fn new() -> HashSet<T, sip::SipHasher> {
+ #[inline]
+ pub fn new() -> HashSet<T, RandomSipHasher> {
HashSet::with_capacity(INITIAL_CAPACITY)
}
/// Create an empty HashSet with space for at least `n` elements in
/// the hash table.
- pub fn with_capacity(capacity: uint) -> HashSet<T, sip::SipHasher> {
+ #[inline]
+ pub fn with_capacity(capacity: uint) -> HashSet<T, RandomSipHasher> {
HashSet { map: HashMap::with_capacity(capacity) }
}
}
/// keys.
///
/// The hash set is also created with the default initial capacity.
+ #[inline]
pub fn with_hasher(hasher: H) -> HashSet<T, H> {
HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
}
/// is designed to allow `HashSet`s to be resistant to attacks that
/// cause many collisions and very poor performance. Setting it
/// manually using this function can expose a DoS attack vector.
+ #[inline]
pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet<T, H> {
HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+ * Generic hashing support.
+ *
+ * This module provides a generic way to compute the hash of a value. The
+ * simplest way to make a type hashable is to use `#[deriving(Hash)]`:
+ *
+ * # Example
+ *
+ * ```rust
+ * use std::hash;
+ * use std::hash::Hash;
+ *
+ * #[deriving(Hash)]
+ * struct Person {
+ * id: uint,
+ * name: String,
+ * phone: u64,
+ * }
+ *
+ * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
+ * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
+ *
+ * assert!(hash::hash(&person1) != hash::hash(&person2));
+ * ```
+ *
+ * If you need more control over how a value is hashed, you need to implement
+ * the trait `Hash`:
+ *
+ * ```rust
+ * use std::hash;
+ * use std::hash::Hash;
+ * use std::hash::sip::SipState;
+ *
+ * struct Person {
+ * id: uint,
+ * name: String,
+ * phone: u64,
+ * }
+ *
+ * impl Hash for Person {
+ * fn hash(&self, state: &mut SipState) {
+ * self.id.hash(state);
+ * self.phone.hash(state);
+ * }
+ * }
+ *
+ * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
+ * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
+ *
+ * assert!(hash::hash(&person1) == hash::hash(&person2));
+ * ```
+ */
+
+pub use core_collections::hash::{Hash, Hasher, Writer, hash, sip};
+
+use default::Default;
+use rand::Rng;
+use rand;
+
+/// `RandomSipHasher` computes the SipHash algorithm from a stream of bytes
+/// initialized with random keys.
+#[deriving(Clone)]
+pub struct RandomSipHasher {
+ hasher: sip::SipHasher,
+}
+
+impl RandomSipHasher {
+ /// Construct a new `RandomSipHasher` that is initialized with random keys.
+ #[inline]
+ pub fn new() -> RandomSipHasher {
+ let mut r = rand::task_rng();
+ let r0 = r.gen();
+ let r1 = r.gen();
+ RandomSipHasher {
+ hasher: sip::SipHasher::new_with_keys(r0, r1),
+ }
+ }
+}
+
+impl Hasher<sip::SipState> for RandomSipHasher {
+ #[inline]
+ fn hash<T: Hash<sip::SipState>>(&self, value: &T) -> u64 {
+ self.hasher.hash(value)
+ }
+}
+
+impl Default for RandomSipHasher {
+ #[inline]
+ fn default() -> RandomSipHasher {
+ RandomSipHasher::new()
+ }
+}
let mut cur = [0u8, .. 2];
for f in files {
let stem = f.filestem_str().unwrap();
- let root = stem[0] - ('0' as u8);
- let name = stem[1] - ('0' as u8);
+ let root = stem.as_bytes()[0] - ('0' as u8);
+ let name = stem.as_bytes()[1] - ('0' as u8);
assert!(cur[root as uint] < name);
cur[root as uint] = name;
}
/// };
///
/// let mut buf = [0, ..10];
-/// match socket.recvfrom(buf) {
+/// match socket.recv_from(buf) {
/// Ok((amt, src)) => {
/// // Send a reply to the socket we received data from
/// let buf = buf.mut_slice_to(amt);
/// buf.reverse();
-/// socket.sendto(buf, src);
+/// socket.send_to(buf, src);
/// }
/// Err(e) => println!("couldn't receive a datagram: {}", e)
/// }
/// Receives data from the socket. On success, returns the number of bytes
/// read and the address from whence the data came.
- pub fn recvfrom(&mut self, buf: &mut [u8])
+ pub fn recv_from(&mut self, buf: &mut [u8])
-> IoResult<(uint, SocketAddr)> {
- match self.obj.recvfrom(buf) {
+ match self.obj.recv_from(buf) {
Ok((amt, rtio::SocketAddr { ip, port })) => {
Ok((amt, SocketAddr { ip: super::from_rtio(ip), port: port }))
}
}
}
+ #[allow(missing_doc)]
+ #[deprecated = "renamed to `recv_from`"]
+ pub fn recvfrom(&mut self, buf: &mut [u8])
+ -> IoResult<(uint, SocketAddr)> {
+ self.recv_from(buf)
+ }
+
/// Sends data on the socket to the given address. Returns nothing on
/// success.
- pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
- self.obj.sendto(buf, rtio::SocketAddr {
+ pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
+ self.obj.send_to(buf, rtio::SocketAddr {
ip: super::to_rtio(dst.ip),
port: dst.port,
}).map_err(IoError::from_rtio_error)
}
+ #[allow(missing_doc)]
+ #[deprecated = "renamed to `send_to`"]
+ pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
+ self.send_to(buf, dst)
+ }
+
/// Creates a `UdpStream`, which allows use of the `Reader` and `Writer`
/// traits to receive and send data from the same address. This transfers
/// ownership of the socket to the stream.
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
let peer = self.connected_to;
self.as_socket(|sock| {
- match sock.recvfrom(buf) {
+ match sock.recv_from(buf) {
Ok((_nread, src)) if src != peer => Ok(0),
Ok((nread, _src)) => Ok(nread),
Err(e) => Err(e),
impl Writer for UdpStream {
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
let connected_to = self.connected_to;
- self.as_socket(|sock| sock.sendto(buf, connected_to))
+ self.as_socket(|sock| sock.send_to(buf, connected_to))
}
}
match UdpSocket::bind(client_ip) {
Ok(ref mut client) => {
rx1.recv();
- client.sendto([99], server_ip).unwrap()
+ client.send_to([99], server_ip).unwrap()
}
Err(..) => fail!()
}
Ok(ref mut server) => {
tx1.send(());
let mut buf = [0];
- match server.recvfrom(buf) {
+ match server.recv_from(buf) {
Ok((nread, src)) => {
assert_eq!(nread, 1);
assert_eq!(buf[0], 99);
match UdpSocket::bind(client_ip) {
Ok(ref mut client) => {
rx.recv();
- client.sendto([99], server_ip).unwrap()
+ client.send_to([99], server_ip).unwrap()
}
Err(..) => fail!()
}
Ok(ref mut server) => {
tx.send(());
let mut buf = [0];
- match server.recvfrom(buf) {
+ match server.recv_from(buf) {
Ok((nread, src)) => {
assert_eq!(nread, 1);
assert_eq!(buf[0], 99);
spawn(proc() {
let mut sock2 = sock2;
let mut buf = [0, 0];
- assert_eq!(sock2.recvfrom(buf), Ok((1, addr1)));
+ assert_eq!(sock2.recv_from(buf), Ok((1, addr1)));
assert_eq!(buf[0], 1);
- sock2.sendto([2], addr1).unwrap();
+ sock2.send_to([2], addr1).unwrap();
});
let sock3 = sock1.clone();
spawn(proc() {
let mut sock3 = sock3;
rx1.recv();
- sock3.sendto([1], addr2).unwrap();
+ sock3.send_to([1], addr2).unwrap();
tx2.send(());
});
tx1.send(());
let mut buf = [0, 0];
- assert_eq!(sock1.recvfrom(buf), Ok((1, addr2)));
+ assert_eq!(sock1.recv_from(buf), Ok((1, addr2)));
rx2.recv();
})
spawn(proc() {
let mut sock2 = sock2;
- sock2.sendto([1], addr1).unwrap();
+ sock2.send_to([1], addr1).unwrap();
rx.recv();
- sock2.sendto([2], addr1).unwrap();
+ sock2.send_to([2], addr1).unwrap();
rx.recv();
});
spawn(proc() {
let mut sock3 = sock3;
let mut buf = [0, 0];
- sock3.recvfrom(buf).unwrap();
+ sock3.recv_from(buf).unwrap();
tx2.send(());
done.send(());
});
let mut buf = [0, 0];
- sock1.recvfrom(buf).unwrap();
+ sock1.recv_from(buf).unwrap();
tx1.send(());
rx.recv();
let mut buf = [0, 1];
rx.recv();
- match sock2.recvfrom(buf) {
+ match sock2.recv_from(buf) {
Ok(..) => {}
Err(e) => fail!("failed receive: {}", e),
}
let tx2 = tx.clone();
spawn(proc() {
let mut sock3 = sock3;
- match sock3.sendto([1], addr2) {
+ match sock3.send_to([1], addr2) {
Ok(..) => { let _ = tx2.send_opt(()); }
Err(..) => {}
}
done.send(());
});
- match sock1.sendto([2], addr2) {
+ match sock1.send_to([2], addr2) {
Ok(..) => { let _ = tx.send_opt(()); }
Err(..) => {}
}
serv_rx.recv();
})
- iotest!(fn recvfrom_timeout() {
+ iotest!(fn recv_from_timeout() {
let addr1 = next_test_ip4();
let addr2 = next_test_ip4();
let mut a = UdpSocket::bind(addr1).unwrap();
let (tx2, rx2) = channel();
spawn(proc() {
let mut a = UdpSocket::bind(addr2).unwrap();
- assert_eq!(a.recvfrom([0]), Ok((1, addr1)));
- assert_eq!(a.sendto([0], addr1), Ok(()));
+ assert_eq!(a.recv_from([0]), Ok((1, addr1)));
+ assert_eq!(a.send_to([0], addr1), Ok(()));
rx.recv();
- assert_eq!(a.sendto([0], addr1), Ok(()));
+ assert_eq!(a.send_to([0], addr1), Ok(()));
tx2.send(());
});
// Make sure that reads time out, but writes can continue
a.set_read_timeout(Some(20));
- assert_eq!(a.recvfrom([0]).err().unwrap().kind, TimedOut);
- assert_eq!(a.recvfrom([0]).err().unwrap().kind, TimedOut);
- assert_eq!(a.sendto([0], addr2), Ok(()));
+ assert_eq!(a.recv_from([0]).err().unwrap().kind, TimedOut);
+ assert_eq!(a.recv_from([0]).err().unwrap().kind, TimedOut);
+ assert_eq!(a.send_to([0], addr2), Ok(()));
// Cloned handles should be able to block
let mut a2 = a.clone();
- assert_eq!(a2.recvfrom([0]), Ok((1, addr2)));
+ assert_eq!(a2.recv_from([0]), Ok((1, addr2)));
// Clearing the timeout should allow for receiving
a.set_timeout(None);
tx.send(());
- assert_eq!(a2.recvfrom([0]), Ok((1, addr2)));
+ assert_eq!(a2.recv_from([0]), Ok((1, addr2)));
// Make sure the child didn't die
rx2.recv();
})
- iotest!(fn sendto_timeout() {
+ iotest!(fn send_to_timeout() {
let addr1 = next_test_ip4();
let addr2 = next_test_ip4();
let mut a = UdpSocket::bind(addr1).unwrap();
a.set_write_timeout(Some(1000));
for _ in range(0u, 100) {
- match a.sendto([0, ..4*1024], addr2) {
+ match a.send_to([0, ..4*1024], addr2) {
Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
Err(IoError { kind: TimedOut, .. }) => break,
Err(e) => fail!("other error: {}", e),
pub use alloc::owned;
pub use alloc::rc;
-pub use core_collections::hash;
pub use core_collections::slice;
pub use core_collections::str;
pub use core_collections::string;
/* Common data structures */
pub mod collections;
+pub mod hash;
/* Tasks and communication */
fn is_vol_abs(path: &str, prefix: Option<PathPrefix>) -> bool {
// assume prefix is Some(DiskPrefix)
let rest = path.slice_from(prefix_len(prefix));
- !rest.is_empty() && rest[0].is_ascii() && is_sep(rest[0] as char)
+ !rest.is_empty() && rest.as_bytes()[0].is_ascii() && is_sep(rest.as_bytes()[0] as char)
}
fn shares_volume(me: &Path, path: &str) -> bool {
// path is assumed to have a prefix of Some(DiskPrefix)
let repr = me.repr.as_slice();
match me.prefix {
- Some(DiskPrefix) => repr[0] == path[0].to_ascii().to_upper().to_byte(),
- Some(VerbatimDiskPrefix) => repr[4] == path[0].to_ascii().to_upper().to_byte(),
+ Some(DiskPrefix) => {
+ repr.as_bytes()[0] == path.as_bytes()[0].to_ascii().to_upper().to_byte()
+ }
+ Some(VerbatimDiskPrefix) => {
+ repr.as_bytes()[4] == path.as_bytes()[0].to_ascii().to_upper().to_byte()
+ }
_ => false
}
}
// if me is "C:" we don't want to add a path separator
match me.prefix {
Some(DiskPrefix) if me.repr.len() == plen => (),
- _ if !(me.repr.len() > plen && me.repr.as_slice()[me.repr.len()-1] == SEP_BYTE) => {
+ _ if !(me.repr.len() > plen && me.repr.as_bytes()[me.repr.len()-1] == SEP_BYTE) => {
s.push_char(SEP);
}
_ => ()
// absolute path, or cwd-relative and self is not same volume
replace_path(self, path, prefix);
}
- None if !path.is_empty() && is_sep_(self.prefix, path[0]) => {
+ None if !path.is_empty() && is_sep_(self.prefix, path.as_bytes()[0]) => {
// volume-relative path
if self.prefix.is_some() {
// truncate self down to the prefix, then append
match self.prefix {
Some(DiskPrefix) => {
let rest = self.repr.as_slice().slice_from(self.prefix_len());
- rest.len() > 0 && rest[0] == SEP_BYTE
+ rest.len() > 0 && rest.as_bytes()[0] == SEP_BYTE
}
Some(_) => true,
None => false
let s = match self.prefix {
Some(_) => {
let plen = self.prefix_len();
- if repr.len() > plen && repr[plen] == SEP_BYTE {
+ if repr.len() > plen && repr.as_bytes()[plen] == SEP_BYTE {
repr.slice_from(plen+1)
} else { repr.slice_from(plen) }
}
- None if repr[0] == SEP_BYTE => repr.slice_from(1),
+ None if repr.as_bytes()[0] == SEP_BYTE => repr.slice_from(1),
None => repr
};
let ret = s.split_terminator(SEP).map(Some);
match (self.prefix, other.prefix) {
(Some(DiskPrefix), Some(VerbatimDiskPrefix)) => {
self.is_absolute() &&
- s_repr[0].to_ascii().eq_ignore_case(o_repr[4].to_ascii())
+ s_repr.as_bytes()[0].to_ascii().eq_ignore_case(o_repr.as_bytes()[4].to_ascii())
}
(Some(VerbatimDiskPrefix), Some(DiskPrefix)) => {
other.is_absolute() &&
- s_repr[4].to_ascii().eq_ignore_case(o_repr[0].to_ascii())
+ s_repr.as_bytes()[4].to_ascii().eq_ignore_case(o_repr.as_bytes()[0].to_ascii())
}
(Some(VerbatimDiskPrefix), Some(VerbatimDiskPrefix)) => {
- s_repr[4].to_ascii().eq_ignore_case(o_repr[4].to_ascii())
+ s_repr.as_bytes()[4].to_ascii().eq_ignore_case(o_repr.as_bytes()[4].to_ascii())
}
(Some(UNCPrefix(_,_)), Some(VerbatimUNCPrefix(_,_))) => {
s_repr.slice(2, self.prefix_len()) == o_repr.slice(8, other.prefix_len())
let mut comps = comps;
match (comps.is_some(),prefix) {
(false, Some(DiskPrefix)) => {
- if s[0] >= 'a' as u8 && s[0] <= 'z' as u8 {
+ if s.as_bytes()[0] >= 'a' as u8 && s.as_bytes()[0] <= 'z' as u8 {
comps = Some(vec![]);
}
}
(false, Some(VerbatimDiskPrefix)) => {
- if s[4] >= 'a' as u8 && s[0] <= 'z' as u8 {
+ if s.as_bytes()[4] >= 'a' as u8 && s.as_bytes()[0] <= 'z' as u8 {
comps = Some(vec![]);
}
}
let mut s = String::with_capacity(n);
match prefix {
Some(DiskPrefix) => {
- s.push_char(prefix_[0].to_ascii().to_upper().to_char());
+ s.push_char(prefix_.as_bytes()[0].to_ascii().to_upper().to_char());
s.push_char(':');
}
Some(VerbatimDiskPrefix) => {
s.push_str(prefix_.slice_to(4));
- s.push_char(prefix_[4].to_ascii().to_upper().to_char());
+ s.push_char(prefix_.as_bytes()[4].to_ascii().to_upper().to_char());
s.push_str(prefix_.slice_from(5));
}
Some(UNCPrefix(a,b)) => {
fn has_nonsemantic_trailing_slash(&self) -> bool {
is_verbatim(self) && self.repr.len() > self.prefix_len()+1 &&
- self.repr.as_slice()[self.repr.len()-1] == SEP_BYTE
+ self.repr.as_bytes()[self.repr.len()-1] == SEP_BYTE
}
fn update_normalized<S: Str>(&mut self, s: S) {
/// but absolute within that volume.
#[inline]
pub fn is_vol_relative(path: &Path) -> bool {
- path.prefix.is_none() && is_sep_byte(&path.repr.as_slice()[0])
+ path.prefix.is_none() && is_sep_byte(&path.repr.as_bytes()[0])
}
/// Returns whether the path is considered "cwd-relative", which means a path
} else {
// \\?\path
let idx = path.find('\\');
- if idx == Some(2) && path[1] == ':' as u8 {
- let c = path[0];
+ if idx == Some(2) && path.as_bytes()[1] == ':' as u8 {
+ let c = path.as_bytes()[0];
if c.is_ascii() && ::char::is_alphabetic(c as char) {
// \\?\C:\ path
return Some(VerbatimDiskPrefix);
}
_ => ()
}
- } else if path.len() > 1 && path[1] == ':' as u8 {
+ } else if path.len() > 1 && path.as_bytes()[1] == ':' as u8 {
// C:
- let c = path[0];
+ let c = path.as_bytes()[0];
if c.is_ascii() && ::char::is_alphabetic(c as char) {
return Some(DiskPrefix);
}
}
let orig = fm.get_line(*lines.lines.get(0) as int);
for pos in range(0u, left-skip) {
- let cur_char = orig.as_slice()[pos] as char;
+ let cur_char = orig.as_bytes()[pos] as char;
// Whenever a tab occurs on the previous line, we insert one on
// the error-point-squiggly-line as well (instead of a space).
// That way the squiggly line will usually appear in the correct
fn read_one_line_comment(&mut self) -> String {
let val = self.read_to_eol();
- assert!((val.as_slice()[0] == '/' as u8 && val.as_slice()[1] == '/' as u8)
- || (val.as_slice()[0] == '#' as u8 && val.as_slice()[1] == '!' as u8));
+ assert!((val.as_bytes()[0] == '/' as u8 && val.as_bytes()[1] == '/' as u8)
+ || (val.as_bytes()[0] == '#' as u8 && val.as_bytes()[1] == '!' as u8));
return val;
}
fn match_str(s: &str, pos: uint, needle: &str) -> bool {
let mut i = pos;
for ch in needle.bytes() {
- if s[i] != ch {
+ if s.as_bytes()[i] != ch {
return false;
}
i += 1u;
let mut s: Vec<u8> = Vec::from_elem(32, 0u8);
for i in range(0u, 16u) {
let digit = format!("{:02x}", self.bytes[i] as uint);
- *s.get_mut(i*2+0) = digit.as_slice()[0];
- *s.get_mut(i*2+1) = digit.as_slice()[1];
+ *s.get_mut(i*2+0) = digit.as_bytes()[0];
+ *s.get_mut(i*2+1) = digit.as_bytes()[1];
}
str::from_utf8(s.as_slice()).unwrap().to_string()
}
if line.len() == 0u { continue; }
- match (line.as_slice()[0] as char, proc_mode) {
+ match (line.as_bytes()[0] as char, proc_mode) {
// start processing if this is the one
('>', false) => {
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
+// The Computer Language Benchmarks Game
+// http://benchmarksgame.alioth.debian.org/
//
-// 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.
+// contributed by the Rust Project Developers
+
+// Copyright (c) 2012-2014 The Rust Project Developers
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// - Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// - Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in
+// the documentation and/or other materials provided with the
+// distribution.
+//
+// - Neither the name of "The Computer Language Benchmarks Game" nor
+// the name of "The Computer Language Shootout Benchmarks" nor the
+// names of its contributors may be used to endorse or promote
+// products derived from this software without specific prior
+// written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+// OF THE POSSIBILITY OF SUCH DAMAGE.
+
#![feature(macro_rules)]
#![feature(simd)]
#![allow(experimental)]
assert_eq!(v.as_slice()[3u32], 3); //~ ERROR: mismatched types
assert_eq!(v.as_slice()[3i32], 3); //~ ERROR: mismatched types
println!("{}", v.as_slice()[3u8]); //~ ERROR: mismatched types
- assert_eq!(s.as_slice()[3u], 'd' as u8);
- assert_eq!(s.as_slice()[3u8], 'd' as u8); //~ ERROR: mismatched types
- assert_eq!(s.as_slice()[3i8], 'd' as u8); //~ ERROR: mismatched types
- assert_eq!(s.as_slice()[3u32], 'd' as u8); //~ ERROR: mismatched types
- assert_eq!(s.as_slice()[3i32], 'd' as u8); //~ ERROR: mismatched types
- println!("{}", s.as_slice()[3u8]); //~ ERROR: mismatched types
+ assert_eq!(s.as_bytes()[3u], 'd' as u8);
+ assert_eq!(s.as_bytes()[3u8], 'd' as u8); //~ ERROR: mismatched types
+ assert_eq!(s.as_bytes()[3i8], 'd' as u8); //~ ERROR: mismatched types
+ assert_eq!(s.as_bytes()[3u32], 'd' as u8); //~ ERROR: mismatched types
+ assert_eq!(s.as_bytes()[3i32], 'd' as u8); //~ ERROR: mismatched types
+ println!("{}", s.as_bytes()[3u8]); //~ ERROR: mismatched types
}
--- /dev/null
+// 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.
+
+extern crate debug;
+
+pub fn main() {
+ let s: &str = "hello";
+ let c: u8 = s[4]; //~ ERROR cannot index a value of type `&str`
+}
let s: String = "hello".to_string();
// Bounds-check failure.
- assert_eq!(s.as_slice()[5], 0x0 as u8);
+ assert_eq!(s.as_bytes()[5], 0x0 as u8);
}
println!("{}", x);
println!("{}", y);
- assert_eq!(x[0], 'h' as u8);
- assert_eq!(x[4], 'o' as u8);
+ assert_eq!(x.as_bytes()[0], 'h' as u8);
+ assert_eq!(x.as_bytes()[4], 'o' as u8);
let z : &str = "thing";
assert_eq!(v, x);
let _y : String = "there".to_string();
let mut z = "thing".to_string();
z = x;
- assert_eq!(z.as_slice()[0], ('h' as u8));
- assert_eq!(z.as_slice()[4], ('o' as u8));
+ assert_eq!(z.as_bytes()[0], ('h' as u8));
+ assert_eq!(z.as_bytes()[4], ('o' as u8));
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![allow(dead_code)]
+
+trait Foo {}
+impl Foo for int {}
+fn foo(_: [&Foo, ..2]) {}
+fn foos(_: &[&Foo]) {}
+fn foog<T>(_: &[T], _: &[T]) {}
+
+fn bar(_: [Box<Foo>, ..2]) {}
+fn bars(_: &[Box<Foo>]) {}
+
+fn main() {
+ let x: [&Foo, ..2] = [&1i, &2i];
+ foo(x);
+ foo([&1i, &2i]);
+
+ let r = &1i;
+ let x: [&Foo, ..2] = [r, ..2];
+ foo(x);
+ foo([&1i, ..2]);
+
+ let x: &[&Foo] = &[&1i, &2i];
+ foos(x);
+ foos(&[&1i, &2i]);
+
+ let x: &[&Foo] = &[&1i, &2i];
+ let r = &1i;
+ foog(x, &[r]);
+
+ let x: [Box<Foo>, ..2] = [box 1i, box 2i];
+ bar(x);
+ bar([box 1i, box 2i]);
+
+ let x: &[Box<Foo>] = &[box 1i, box 2i];
+ bars(x);
+ bars(&[box 1i, box 2i]);
+
+ let x: &[Box<Foo>] = &[box 1i, box 2i];
+ foog(x, &[box 1i]);
+
+ struct T<'a> {
+ t: [&'a Foo, ..2]
+ }
+ let _n = T {
+ t: [&1i, &2i]
+ };
+ let r = &1i;
+ let _n = T {
+ t: [r, ..2]
+ };
+ let x: [&Foo, ..2] = [&1i, &2i];
+ let _n = T {
+ t: x
+ };
+
+ struct F<'b> {
+ t: &'b [&'b Foo]
+ }
+ let _n = F {
+ t: &[&1i, &2i]
+ };
+ let r = &1i;
+ let r: [&Foo, ..2] = [r, ..2];
+ let _n = F {
+ t: r
+ };
+ let x: [&Foo, ..2] = [&1i, &2i];
+ let _n = F {
+ t: x
+ };
+
+ struct M<'a> {
+ t: &'a [Box<Foo>]
+ }
+ let _n = M {
+ t: &[box 1i, box 2i]
+ };
+ let x: [Box<Foo>, ..2] = [box 1i, box 2i];
+ let _n = M {
+ t: x
+ };
+}
let b: String = "world".to_string();
let s: String = format!("{}{}", a, b);
println!("{}", s.clone());
- assert_eq!(s.as_slice()[9], 'd' as u8);
+ assert_eq!(s.as_bytes()[9], 'd' as u8);
}
+++ /dev/null
-// 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.
-
-extern crate debug;
-
-pub fn main() {
- let s = "hello".to_string();
- let c: u8 = s.as_slice()[4];
- println!("{:?}", c);
- assert_eq!(c, 0x6f as u8);
-}
let s0 = "test".to_string();
tx.send(s0);
let s1 = rx.recv();
- assert_eq!(s1.as_slice()[0], 't' as u8);
- assert_eq!(s1.as_slice()[1], 'e' as u8);
- assert_eq!(s1.as_slice()[2], 's' as u8);
- assert_eq!(s1.as_slice()[3], 't' as u8);
+ assert_eq!(s1.as_bytes()[0], 't' as u8);
+ assert_eq!(s1.as_bytes()[1], 'e' as u8);
+ assert_eq!(s1.as_bytes()[2], 's' as u8);
+ assert_eq!(s1.as_bytes()[3], 't' as u8);
}
#[deriving(Show)]
fn check_names(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
for pet in arc.iter() {
pet.name(|name| {
- assert!(name[0] == 'a' as u8 && name[1] == 'l' as u8);
+ assert!(name.as_bytes()[0] == 'a' as u8 && name.as_bytes()[1] == 'l' as u8);
})
}
}
for ab in a.as_slice().bytes() {
println!("{}", i);
println!("{}", ab);
- let bb: u8 = b.as_slice()[i as uint];
+ let bb: u8 = b.as_bytes()[i as uint];
println!("{}", bb);
assert_eq!(ab, bb);
i += 1;