The reasoning for doing it this way is that it's much easier to transition method-by-method to the `Map` API than trying to do the migration all at once.
I found an issue unrelated to my changes in one of the run-fail tests - if it uses `LinearMap`, it still fails but exits with 0. I xfailed it for now and opened [an issue](https://github.com/mozilla/rust/issues/5512), because it's not caused by these changes.
r?
There are a lot of commits here, but not all that much substance. Mostly just refactoring.
I started sketching out the beginnings of a very simple I/O API in `core::rt::io` that represents I/O streams as a single `Stream` trait instead of `Reader` / `Writer` pairs. This seems to be the more common pattern (at least this is how the .NET BCL does it) and it seems to me that separate readers and writers would make duplex streams very awkward. Regardless, I don't intend to go very far down the I/O API design road without some mailing list discussion.
I've also started on the uv bindings for file I/O but haven't gotten very far.
Also hooked up the new scheduler to `rust_start` and the compiletest driver. 70% of run-pass test cases already pass, but I wouldn't read too much into that.
I also split the direct, low-level uv bindings in two so that the scheduler can have its own set, leaving `std::net` on its own.
As per #2521. Inlining seems to improve performance slightly:
Inlined Not Inlined
x86: 13.5482 14.4112
x86_64: 17.4712 18.0696
(Average of 5 runs timed with `time`)
```Rust
fn foo() -> int {
int::from_str(~"28098").unwrap()
}
fn main() {
for 1000000.times {
foo();
foo();
foo();
foo();
foo();
}
}
```
All run on:
Linux 3.2.0-0.bpo.4-amd64 #1 SMP Debian 3.2.35-2~bpo60+1 x86_64 GNU/Linux
The MIPS and ARM bits I didn't inline since I'm not as familiar with them and I also can't test them. All green on try.
This is a minor step towards #3571, although I'm sure there's still more work to be done. Previously, `fmt!` collected a bunch of strings in a vector and then called `str::concat`. This changes the behavior by maintaining only one buffer and appending directly into that buffer. This avoids doubly-allocating memory, and it has the added bonus of reducing some allocations in `core::unstable::extfmt`
One of the unfortunate side effects of this is that the `rt` module in `extfmt.rs` had to be duplicated to avoid `stage0` errors. Dealing with the change in conversion functions may require a bit of a dance when a snapshot happens, but I think it's doable.
If the second speedup commit isn't deemed necessary, I got about a 15% speedup with just the first patch which doesn't require any modification of `extfmt.rs`, so no snapshot weirdness.
Here's some other things I ran into when looking at `fmt!`:
* I don't think that #2249 is relevant any more except for maybe removing one of `%i` or `%d`
* I'm not sure what was in mind for using traits with #3571, but I thought that formatters like `%u` could invoke the `to_uint()` method on the `NumCast` trait, but I ran into some problems like those in #5462
I'm having trouble thinking of other wins for `fmt!`, but if there's some suggestions I'd be more than willing to look into if they'd work out or not.
The `each_line` function in `ReaderUtil` acts very differently to equivalent functions in Python, Ruby, Clojure etc. E.g. given a file `t` with contents `trailing\nnew line\n` and `n` containing `no trailing\nnew line`:
Rust:
```Rust
t: ~[~"trailing", ~"new line", ~""]
n: ~[~"no trailing", ~"new line"]
```
Python:
```Python
>>> open('t').readlines()
['trailing\n', 'new line\n']
>>> open('n').readlines()
['no trailing\n', 'new line']
```
Ruby:
```Ruby
irb(main):001:0> File.readlines('t')
=> ["trailing\n", "new line\n"]
irb(main):002:0> File.readlines('n')
=> ["no trailing\n", "new line"]
```
Clojure
```Clojure
user=> (read-lines "t")
("trailing" "new line")
user=> (read-lines "n")
("no trailing" "new line")
```
The extra string that rust includes at the end is inconsistent, and means that it is impossible to distinguish between the "real" empty line a file that ends `...\n\n`, and the "fake" one after the last `\n`.
The code attached makes Rust's `each_line` act like Clojure (and PHP, i.e. not including the `\n`), as well as adjusting `str::lines` to fix the trailing empty line problem.
Also, add a convenience `read_lines` method to read all the lines in a file into a vector.