]> git.lizzy.rs Git - rust.git/commitdiff
Move std::rt::io to std::io
authorAlex Crichton <alex@alexcrichton.com>
Mon, 11 Nov 2013 06:46:32 +0000 (22:46 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Tue, 12 Nov 2013 04:44:07 +0000 (20:44 -0800)
141 files changed:
doc/tutorial.md
src/compiletest/compiletest.rs
src/compiletest/errors.rs
src/compiletest/header.rs
src/compiletest/procsrv.rs
src/compiletest/runtest.rs
src/etc/combine-tests.py
src/libextra/ebml.rs
src/libextra/glob.rs
src/libextra/json.rs
src/libextra/stats.rs
src/libextra/tempfile.rs
src/libextra/term.rs
src/libextra/terminfo/parser/compiled.rs
src/libextra/terminfo/searcher.rs
src/libextra/test.rs
src/libextra/time.rs
src/libextra/url.rs
src/libextra/uuid.rs
src/libextra/workcache.rs
src/librustc/back/link.rs
src/librustc/driver/driver.rs
src/librustc/lib.rs
src/librustc/metadata/decoder.rs
src/librustc/metadata/encoder.rs
src/librustc/metadata/filesearch.rs
src/librustc/metadata/loader.rs
src/librustc/metadata/tyencode.rs
src/librustc/middle/astencode.rs
src/librustc/middle/dataflow.rs
src/librustc/middle/liveness.rs
src/librustdoc/html/format.rs
src/librustdoc/html/layout.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/librustpkg/conditions.rs
src/librustpkg/installed_packages.rs
src/librustpkg/lib.rs
src/librustpkg/messages.rs
src/librustpkg/package_source.rs
src/librustpkg/path_util.rs
src/librustpkg/source_control.rs
src/librustpkg/tests.rs
src/librustpkg/testsuite/pass/src/fancy-lib/pkg.rs
src/librustpkg/util.rs
src/librustpkg/workcache_support.rs
src/librustuv/addrinfo.rs
src/librustuv/file.rs
src/librustuv/lib.rs
src/librustuv/macros.rs
src/librustuv/net.rs
src/librustuv/pipe.rs
src/librustuv/process.rs
src/librustuv/signal.rs
src/librustuv/tty.rs
src/librustuv/uvio.rs
src/libstd/fmt/mod.rs
src/libstd/hash.rs
src/libstd/io/buffered.rs [new file with mode: 0644]
src/libstd/io/comm_adapters.rs [new file with mode: 0644]
src/libstd/io/extensions.rs [new file with mode: 0644]
src/libstd/io/flate.rs [new file with mode: 0644]
src/libstd/io/fs.rs [new file with mode: 0644]
src/libstd/io/mem.rs [new file with mode: 0644]
src/libstd/io/mod.rs [new file with mode: 0644]
src/libstd/io/native/file.rs [new file with mode: 0644]
src/libstd/io/native/process.rs [new file with mode: 0644]
src/libstd/io/native/stdio.rs [new file with mode: 0644]
src/libstd/io/net/addrinfo.rs [new file with mode: 0644]
src/libstd/io/net/ip.rs [new file with mode: 0644]
src/libstd/io/net/mod.rs [new file with mode: 0644]
src/libstd/io/net/tcp.rs [new file with mode: 0644]
src/libstd/io/net/udp.rs [new file with mode: 0644]
src/libstd/io/net/unix.rs [new file with mode: 0644]
src/libstd/io/option.rs [new file with mode: 0644]
src/libstd/io/pipe.rs [new file with mode: 0644]
src/libstd/io/process.rs [new file with mode: 0644]
src/libstd/io/signal.rs [new file with mode: 0644]
src/libstd/io/stdio.rs [new file with mode: 0644]
src/libstd/io/timer.rs [new file with mode: 0644]
src/libstd/lib.rs
src/libstd/os.rs
src/libstd/prelude.rs
src/libstd/rand/os.rs
src/libstd/rand/reader.rs
src/libstd/repr.rs
src/libstd/rt/io/buffered.rs [deleted file]
src/libstd/rt/io/comm_adapters.rs [deleted file]
src/libstd/rt/io/extensions.rs [deleted file]
src/libstd/rt/io/flate.rs [deleted file]
src/libstd/rt/io/fs.rs [deleted file]
src/libstd/rt/io/mem.rs [deleted file]
src/libstd/rt/io/mod.rs [deleted file]
src/libstd/rt/io/native/file.rs [deleted file]
src/libstd/rt/io/native/process.rs [deleted file]
src/libstd/rt/io/native/stdio.rs [deleted file]
src/libstd/rt/io/net/addrinfo.rs [deleted file]
src/libstd/rt/io/net/ip.rs [deleted file]
src/libstd/rt/io/net/mod.rs [deleted file]
src/libstd/rt/io/net/tcp.rs [deleted file]
src/libstd/rt/io/net/udp.rs [deleted file]
src/libstd/rt/io/net/unix.rs [deleted file]
src/libstd/rt/io/option.rs [deleted file]
src/libstd/rt/io/pipe.rs [deleted file]
src/libstd/rt/io/process.rs [deleted file]
src/libstd/rt/io/signal.rs [deleted file]
src/libstd/rt/io/stdio.rs [deleted file]
src/libstd/rt/io/timer.rs [deleted file]
src/libstd/rt/logging.rs
src/libstd/rt/mod.rs
src/libstd/rt/rtio.rs
src/libstd/rt/sched.rs
src/libstd/rt/task.rs
src/libstd/rt/test.rs
src/libstd/rt/util.rs
src/libstd/run.rs
src/libstd/to_bytes.rs
src/libsyntax/diagnostic.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/source_util.rs
src/libsyntax/parse/comments.rs
src/libsyntax/parse/mod.rs
src/libsyntax/print/pp.rs
src/libsyntax/print/pprust.rs
src/test/bench/core-std.rs
src/test/bench/shootout-fasta.rs
src/test/bench/shootout-k-nucleotide-pipes.rs
src/test/bench/sudoku.rs
src/test/run-pass/core-run-destroy.rs
src/test/run-pass/deriving-encodable-decodable.rs
src/test/run-pass/glob-std.rs
src/test/run-pass/ifmt.rs
src/test/run-pass/issue-2904.rs
src/test/run-pass/issue-4333.rs
src/test/run-pass/issue-8398.rs
src/test/run-pass/rename-directory.rs
src/test/run-pass/rtio-processes.rs
src/test/run-pass/signal-exit-status.rs
src/test/run-pass/stat.rs
src/test/run-pass/tempfile.rs

index 2bcfa567b44a6452b47478758941e0f9e18d96aa..5f805b39f238bed8c725cd8590c7d9dbfcbcc5e7 100644 (file)
@@ -2839,12 +2839,12 @@ you just have to import it with an `use` statement.
 For example, it re-exports `println` which is defined in `std::io::println`:
 
 ~~~
-use puts = std::rt::io::stdio::println;
+use puts = std::io::stdio::println;
 
 fn main() {
     println("println is imported per default.");
     puts("Doesn't hinder you from importing it under an different name yourself.");
-    ::std::rt::io::stdio::println("Or from not using the automatic import.");
+    ::std::io::stdio::println("Or from not using the automatic import.");
 }
 ~~~
 
index e464e0e687c4b2e096d91d8139648f908c1e2e4a..15bddfc80221c8379fc587fa75a40f27149fddc1 100644 (file)
@@ -17,7 +17,7 @@
 
 use std::os;
 use std::rt;
-use std::rt::io::fs;
+use std::io::fs;
 
 use extra::getopts;
 use extra::getopts::groups::{optopt, optflag, reqopt};
index dcb0d2ef01d39b2dbea49215cbf5f6c784e6839c..6be92b12535f5b34b967fcb3ecf1e075a793460f 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::rt::io::buffered::BufferedReader;
-use std::rt::io::File;
+use std::io::buffered::BufferedReader;
+use std::io::File;
 
 pub struct ExpectedError { line: uint, kind: ~str, msg: ~str }
 
index 5571e159ee31dcaa27071508298ede3cea5a3d34..c63436a2c55bd8ee358b79027e4647e1bfb38e5e 100644 (file)
@@ -103,8 +103,8 @@ fn xfail_target(config: &config) -> ~str {
 }
 
 fn iter_header(testfile: &Path, it: &fn(&str) -> bool) -> bool {
-    use std::rt::io::buffered::BufferedReader;
-    use std::rt::io::File;
+    use std::io::buffered::BufferedReader;
+    use std::io::File;
 
     let mut rdr = BufferedReader::new(File::open(testfile).unwrap());
     loop {
index 32ee19badd209c115e131e4744726d85f16a00d1..e107c53018def877537133aa788db673c66ca74b 100644 (file)
@@ -11,7 +11,7 @@
 use std::os;
 use std::run;
 use std::str;
-use std::rt::io::process::ProcessExit;
+use std::io::process::ProcessExit;
 
 #[cfg(target_os = "win32")]
 fn target_env(lib_path: &str, prog: &str) -> ~[(~str,~str)] {
index ffd5e721d67f41463fa18859f6ec500f73b567c9..33bd62632095f18da4c7d2c5cdbfcfa6e804fc96 100644 (file)
@@ -8,30 +8,30 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use common::mode_run_pass;
-use common::mode_run_fail;
+use common::config;
 use common::mode_compile_fail;
 use common::mode_pretty;
-use common::config;
+use common::mode_run_fail;
+use common::mode_run_pass;
 use errors;
-use header::load_props;
 use header::TestProps;
+use header::load_props;
 use procsrv;
-use util;
 use util::logv;
+use util;
 
-use std::rt::io;
-use std::rt::io::fs;
-use std::rt::io::File;
-use std::rt::io::process;
-use std::rt::io::process::ProcessExit;
+use std::io::File;
+use std::io::fs;
+use std::io::net::ip::{Ipv4Addr, SocketAddr};
+use std::io::net::tcp;
+use std::io::process::ProcessExit;
+use std::io::process;
+use std::io::timer;
+use std::io;
 use std::os;
 use std::str;
-use std::vec;
-use std::rt::io::net::tcp;
-use std::rt::io::net::ip::{Ipv4Addr, SocketAddr};
 use std::task;
-use std::rt::io::timer;
+use std::vec;
 
 use extra::test::MetricMap;
 
index dc5e11dabdf6822080a5dae22ebbf60a72905f81..0abe4dae606b808395696d2202de9d5dcd6cea04 100755 (executable)
@@ -56,8 +56,8 @@ d.write("#[feature(globs, managed_boxes)];\n")
 d.write("extern mod extra;\n")
 d.write("extern mod run_pass_stage2;\n")
 d.write("use run_pass_stage2::*;\n")
-d.write("use std::rt::io;\n");
-d.write("use std::rt::io::Writer;\n");
+d.write("use std::io;\n");
+d.write("use std::io::Writer;\n");
 d.write("fn main() {\n");
 d.write("    let mut out = io::stdout();\n");
 i = 0
index f577ed55f9750cef212332ffd9b94bdfbe2d3f02..c249a8c09f29b0695506d8bfd843b5dcc6eaf044 100644 (file)
@@ -97,7 +97,7 @@ pub mod reader {
     use std::cast::transmute;
     use std::int;
     use std::option::{None, Option, Some};
-    use std::rt::io::extensions::u64_from_be_bytes;
+    use std::io::extensions::u64_from_be_bytes;
 
     // ebml reading
 
@@ -608,10 +608,10 @@ pub mod writer {
 
     use std::cast;
     use std::clone::Clone;
-    use std::rt::io;
-    use std::rt::io::{Writer, Seek};
-    use std::rt::io::mem::MemWriter;
-    use std::rt::io::extensions::u64_to_be_bytes;
+    use std::io;
+    use std::io::{Writer, Seek};
+    use std::io::mem::MemWriter;
+    use std::io::extensions::u64_to_be_bytes;
 
     // ebml writing
     pub struct Encoder {
@@ -961,8 +961,8 @@ mod tests {
     use serialize::Encodable;
     use serialize;
 
-    use std::rt::io::Decorator;
-    use std::rt::io::mem::MemWriter;
+    use std::io::Decorator;
+    use std::io::mem::MemWriter;
     use std::option::{None, Option, Some};
 
     #[test]
index 1edef5ddbe1b4f4d8de22da761c9cbfbd803c332..d371d7bbdb3aafba22167d81dceef19e2da86b01 100644 (file)
@@ -24,8 +24,8 @@
  */
 
 use std::{os, path};
-use std::rt::io;
-use std::rt::io::fs;
+use std::io;
+use std::io::fs;
 use std::path::is_sep;
 
 use sort;
index 9f75d6771360ac85ff55b021a389bec494ad8f0d..7370dfafba9c8df1dd1175204b0b8b24b943c591 100644 (file)
@@ -20,9 +20,9 @@
 use std::cast::transmute;
 use std::f64;
 use std::hashmap::HashMap;
-use std::rt::io;
-use std::rt::io::Decorator;
-use std::rt::io::mem::MemWriter;
+use std::io;
+use std::io::Decorator;
+use std::io::mem::MemWriter;
 use std::num;
 use std::str;
 use std::to_str;
@@ -1311,7 +1311,7 @@ mod tests {
 
     use super::*;
 
-    use std::rt::io;
+    use std::io;
     use serialize::Decodable;
     use treemap::TreeMap;
 
@@ -1483,8 +1483,8 @@ fn test_write_object() {
     }
 
     fn with_str_writer(f: &fn(@mut io::Writer)) -> ~str {
-        use std::rt::io::mem::MemWriter;
-        use std::rt::io::Decorator;
+        use std::io::mem::MemWriter;
+        use std::io::Decorator;
         use std::str;
 
         let m = @mut MemWriter::new();
index 497145ca7c992c6468422c775e45aa205df5ef5b..44c399c89da4c681477415194e87ac3592546a40 100644 (file)
@@ -13,7 +13,7 @@
 use sort;
 use std::cmp;
 use std::hashmap;
-use std::rt::io;
+use std::io;
 use std::num;
 
 // NB: this can probably be rewritten in terms of num::Num
@@ -388,7 +388,7 @@ mod tests {
     use stats::Summary;
     use stats::write_5_number_summary;
     use stats::write_boxplot;
-    use std::rt::io;
+    use std::io;
     use std::str;
 
     fn check(samples: &[f64], summ: &Summary) {
@@ -942,8 +942,8 @@ fn test_unif25() {
     #[test]
     fn test_boxplot_nonpositive() {
         fn t(s: &Summary, expected: ~str) {
-            use std::rt::io::mem::MemWriter;
-            use std::rt::io::Decorator;
+            use std::io::mem::MemWriter;
+            use std::io::Decorator;
             let mut m = MemWriter::new();
             write_boxplot(&mut m as &mut io::Writer, s, 30);
             let out = str::from_utf8_owned(m.inner());
index fbd65cab98ca7858f522446b3f727762fe647ec9..5bcba2957230407023652b6559fe22ebc257cc78 100644 (file)
@@ -14,8 +14,8 @@
 use std::os;
 use std::rand::Rng;
 use std::rand;
-use std::rt::io;
-use std::rt::io::fs;
+use std::io;
+use std::io::fs;
 
 /// A wrapper for a path to temporary directory implementing automatic
 /// scope-pased deletion.
index 22ce833ea24d9b97d4351eda4298a3587b8f7bd2..05c6a366807369bdfd5a0969476ab21134ca4459 100644 (file)
@@ -13,7 +13,7 @@
 #[allow(missing_doc)];
 
 
-use std::rt::io;
+use std::io;
 
 #[cfg(not(target_os = "win32"))] use std::os;
 #[cfg(not(target_os = "win32"))] use terminfo::*;
index 04b30e5ef7474c911d22541adde858792135902d..17ea165c7e542d613863b9d319af9c2dbb309e0f 100644 (file)
@@ -15,7 +15,7 @@
 
 use std::{vec, str};
 use std::hashmap::HashMap;
-use std::rt::io;
+use std::io;
 use super::super::TermInfo;
 
 // These are the orders ncurses uses in its compiled format (as of 5.9). Not sure if portable.
index 09ceae66bb12d355ee95c0bc02ec874fa96e08ce..3754849b3eaf0a19ecca5d3a46f34bbb2bc4fc47 100644 (file)
@@ -13,8 +13,8 @@
 
 use std::{os, str};
 use std::os::getenv;
-use std::rt::io;
-use std::rt::io::File;
+use std::io;
+use std::io::File;
 
 /// Return path to database entry for `term`
 pub fn get_dbpath_for_term(term: &str) -> Option<~Path> {
index 04f045c961ff53565f704b3ca8674c0fbf957d73..14fee38dada2c6971d623247ad88a3d871091718 100644 (file)
@@ -30,8 +30,8 @@
 
 use std::clone::Clone;
 use std::comm::{stream, SharedChan, GenericPort, GenericChan};
-use std::rt::io;
-use std::rt::io::File;
+use std::io;
+use std::io::File;
 use std::task;
 use std::to_str::ToStr;
 use std::f64;
@@ -655,9 +655,9 @@ fn len_if_padded(t: &TestDescAndFn) -> uint {
 
 #[test]
 fn should_sort_failures_before_printing_them() {
-    use std::rt::io;
-    use std::rt::io::Decorator;
-    use std::rt::io::mem::MemWriter;
+    use std::io;
+    use std::io::Decorator;
+    use std::io::mem::MemWriter;
     use std::str;
     fn dummy() {}
 
index aed42e8d7fe965cb59cafb4d43adb78db14e8868..901daba84ed51331a2b3daf4c8fcc0464ef79993 100644 (file)
@@ -10,8 +10,8 @@
 
 #[allow(missing_doc)];
 
-use std::rt::io::Reader;
-use std::rt::io::mem::BufReader;
+use std::io::Reader;
+use std::io::mem::BufReader;
 use std::num;
 use std::str;
 
index 8005acf6e6bcbff6e2939ef8e14bb393c3d508bf..7570d26901c95e097611db1426171d4a0e078b81 100644 (file)
@@ -12,8 +12,8 @@
 
 #[allow(missing_doc)];
 
-use std::rt::io::{Reader, Seek};
-use std::rt::io::mem::BufReader;
+use std::io::{Reader, Seek};
+use std::io::mem::BufReader;
 use std::cmp::Eq;
 use std::hashmap::HashMap;
 use std::to_bytes;
index 54ce349a0b484dd722cb9ada18f891ea47de9129..62a15a922fa35927aa2eadb57d5c24d4412de223 100644 (file)
@@ -522,8 +522,8 @@ mod test {
     use std::str;
     use std::rand;
     use std::num::Zero;
-    use std::rt::io::Decorator;
-    use std::rt::io::mem::MemWriter;
+    use std::io::Decorator;
+    use std::io::mem::MemWriter;
 
     #[test]
     fn test_new_nil() {
index eed37a426be2db6252354e5d4541203be6ef24d3..89e50f53ab464c175a2ffd2abeccccd637eaeda0 100644 (file)
@@ -18,9 +18,9 @@
 use std::cell::Cell;
 use std::comm::{PortOne, oneshot};
 use std::{str, task};
-use std::rt::io;
-use std::rt::io::{File, Decorator};
-use std::rt::io::mem::MemWriter;
+use std::io;
+use std::io::{File, Decorator};
+use std::io::mem::MemWriter;
 
 /**
 *
@@ -479,7 +479,7 @@ pub fn unwrap(self) -> T {
 #[test]
 fn test() {
     use std::{os, run};
-    use std::rt::io::fs;
+    use std::io::fs;
     use std::str::from_utf8_owned;
 
     // Create a path to a new file 'filename' in the directory in which
index 9b0a2c5fde8b0b0100437b1097dd8403dc15cdc8..01b257cd8b35c343ed6f99ce07a56e5d2373fb7b 100644 (file)
@@ -31,7 +31,7 @@
 use std::run;
 use std::str;
 use std::vec;
-use std::rt::io::fs;
+use std::io::fs;
 use syntax::abi;
 use syntax::ast;
 use syntax::ast_map::{path, path_mod, path_name, path_pretty_name};
@@ -968,7 +968,7 @@ pub fn link_binary(sess: Session,
 }
 
 fn is_writeable(p: &Path) -> bool {
-    use std::rt::io;
+    use std::io;
 
     !p.exists() ||
         (match io::result(|| p.stat()) {
index 880d79ac48a935f23c451995fbe648617f770be4..f920b8debf1013092b7d9de175ac9c58f9114fc6 100644 (file)
@@ -26,9 +26,9 @@
 use util::ppaux;
 
 use std::hashmap::{HashMap,HashSet};
-use std::rt::io;
-use std::rt::io::fs;
-use std::rt::io::mem::MemReader;
+use std::io;
+use std::io::fs;
+use std::io::mem::MemReader;
 use std::os;
 use std::vec;
 use extra::getopts::groups::{optopt, optmulti, optflag, optflagopt};
index 798418f52dc74d707ecb92353ad2e1faea7efaa2..f67de4456034b211dfd0d772f91724ab401b2072 100644 (file)
@@ -34,8 +34,8 @@
 use middle::lint;
 
 use std::comm;
-use std::rt::io;
-use std::rt::io::Reader;
+use std::io;
+use std::io::Reader;
 use std::num;
 use std::os;
 use std::result;
index b63d9320bd6e0c816d2b799e44d3eafe157cad3d..0680968703f9462870708430edb5e4cedbb57af3 100644 (file)
@@ -27,8 +27,8 @@
 
 use std::at_vec;
 use std::u64;
-use std::rt::io;
-use std::rt::io::extensions::u64_from_be_bytes;
+use std::io;
+use std::io::extensions::u64_from_be_bytes;
 use std::option;
 use std::str;
 use std::vec;
index fe9ca6a16f0c2714e730723b1b6bfa85149a7cca..be45bf81867fc3e5759797adab0739e36777475c 100644 (file)
@@ -22,8 +22,8 @@
 use middle;
 
 use std::hashmap::{HashMap, HashSet};
-use std::rt::io::{Writer, Seek, Decorator};
-use std::rt::io::mem::MemWriter;
+use std::io::{Writer, Seek, Decorator};
+use std::io::mem::MemWriter;
 use std::str;
 use std::vec;
 
index c9bd5eff4a771f3bf89591aecf6ffd8017a1bf3b..237c50ab294107e08f5455b3d1cd497be5be69db 100644 (file)
@@ -11,8 +11,8 @@
 
 use std::option;
 use std::os;
-use std::rt::io;
-use std::rt::io::fs;
+use std::io;
+use std::io::fs;
 use std::hashmap::HashSet;
 
 pub enum FileMatch { FileMatches, FileDoesntMatch }
index 34eb387a3f5d4c47df12b2d945ade5b4dd07a565..391b894460034cbe1a2d97aa41f9025b87d634e0 100644 (file)
@@ -25,7 +25,7 @@
 
 use std::c_str::ToCStr;
 use std::cast;
-use std::rt::io;
+use std::io;
 use std::num;
 use std::option;
 use std::os::consts::{macos, freebsd, linux, android, win32};
index d304db0935ac5452902eb8addc75765bd0fe341e..49afb29488d9d620f72f2c253a641bf63fd7d590 100644 (file)
@@ -11,9 +11,9 @@
 // Type encoding
 
 use std::hashmap::HashMap;
-use std::rt::io;
-use std::rt::io::{Decorator, Writer, Seek};
-use std::rt::io::mem::MemWriter;
+use std::io;
+use std::io::{Decorator, Writer, Seek};
+use std::io::mem::MemWriter;
 use std::str;
 use std::fmt;
 
index 09c0951b9e3c5b44aada56b1d8ef217da969d3a3..97d46cd3a0b1756ac143816b702f1378eb12cdb7 100644 (file)
@@ -38,7 +38,7 @@
 use std::at_vec;
 use std::libc;
 use std::cast;
-use std::rt::io::Seek;
+use std::io::Seek;
 
 use extra::ebml::reader;
 use extra::ebml;
@@ -1344,8 +1344,8 @@ fn mk_ctxt() -> @fake_ext_ctxt {
 
 #[cfg(test)]
 fn roundtrip(in_item: Option<@ast::item>) {
-    use std::rt::io::Decorator;
-    use std::rt::io::mem::MemWriter;
+    use std::io::Decorator;
+    use std::io::mem::MemWriter;
 
     let in_item = in_item.unwrap();
     let wr = @mut MemWriter::new();
index 299aa65897e6d48770c734456221dd901a9380fd..6b46da06211271012d9f53804087ead05e233169 100644 (file)
@@ -18,7 +18,7 @@
 
 
 use std::cast;
-use std::rt::io;
+use std::io;
 use std::uint;
 use std::vec;
 use std::hashmap::HashMap;
index a370da2893a50d4179775257fc34facf2c91f30b..05c154c5c8d53bb454a944b905615a99f0dc26c3 100644 (file)
 
 use std::cast::transmute;
 use std::hashmap::HashMap;
-use std::rt::io;
+use std::io;
 use std::str;
 use std::to_str;
 use std::uint;
index 4c64feee384397ed5f1ef198e41aa8c13b99343d..ee2aaee240ec8370761adcea226792caefc4e25b 100644 (file)
@@ -17,7 +17,7 @@
 
 use std::fmt;
 use std::local_data;
-use std::rt::io;
+use std::io;
 
 use syntax::ast;
 use syntax::ast_util;
index 5f3ffd185e7300e6e4e01466de3a51e545d1da1b..e4081df5c3c19217087902b6c0092631690a3377 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::fmt;
-use std::rt::io;
+use std::io;
 
 #[deriving(Clone)]
 pub struct Layout {
index cb9ced6b19d5b68269165b00dcaac0d8c10f9163..c07befea18feb2d1a2e6326fa78bf876559b2b9a 100644 (file)
@@ -24,7 +24,7 @@
 
 use std::fmt;
 use std::libc;
-use std::rt::io;
+use std::io;
 use std::vec;
 
 /// A unit struct which has the `fmt::Default` trait implemented. When
index 4b6092abb48e01f763d13736e32d85bcd0e9b04f..1b514f10af0497242599b92f141cbcea9989346e 100644 (file)
 use std::fmt;
 use std::hashmap::{HashMap, HashSet};
 use std::local_data;
-use std::rt::io::buffered::BufferedWriter;
-use std::rt::io;
-use std::rt::io::fs;
-use std::rt::io::File;
+use std::io::buffered::BufferedWriter;
+use std::io;
+use std::io::fs;
+use std::io::File;
 use std::os;
 use std::str;
 use std::task;
index 96624ec5b6c2be7f58579c536b0ee1c806566980..12a79aa545e80e3063adce8ccde8f0140f182cee 100644 (file)
 
 use std::cell::Cell;
 use std::local_data;
-use std::rt::io;
-use std::rt::io::File;
-use std::rt::io::mem::MemWriter;
-use std::rt::io::Decorator;
+use std::io;
+use std::io::File;
+use std::io::mem::MemWriter;
+use std::io::Decorator;
 use std::str;
 use extra::getopts;
 use extra::getopts::groups;
index 6831b6ec31275bd7c613c80c0224b9373d449080..02817fd91e525ef3949a63fcf43ed1b0b75df03e 100644 (file)
 
 // Useful conditions
 
-pub use std::path::Path;
 pub use package_id::PkgId;
-pub use std::rt::io::FileStat;
-pub use std::rt::io::process::ProcessExit;
+pub use std::io::FileStat;
+pub use std::io::process::ProcessExit;
+pub use std::path::Path;
 
 condition! {
     pub bad_path: (Path, ~str) -> Path;
index 576d5abe8bdade3960f4d61665fe17d11cbce01c..23fa1bdebd55c6e10736e68886a42290de16267a 100644 (file)
@@ -13,8 +13,8 @@
 use rustc::metadata::filesearch::rust_path;
 use path_util::*;
 use std::os;
-use std::rt::io;
-use std::rt::io::fs;
+use std::io;
+use std::io::fs;
 
 pub fn list_installed_packages(f: &fn(&PkgId) -> bool) -> bool  {
     let workspaces = rust_path();
index 94978b4a7e12fc82e0c6f179a7c9d8bd13736af3..5e9d06f533bb30268787f1c626bab0860f04325a 100644 (file)
 extern mod syntax;
 
 use std::{os, result, run, str, task};
-use std::rt::io::process;
+use std::io::process;
 use std::hashmap::HashSet;
-use std::rt::io;
-use std::rt::io::fs;
+use std::io;
+use std::io::fs;
 pub use std::path::Path;
 
 use extra::workcache;
index 79c8ff794ab5613475cbde76a56c7e3ad92b41c7..ae9e0e62661f88bb812271fb96f529b796757cc6 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use extra::term;
-use std::rt::io;
+use std::io;
 
 pub fn note(msg: &str) {
     pretty_message(msg, "note: ", term::color::GREEN,
index 3023f3ed60c5cd193f5aebd1b79872c050a96bf1..f27ca9e0a18180af8b14abb9158a8d6a50738438 100644 (file)
@@ -12,8 +12,8 @@
 
 use target::*;
 use package_id::PkgId;
-use std::rt::io;
-use std::rt::io::fs;
+use std::io;
+use std::io::fs;
 use std::os;
 use context::*;
 use crate::Crate;
index 56cf073cbdf63800e173f49e4f156a9c5cb672e8..bce41e5a49fe0560fd04103a87402cf574a79b75 100644 (file)
@@ -19,8 +19,8 @@
 use std::libc;
 use std::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
 use std::os;
-use std::rt::io;
-use std::rt::io::fs;
+use std::io;
+use std::io::fs;
 use messages::*;
 
 pub fn default_workspace() -> Path {
index 6f484a7be5da241f833a288557717305f16c76a0..702a849e4addd027ede7c93a1634186a5e24c3be 100644 (file)
@@ -12,7 +12,7 @@
 
 use std::{run, str};
 use std::run::{ProcessOutput, ProcessOptions, Process};
-use std::rt::io::fs;
+use std::io::fs;
 use extra::tempfile::TempDir;
 use version::*;
 use path_util::chmod_read_only;
index 99910242582c7a9fffa6d60dfa9c9412029c9b5a..02d2f9095090ab0b8c7815b2fe5f4db9b68cb84e 100644 (file)
 
 use context::{BuildContext, Context, RustcFlags};
 use std::{os, run, str, task};
-use std::rt::io;
-use std::rt::io::fs;
-use std::rt::io::File;
-use std::rt::io::process;
-use std::rt::io::process::ProcessExit;
+use std::io;
+use std::io::fs;
+use std::io::File;
+use std::io::process;
+use std::io::process::ProcessExit;
 use extra::arc::Arc;
 use extra::arc::RWArc;
 use extra::tempfile::TempDir;
index 1c3bf897bec1d437a76641fd8deb353c3cb88a4c..4a107de55a59f590ef043807bd4a0b5791cc4797 100644 (file)
@@ -12,7 +12,7 @@
 extern mod rustc;
 
 use std::os;
-use std::rt::io::File;
+use std::io::File;
 use rustpkg::api;
 use rustpkg::version::NoVersion;
 
index ec7771c2ab5e470f1d6784ca6901cbf08387d36e..df94e166dc211de2f4d8605f66731574775640dc 100644 (file)
@@ -10,8 +10,8 @@
 
 use std::libc;
 use std::os;
-use std::rt::io;
-use std::rt::io::fs;
+use std::io;
+use std::io::fs;
 use extra::workcache;
 use rustc::driver::{driver, session};
 use extra::getopts::groups::getopts;
index d8b35f2c0332a424e2764b48c98f3022a0862c14..42f0aec6b74379e63e299a199ecd3e2915af4cba 100644 (file)
@@ -8,8 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::rt::io;
-use std::rt::io::File;
+use std::io;
+use std::io::File;
 use extra::workcache;
 use sha1::{Digest, Sha1};
 
index 2808915907b2717d41f82cbf37cabda0e2c93e7d..49782c62838f8a43c2b4c363bb65d5f3d238da97 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use ai = std::rt::io::net::addrinfo;
+use ai = std::io::net::addrinfo;
 use std::libc::c_int;
 use std::ptr::null;
 use std::rt::BlockedTask;
@@ -186,7 +186,7 @@ pub fn accum_addrinfo(addr: &Addrinfo) -> ~[ai::Info] {
 
 #[cfg(test)]
 mod test {
-    use std::rt::io::net::ip::{SocketAddr, Ipv4Addr};
+    use std::io::net::ip::{SocketAddr, Ipv4Addr};
     use super::*;
     use super::super::local_loop;
 
index 67fa424af1ae444859d1697e44dff3e95b6ed699..984b9ee53c2102fa2fdc0cdc1471a00fc68aed1d 100644 (file)
@@ -15,8 +15,8 @@
 use std::libc::{c_int, c_char, c_void, size_t};
 use std::libc;
 use std::rt::BlockedTask;
-use std::rt::io::{FileStat, IoError};
-use std::rt::io;
+use std::io::{FileStat, IoError};
+use std::io;
 use std::rt::local::Local;
 use std::rt::rtio;
 use std::rt::sched::{Scheduler, SchedHandle};
@@ -450,7 +450,7 @@ fn truncate(&mut self, offset: i64) -> Result<(), IoError> {
 mod test {
     use std::libc::c_int;
     use std::libc::{O_CREAT, O_RDWR, O_RDONLY, S_IWUSR, S_IRUSR};
-    use std::rt::io;
+    use std::io;
     use std::str;
     use std::vec;
     use super::*;
index 599cd01c46096b276e5dbb2068b7ce5322b4ad3e..e8ce8113033a9d8a4753ab84d3cd9f0fc33f69cc 100644 (file)
@@ -61,7 +61,7 @@
 use std::unstable::finally::Finally;
 use std::vec;
 
-use std::rt::io::IoError;
+use std::io::IoError;
 
 pub use self::async::AsyncWatcher;
 pub use self::file::{FsRequest, FileWatcher};
@@ -327,7 +327,7 @@ pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
     unsafe {
         // Importing error constants
         use uvll::*;
-        use std::rt::io::*;
+        use std::io::*;
 
         // uv error descriptions are static
         let c_desc = uvll::uv_strerror(*uverr);
index 90b8263da79fd326614f251e6e4af11b5253bd8c..01f2bfd648cd587250755df246e9d6160bd905fe 100644 (file)
@@ -33,8 +33,8 @@ macro_rules! get_handle_to_current_scheduler(
 )
 
 pub fn dumb_println(args: &fmt::Arguments) {
-    use std::rt::io::native::stdio::stderr;
-    use std::rt::io::Writer;
+    use std::io::native::stdio::stderr;
+    use std::io::Writer;
 
     let mut out = stderr();
     fmt::writeln(&mut out as &mut Writer, args);
index 8e649bbc17abfb61188870a76be236e35c2c3bba..dc6fbcec3f2a466d2a1a5d2df3419b38b75e7ee9 100644 (file)
@@ -13,8 +13,8 @@
 use std::libc::{size_t, ssize_t, c_int, c_void, c_uint, c_char};
 use std::ptr;
 use std::rt::BlockedTask;
-use std::rt::io::IoError;
-use std::rt::io::net::ip::{Ipv4Addr, Ipv6Addr, SocketAddr, IpAddr};
+use std::io::IoError;
+use std::io::net::ip::{Ipv4Addr, Ipv6Addr, SocketAddr, IpAddr};
 use std::rt::local::Local;
 use std::rt::rtio;
 use std::rt::sched::{Scheduler, SchedHandle};
index 1b0f352dc4df1dc1b0710574564a5652defe6c95..0c1e53082f7a484fc8dbf286315815847d912de0 100644 (file)
@@ -11,7 +11,7 @@
 use std::c_str::CString;
 use std::libc;
 use std::rt::BlockedTask;
-use std::rt::io::IoError;
+use std::io::IoError;
 use std::rt::local::Local;
 use std::rt::rtio::{RtioPipe, RtioUnixListener, RtioUnixAcceptor};
 use std::rt::sched::{Scheduler, SchedHandle};
index e49930c1fc93dbf3250f346545679d5d9e609781..c537ee582cb8d950b67cd7c1ab1235c50a2f2dfe 100644 (file)
@@ -12,8 +12,8 @@
 use std::libc;
 use std::ptr;
 use std::rt::BlockedTask;
-use std::rt::io::IoError;
-use std::rt::io::process::*;
+use std::io::IoError;
+use std::io::process::*;
 use std::rt::local::Local;
 use std::rt::rtio::RtioProcess;
 use std::rt::sched::{Scheduler, SchedHandle};
index da2e1d8837c458e21acda539cd62c79a272d5764..10c2bc3be0569c44f35a42db79fd000fe152f37e 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::libc::c_int;
-use std::rt::io::signal::Signum;
+use std::io::signal::Signum;
 use std::rt::sched::{SchedHandle, Scheduler};
 use std::comm::{SharedChan, SendDeferred};
 use std::rt::local::Local;
@@ -78,7 +78,7 @@ mod test {
     use super::*;
     use std::cell::Cell;
     use super::super::local_loop;
-    use std::rt::io::signal;
+    use std::io::signal;
     use std::comm::{SharedChan, stream};
 
     #[test]
index d3f001f39312f055bb4444f6f8d5b76b91065b91..c7c09f3480e20b943d428ac814785b9fc74d1b48 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use std::libc;
-use std::rt::io::IoError;
+use std::io::IoError;
 use std::rt::local::Local;
 use std::rt::rtio::RtioTTY;
 use std::rt::sched::{Scheduler, SchedHandle};
index 75ec5f26b336ce8ffc972d12260bfae950c932cd..6f9dbc8ec9095ad6b1db3e7e1629ccf682ecacb1 100644 (file)
 use std::libc::c_int;
 use std::libc;
 use std::path::Path;
-use std::rt::io::IoError;
-use std::rt::io::net::ip::SocketAddr;
-use std::rt::io::process::ProcessConfig;
-use std::rt::io;
+use std::io::IoError;
+use std::io::net::ip::SocketAddr;
+use std::io::process::ProcessConfig;
+use std::io;
 use std::rt::local::Local;
 use std::rt::rtio::*;
 use std::rt::sched::{Scheduler, SchedHandle};
 use std::rt::task::Task;
 use std::libc::{O_CREAT, O_APPEND, O_TRUNC, O_RDWR, O_RDONLY, O_WRONLY,
                 S_IRUSR, S_IWUSR};
-use std::rt::io::{FileMode, FileAccess, Open, Append, Truncate, Read, Write,
+use std::io::{FileMode, FileAccess, Open, Append, Truncate, Read, Write,
                   ReadWrite, FileStat};
-use std::rt::io::signal::Signum;
+use std::io::signal::Signum;
 use std::util;
-use ai = std::rt::io::net::addrinfo;
+use ai = std::io::net::addrinfo;
 
 #[cfg(test)] use std::unstable::run_in_bare_thread;
 
index 9d5c9c1a5cd66fe9df469b2a16123e81b87ffdc7..a48b8578116dec80d7e7b82c621a21a94f8e8b61 100644 (file)
@@ -220,7 +220,7 @@ fn main() {
 
 ```rust
 format!      // described above
-write!       // first argument is a &mut rt::io::Writer, the destination
+write!       // first argument is a &mut io::Writer, the destination
 writeln!     // same as write but appends a newline
 print!       // the format string is printed to the standard output
 println!     // same as print but appends a newline
@@ -236,7 +236,7 @@ fn main() {
 actually invoking the `write` function defined in this module. Example usage is:
 
 ```rust
-use std::rt::io;
+use std::io;
 
 let mut w = io::mem::MemWriter::new();
 write!(&mut w as &mut io::Writer, "Hello {}!", "world");
@@ -462,9 +462,9 @@ fn main() {
 
 use cast;
 use char::Char;
-use rt::io::Decorator;
-use rt::io::mem::MemWriter;
-use rt::io;
+use io::Decorator;
+use io::mem::MemWriter;
+use io;
 use str;
 use repr;
 use util;
index 6f6e847f569b69fbfde27b470252ac6141fa9054..c9a85e6d25e13b93c5b9485c2002492376cc4b22 100644 (file)
@@ -29,7 +29,7 @@
 use container::Container;
 use iter::Iterator;
 use option::{Some, None};
-use rt::io::Writer;
+use io::Writer;
 use str::OwnedStr;
 use to_bytes::IterBytes;
 use vec::ImmutableVector;
diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs
new file mode 100644 (file)
index 0000000..4932f39
--- /dev/null
@@ -0,0 +1,473 @@
+// 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.
+
+//! Buffering wrappers for I/O traits
+//!
+//! It can be excessively inefficient to work directly with a `Reader` or
+//! `Writer`. Every call to `read` or `write` on `TcpStream` results in a
+//! system call, for example. This module provides structures that wrap
+//! `Readers`, `Writers`, and `Streams` and buffer input and output to them.
+//!
+//! # Examples
+//!
+//! ```
+//! let tcp_stream = TcpStream::connect(addr);
+//! let reader = BufferedReader::new(tcp_stream);
+//!
+//! let mut buf: ~[u8] = vec::from_elem(100, 0u8);
+//! match reader.read(buf.as_slice()) {
+//!     Some(nread) => println!("Read {} bytes", nread),
+//!     None => println!("At the end of the stream!")
+//! }
+//! ```
+//!
+//! ```
+//! let tcp_stream = TcpStream::connect(addr);
+//! let writer = BufferedWriter::new(tcp_stream);
+//!
+//! writer.write("hello, world".as_bytes());
+//! writer.flush();
+//! ```
+//!
+//! ```
+//! let tcp_stream = TcpStream::connect(addr);
+//! let stream = BufferedStream::new(tcp_stream);
+//!
+//! stream.write("hello, world".as_bytes());
+//! stream.flush();
+//!
+//! let mut buf = vec::from_elem(100, 0u8);
+//! match stream.read(buf.as_slice()) {
+//!     Some(nread) => println!("Read {} bytes", nread),
+//!     None => println!("At the end of the stream!")
+//! }
+//! ```
+//!
+
+use prelude::*;
+
+use num;
+use vec;
+use str;
+use super::{Reader, Writer, Stream, Decorator};
+
+// libuv recommends 64k buffers to maximize throughput
+// https://groups.google.com/forum/#!topic/libuv/oQO1HJAIDdA
+static DEFAULT_CAPACITY: uint = 64 * 1024;
+
+/// Wraps a Reader and buffers input from it
+pub struct BufferedReader<R> {
+    priv inner: R,
+    priv buf: ~[u8],
+    priv pos: uint,
+    priv cap: uint
+}
+
+impl<R: Reader> BufferedReader<R> {
+    /// Creates a new `BufferedReader` with with the specified buffer capacity
+    pub fn with_capacity(cap: uint, inner: R) -> BufferedReader<R> {
+        // It's *much* faster to create an uninitialized buffer than it is to
+        // fill everything in with 0. This buffer is entirely an implementation
+        // detail and is never exposed, so we're safe to not initialize
+        // everything up-front. This allows creation of BufferedReader instances
+        // to be very cheap (large mallocs are not nearly as expensive as large
+        // callocs).
+        let mut buf = vec::with_capacity(cap);
+        unsafe { vec::raw::set_len(&mut buf, cap); }
+        BufferedReader {
+            inner: inner,
+            buf: buf,
+            pos: 0,
+            cap: 0
+        }
+    }
+
+    /// Creates a new `BufferedReader` with a default buffer capacity
+    pub fn new(inner: R) -> BufferedReader<R> {
+        BufferedReader::with_capacity(DEFAULT_CAPACITY, inner)
+    }
+
+    /// Reads the next line of input, interpreted as a sequence of utf-8
+    /// encoded unicode codepoints. If a newline is encountered, then the
+    /// newline is contained in the returned string.
+    pub fn read_line(&mut self) -> Option<~str> {
+        self.read_until('\n' as u8).map(str::from_utf8_owned)
+    }
+
+    /// Reads a sequence of bytes leading up to a specified delimeter. Once the
+    /// specified byte is encountered, reading ceases and the bytes up to and
+    /// including the delimiter are returned.
+    pub fn read_until(&mut self, byte: u8) -> Option<~[u8]> {
+        let mut res = ~[];
+        let mut used;
+        loop {
+            {
+                let available = self.fill_buffer();
+                match available.iter().position(|&b| b == byte) {
+                    Some(i) => {
+                        res.push_all(available.slice_to(i + 1));
+                        used = i + 1;
+                        break
+                    }
+                    None => {
+                        res.push_all(available);
+                        used = available.len();
+                    }
+                }
+            }
+            if used == 0 {
+                break
+            }
+            self.pos += used;
+        }
+        self.pos += used;
+        return if res.len() == 0 {None} else {Some(res)};
+    }
+
+    fn fill_buffer<'a>(&'a mut self) -> &'a [u8] {
+        if self.pos == self.cap {
+            match self.inner.read(self.buf) {
+                Some(cap) => {
+                    self.pos = 0;
+                    self.cap = cap;
+                }
+                None => {}
+            }
+        }
+        return self.buf.slice(self.pos, self.cap);
+    }
+}
+
+impl<R: Reader> Reader for BufferedReader<R> {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        let nread = {
+            let available = self.fill_buffer();
+            if available.len() == 0 {
+                return None;
+            }
+            let nread = num::min(available.len(), buf.len());
+            vec::bytes::copy_memory(buf, available, nread);
+            nread
+        };
+        self.pos += nread;
+        Some(nread)
+    }
+
+    fn eof(&mut self) -> bool {
+        self.pos == self.cap && self.inner.eof()
+    }
+}
+
+impl<R: Reader> Decorator<R> for BufferedReader<R> {
+    fn inner(self) -> R {
+        self.inner
+    }
+
+    fn inner_ref<'a>(&'a self) -> &'a R {
+        &self.inner
+    }
+
+    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut R {
+        &mut self.inner
+    }
+}
+
+/// Wraps a Writer and buffers output to it
+///
+/// Note that `BufferedWriter` will NOT flush its buffer when dropped.
+pub struct BufferedWriter<W> {
+    priv inner: W,
+    priv buf: ~[u8],
+    priv pos: uint
+}
+
+impl<W: Writer> BufferedWriter<W> {
+    /// Creates a new `BufferedWriter` with with the specified buffer capacity
+    pub fn with_capacity(cap: uint, inner: W) -> BufferedWriter<W> {
+        // See comments in BufferedReader for why this uses unsafe code.
+        let mut buf = vec::with_capacity(cap);
+        unsafe { vec::raw::set_len(&mut buf, cap); }
+        BufferedWriter {
+            inner: inner,
+            buf: buf,
+            pos: 0
+        }
+    }
+
+    /// Creates a new `BufferedWriter` with a default buffer capacity
+    pub fn new(inner: W) -> BufferedWriter<W> {
+        BufferedWriter::with_capacity(DEFAULT_CAPACITY, inner)
+    }
+}
+
+impl<W: Writer> Writer for BufferedWriter<W> {
+    fn write(&mut self, buf: &[u8]) {
+        if self.pos + buf.len() > self.buf.len() {
+            self.flush();
+        }
+
+        if buf.len() > self.buf.len() {
+            self.inner.write(buf);
+        } else {
+            let dst = self.buf.mut_slice_from(self.pos);
+            vec::bytes::copy_memory(dst, buf, buf.len());
+            self.pos += buf.len();
+        }
+    }
+
+    fn flush(&mut self) {
+        if self.pos != 0 {
+            self.inner.write(self.buf.slice_to(self.pos));
+            self.pos = 0;
+        }
+        self.inner.flush();
+    }
+}
+
+impl<W: Writer> Decorator<W> for BufferedWriter<W> {
+    fn inner(self) -> W { self.inner }
+    fn inner_ref<'a>(&'a self) -> &'a W { &self.inner }
+    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut W { &mut self.inner }
+}
+
+/// Wraps a Writer and buffers output to it, flushing whenever a newline (0xa,
+/// '\n') is detected.
+///
+/// Note that this structure does NOT flush the output when dropped.
+pub struct LineBufferedWriter<W> {
+    priv inner: BufferedWriter<W>,
+}
+
+impl<W: Writer> LineBufferedWriter<W> {
+    /// Creates a new `LineBufferedWriter`
+    pub fn new(inner: W) -> LineBufferedWriter<W> {
+        // Lines typically aren't that long, don't use a giant buffer
+        LineBufferedWriter {
+            inner: BufferedWriter::with_capacity(1024, inner)
+        }
+    }
+}
+
+impl<W: Writer> Writer for LineBufferedWriter<W> {
+    fn write(&mut self, buf: &[u8]) {
+        match buf.iter().position(|&b| b == '\n' as u8) {
+            Some(i) => {
+                self.inner.write(buf.slice_to(i + 1));
+                self.inner.flush();
+                self.inner.write(buf.slice_from(i + 1));
+            }
+            None => self.inner.write(buf),
+        }
+    }
+
+    fn flush(&mut self) { self.inner.flush() }
+}
+
+impl<W: Writer> Decorator<W> for LineBufferedWriter<W> {
+    fn inner(self) -> W { self.inner.inner() }
+    fn inner_ref<'a>(&'a self) -> &'a W { self.inner.inner_ref() }
+    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut W { self.inner.inner_mut_ref() }
+}
+
+struct InternalBufferedWriter<W>(BufferedWriter<W>);
+
+impl<W: Reader> Reader for InternalBufferedWriter<W> {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        self.inner.read(buf)
+    }
+
+    fn eof(&mut self) -> bool {
+        self.inner.eof()
+    }
+}
+
+/// Wraps a Stream and buffers input and output to and from it
+///
+/// Note that `BufferedStream` will NOT flush its output buffer when dropped.
+pub struct BufferedStream<S> {
+    priv inner: BufferedReader<InternalBufferedWriter<S>>
+}
+
+impl<S: Stream> BufferedStream<S> {
+    pub fn with_capacities(reader_cap: uint, writer_cap: uint, inner: S)
+                           -> BufferedStream<S> {
+        let writer = BufferedWriter::with_capacity(writer_cap, inner);
+        let internal_writer = InternalBufferedWriter(writer);
+        let reader = BufferedReader::with_capacity(reader_cap,
+                                                   internal_writer);
+        BufferedStream { inner: reader }
+    }
+
+    pub fn new(inner: S) -> BufferedStream<S> {
+        BufferedStream::with_capacities(DEFAULT_CAPACITY, DEFAULT_CAPACITY,
+                                        inner)
+    }
+}
+
+impl<S: Stream> Reader for BufferedStream<S> {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        self.inner.read(buf)
+    }
+
+    fn eof(&mut self) -> bool {
+        self.inner.eof()
+    }
+}
+
+impl<S: Stream> Writer for BufferedStream<S> {
+    fn write(&mut self, buf: &[u8]) {
+        self.inner.inner.write(buf)
+    }
+
+    fn flush(&mut self) {
+        self.inner.inner.flush()
+    }
+}
+
+impl<S: Stream> Decorator<S> for BufferedStream<S> {
+    fn inner(self) -> S {
+        self.inner.inner.inner()
+    }
+
+    fn inner_ref<'a>(&'a self) -> &'a S {
+        self.inner.inner.inner_ref()
+    }
+
+    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut S {
+        self.inner.inner.inner_mut_ref()
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::*;
+    use super::*;
+    use io;
+    use super::super::mem::{MemReader, MemWriter};
+
+    #[test]
+    fn test_buffered_reader() {
+        let inner = MemReader::new(~[0, 1, 2, 3, 4]);
+        let mut reader = BufferedReader::with_capacity(2, inner);
+
+        let mut buf = [0, 0, 0];
+        let nread = reader.read(buf);
+        assert_eq!(Some(2), nread);
+        assert_eq!([0, 1, 0], buf);
+        assert!(!reader.eof());
+
+        let mut buf = [0];
+        let nread = reader.read(buf);
+        assert_eq!(Some(1), nread);
+        assert_eq!([2], buf);
+        assert!(!reader.eof());
+
+        let mut buf = [0, 0, 0];
+        let nread = reader.read(buf);
+        assert_eq!(Some(1), nread);
+        assert_eq!([3, 0, 0], buf);
+        assert!(!reader.eof());
+
+        let nread = reader.read(buf);
+        assert_eq!(Some(1), nread);
+        assert_eq!([4, 0, 0], buf);
+        assert!(reader.eof());
+
+        assert_eq!(None, reader.read(buf));
+    }
+
+    #[test]
+    fn test_buffered_writer() {
+        let inner = MemWriter::new();
+        let mut writer = BufferedWriter::with_capacity(2, inner);
+
+        writer.write([0, 1]);
+        assert_eq!([], writer.inner_ref().inner_ref().as_slice());
+
+        writer.write([2]);
+        assert_eq!([0, 1], writer.inner_ref().inner_ref().as_slice());
+
+        writer.write([3]);
+        assert_eq!([0, 1], writer.inner_ref().inner_ref().as_slice());
+
+        writer.flush();
+        assert_eq!([0, 1, 2, 3], writer.inner_ref().inner_ref().as_slice());
+
+        writer.write([4]);
+        writer.write([5]);
+        assert_eq!([0, 1, 2, 3], writer.inner_ref().inner_ref().as_slice());
+
+        writer.write([6]);
+        assert_eq!([0, 1, 2, 3, 4, 5],
+                   writer.inner_ref().inner_ref().as_slice());
+
+        writer.write([7, 8]);
+        assert_eq!([0, 1, 2, 3, 4, 5, 6],
+                   writer.inner_ref().inner_ref().as_slice());
+
+        writer.write([9, 10, 11]);
+        assert_eq!([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
+                   writer.inner_ref().inner_ref().as_slice());
+
+        writer.flush();
+        assert_eq!([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
+                   writer.inner_ref().inner_ref().as_slice());
+    }
+
+    // This is just here to make sure that we don't infinite loop in the
+    // newtype struct autoderef weirdness
+    #[test]
+    fn test_buffered_stream() {
+        use rt;
+        struct S;
+
+        impl io::Writer for S {
+            fn write(&mut self, _: &[u8]) {}
+        }
+
+        impl io::Reader for S {
+            fn read(&mut self, _: &mut [u8]) -> Option<uint> { None }
+            fn eof(&mut self) -> bool { true }
+        }
+
+        let mut stream = BufferedStream::new(S);
+        let mut buf = [];
+        stream.read(buf);
+        stream.eof();
+        stream.write(buf);
+        stream.flush();
+    }
+
+    #[test]
+    fn test_read_until() {
+        let inner = MemReader::new(~[0, 1, 2, 1, 0]);
+        let mut reader = BufferedReader::with_capacity(2, inner);
+        assert_eq!(reader.read_until(0), Some(~[0]));
+        assert_eq!(reader.read_until(2), Some(~[1, 2]));
+        assert_eq!(reader.read_until(1), Some(~[1]));
+        assert_eq!(reader.read_until(8), Some(~[0]));
+        assert_eq!(reader.read_until(9), None);
+    }
+
+    #[test]
+    fn test_line_buffer() {
+        let mut writer = LineBufferedWriter::new(MemWriter::new());
+        writer.write([0]);
+        assert_eq!(*writer.inner_ref().inner_ref(), ~[]);
+        writer.write([1]);
+        assert_eq!(*writer.inner_ref().inner_ref(), ~[]);
+        writer.flush();
+        assert_eq!(*writer.inner_ref().inner_ref(), ~[0, 1]);
+        writer.write([0, '\n' as u8, 1]);
+        assert_eq!(*writer.inner_ref().inner_ref(), ~[0, 1, 0, '\n' as u8]);
+        writer.flush();
+        assert_eq!(*writer.inner_ref().inner_ref(), ~[0, 1, 0, '\n' as u8, 1]);
+    }
+}
diff --git a/src/libstd/io/comm_adapters.rs b/src/libstd/io/comm_adapters.rs
new file mode 100644 (file)
index 0000000..98dbec2
--- /dev/null
@@ -0,0 +1,57 @@
+// 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.
+
+use option::Option;
+use comm::{GenericPort, GenericChan};
+use super::{Reader, Writer};
+
+struct PortReader<P>;
+
+impl<P: GenericPort<~[u8]>> PortReader<P> {
+    pub fn new(_port: P) -> PortReader<P> { fail!() }
+}
+
+impl<P: GenericPort<~[u8]>> Reader for PortReader<P> {
+    fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail!() }
+
+    fn eof(&mut self) -> bool { fail!() }
+}
+
+struct ChanWriter<C>;
+
+impl<C: GenericChan<~[u8]>> ChanWriter<C> {
+    pub fn new(_chan: C) -> ChanWriter<C> { fail!() }
+}
+
+impl<C: GenericChan<~[u8]>> Writer for ChanWriter<C> {
+    fn write(&mut self, _buf: &[u8]) { fail!() }
+}
+
+struct ReaderPort<R>;
+
+impl<R: Reader> ReaderPort<R> {
+    pub fn new(_reader: R) -> ReaderPort<R> { fail!() }
+}
+
+impl<R: Reader> GenericPort<~[u8]> for ReaderPort<R> {
+    fn recv(&self) -> ~[u8] { fail!() }
+
+    fn try_recv(&self) -> Option<~[u8]> { fail!() }
+}
+
+struct WriterChan<W>;
+
+impl<W: Writer> WriterChan<W> {
+    pub fn new(_writer: W) -> WriterChan<W> { fail!() }
+}
+
+impl<W: Writer> GenericChan<~[u8]> for WriterChan<W> {
+    fn send(&self, _x: ~[u8]) { fail!() }
+}
diff --git a/src/libstd/io/extensions.rs b/src/libstd/io/extensions.rs
new file mode 100644 (file)
index 0000000..ebda261
--- /dev/null
@@ -0,0 +1,491 @@
+// 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.
+
+//! Utility mixins that apply to all Readers and Writers
+
+// XXX: Not sure how this should be structured
+// XXX: Iteration should probably be considered separately
+
+use iter::Iterator;
+use option::Option;
+use io::{Reader, Decorator};
+
+/// An iterator that reads a single byte on each iteration,
+/// until `.read_byte()` returns `None`.
+///
+/// # Notes about the Iteration Protocol
+///
+/// The `ByteIterator` may yield `None` and thus terminate
+/// an iteration, but continue to yield elements if iteration
+/// is attempted again.
+///
+/// # Failure
+///
+/// Raises the same conditions as the `read` method, for
+/// each call to its `.next()` method.
+/// Yields `None` if the condition is handled.
+pub struct ByteIterator<T> {
+    priv reader: T,
+}
+
+impl<R: Reader> ByteIterator<R> {
+    pub fn new(r: R) -> ByteIterator<R> {
+        ByteIterator { reader: r }
+    }
+}
+
+impl<R> Decorator<R> for ByteIterator<R> {
+    fn inner(self) -> R { self.reader }
+    fn inner_ref<'a>(&'a self) -> &'a R { &self.reader }
+    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut R { &mut self.reader }
+}
+
+impl<'self, R: Reader> Iterator<u8> for ByteIterator<R> {
+    #[inline]
+    fn next(&mut self) -> Option<u8> {
+        self.reader.read_byte()
+    }
+}
+
+pub fn u64_to_le_bytes<T>(n: u64, size: uint,
+                          f: &fn(v: &[u8]) -> T) -> T {
+    assert!(size <= 8u);
+    match size {
+      1u => f(&[n as u8]),
+      2u => f(&[n as u8,
+              (n >> 8) as u8]),
+      4u => f(&[n as u8,
+              (n >> 8) as u8,
+              (n >> 16) as u8,
+              (n >> 24) as u8]),
+      8u => f(&[n as u8,
+              (n >> 8) as u8,
+              (n >> 16) as u8,
+              (n >> 24) as u8,
+              (n >> 32) as u8,
+              (n >> 40) as u8,
+              (n >> 48) as u8,
+              (n >> 56) as u8]),
+      _ => {
+
+        let mut bytes: ~[u8] = ~[];
+        let mut i = size;
+        let mut n = n;
+        while i > 0u {
+            bytes.push((n & 255_u64) as u8);
+            n >>= 8_u64;
+            i -= 1u;
+        }
+        f(bytes)
+      }
+    }
+}
+
+pub fn u64_to_be_bytes<T>(n: u64, size: uint,
+                           f: &fn(v: &[u8]) -> T) -> T {
+    assert!(size <= 8u);
+    match size {
+      1u => f(&[n as u8]),
+      2u => f(&[(n >> 8) as u8,
+              n as u8]),
+      4u => f(&[(n >> 24) as u8,
+              (n >> 16) as u8,
+              (n >> 8) as u8,
+              n as u8]),
+      8u => f(&[(n >> 56) as u8,
+              (n >> 48) as u8,
+              (n >> 40) as u8,
+              (n >> 32) as u8,
+              (n >> 24) as u8,
+              (n >> 16) as u8,
+              (n >> 8) as u8,
+              n as u8]),
+      _ => {
+        let mut bytes: ~[u8] = ~[];
+        let mut i = size;
+        while i > 0u {
+            let shift = ((i - 1u) * 8u) as u64;
+            bytes.push((n >> shift) as u8);
+            i -= 1u;
+        }
+        f(bytes)
+      }
+    }
+}
+
+pub fn u64_from_be_bytes(data: &[u8],
+                         start: uint,
+                         size: uint)
+                      -> u64 {
+    let mut sz = size;
+    assert!((sz <= 8u));
+    let mut val = 0_u64;
+    let mut pos = start;
+    while sz > 0u {
+        sz -= 1u;
+        val += (data[pos] as u64) << ((sz * 8u) as u64);
+        pos += 1u;
+    }
+    return val;
+}
+
+#[cfg(test)]
+mod test {
+    use option::{None, Option, Some};
+    use io::mem::{MemReader, MemWriter};
+    use io::{Reader, io_error, placeholder_error};
+    use vec::ImmutableVector;
+
+    struct InitialZeroByteReader {
+        count: int,
+    }
+
+    impl Reader for InitialZeroByteReader {
+        fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+            if self.count == 0 {
+                self.count = 1;
+                Some(0)
+            } else {
+                buf[0] = 10;
+                Some(1)
+            }
+        }
+        fn eof(&mut self) -> bool {
+            false
+        }
+    }
+
+    struct EofReader;
+
+    impl Reader for EofReader {
+        fn read(&mut self, _: &mut [u8]) -> Option<uint> {
+            None
+        }
+        fn eof(&mut self) -> bool {
+            false
+        }
+    }
+
+    struct ErroringReader;
+
+    impl Reader for ErroringReader {
+        fn read(&mut self, _: &mut [u8]) -> Option<uint> {
+            io_error::cond.raise(placeholder_error());
+            None
+        }
+        fn eof(&mut self) -> bool {
+            false
+        }
+    }
+
+    struct PartialReader {
+        count: int,
+    }
+
+    impl Reader for PartialReader {
+        fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+            if self.count == 0 {
+                self.count = 1;
+                buf[0] = 10;
+                buf[1] = 11;
+                Some(2)
+            } else {
+                buf[0] = 12;
+                buf[1] = 13;
+                Some(2)
+            }
+        }
+        fn eof(&mut self) -> bool {
+            false
+        }
+    }
+
+    struct ErroringLaterReader {
+        count: int,
+    }
+
+    impl Reader for ErroringLaterReader {
+        fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+            if self.count == 0 {
+                self.count = 1;
+                buf[0] = 10;
+                Some(1)
+            } else {
+                io_error::cond.raise(placeholder_error());
+                None
+            }
+        }
+        fn eof(&mut self) -> bool {
+            false
+        }
+    }
+
+    struct ThreeChunkReader {
+        count: int,
+    }
+
+    impl Reader for ThreeChunkReader {
+        fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+            if self.count == 0 {
+                self.count = 1;
+                buf[0] = 10;
+                buf[1] = 11;
+                Some(2)
+            } else if self.count == 1 {
+                self.count = 2;
+                buf[0] = 12;
+                buf[1] = 13;
+                Some(2)
+            } else {
+                None
+            }
+        }
+        fn eof(&mut self) -> bool {
+            false
+        }
+    }
+
+    #[test]
+    fn read_byte() {
+        let mut reader = MemReader::new(~[10]);
+        let byte = reader.read_byte();
+        assert!(byte == Some(10));
+    }
+
+    #[test]
+    fn read_byte_0_bytes() {
+        let mut reader = InitialZeroByteReader {
+            count: 0,
+        };
+        let byte = reader.read_byte();
+        assert!(byte == Some(10));
+    }
+
+    #[test]
+    fn read_byte_eof() {
+        let mut reader = EofReader;
+        let byte = reader.read_byte();
+        assert!(byte == None);
+    }
+
+    #[test]
+    fn read_byte_error() {
+        let mut reader = ErroringReader;
+        do io_error::cond.trap(|_| {
+        }).inside {
+            let byte = reader.read_byte();
+            assert!(byte == None);
+        }
+    }
+
+    #[test]
+    fn bytes_0_bytes() {
+        let reader = InitialZeroByteReader {
+            count: 0,
+        };
+        let byte = reader.bytes().next();
+        assert!(byte == Some(10));
+    }
+
+    #[test]
+    fn bytes_eof() {
+        let reader = EofReader;
+        let byte = reader.bytes().next();
+        assert!(byte == None);
+    }
+
+    #[test]
+    fn bytes_error() {
+        let reader = ErroringReader;
+        let mut it = reader.bytes();
+        do io_error::cond.trap(|_| ()).inside {
+            let byte = it.next();
+            assert!(byte == None);
+        }
+    }
+
+    #[test]
+    fn read_bytes() {
+        let mut reader = MemReader::new(~[10, 11, 12, 13]);
+        let bytes = reader.read_bytes(4);
+        assert!(bytes == ~[10, 11, 12, 13]);
+    }
+
+    #[test]
+    fn read_bytes_partial() {
+        let mut reader = PartialReader {
+            count: 0,
+        };
+        let bytes = reader.read_bytes(4);
+        assert!(bytes == ~[10, 11, 12, 13]);
+    }
+
+    #[test]
+    fn read_bytes_eof() {
+        let mut reader = MemReader::new(~[10, 11]);
+        do io_error::cond.trap(|_| {
+        }).inside {
+            assert!(reader.read_bytes(4) == ~[10, 11]);
+        }
+    }
+
+    #[test]
+    fn push_bytes() {
+        let mut reader = MemReader::new(~[10, 11, 12, 13]);
+        let mut buf = ~[8, 9];
+        reader.push_bytes(&mut buf, 4);
+        assert!(buf == ~[8, 9, 10, 11, 12, 13]);
+    }
+
+    #[test]
+    fn push_bytes_partial() {
+        let mut reader = PartialReader {
+            count: 0,
+        };
+        let mut buf = ~[8, 9];
+        reader.push_bytes(&mut buf, 4);
+        assert!(buf == ~[8, 9, 10, 11, 12, 13]);
+    }
+
+    #[test]
+    fn push_bytes_eof() {
+        let mut reader = MemReader::new(~[10, 11]);
+        let mut buf = ~[8, 9];
+        do io_error::cond.trap(|_| {
+        }).inside {
+            reader.push_bytes(&mut buf, 4);
+            assert!(buf == ~[8, 9, 10, 11]);
+        }
+    }
+
+    #[test]
+    fn push_bytes_error() {
+        let mut reader = ErroringLaterReader {
+            count: 0,
+        };
+        let mut buf = ~[8, 9];
+        do io_error::cond.trap(|_| { } ).inside {
+            reader.push_bytes(&mut buf, 4);
+        }
+        assert!(buf == ~[8, 9, 10]);
+    }
+
+    #[test]
+    #[should_fail]
+    fn push_bytes_fail_reset_len() {
+        // push_bytes unsafely sets the vector length. This is testing that
+        // upon failure the length is reset correctly.
+        let mut reader = ErroringLaterReader {
+            count: 0,
+        };
+        let buf = @mut ~[8, 9];
+        do (|| {
+            reader.push_bytes(&mut *buf, 4);
+        }).finally {
+            // NB: Using rtassert here to trigger abort on failure since this is a should_fail test
+            // FIXME: #7049 This fails because buf is still borrowed
+            //rtassert!(*buf == ~[8, 9, 10]);
+        }
+    }
+
+    #[test]
+    fn read_to_end() {
+        let mut reader = ThreeChunkReader {
+            count: 0,
+        };
+        let buf = reader.read_to_end();
+        assert!(buf == ~[10, 11, 12, 13]);
+    }
+
+    #[test]
+    #[should_fail]
+    fn read_to_end_error() {
+        let mut reader = ThreeChunkReader {
+            count: 0,
+        };
+        let buf = reader.read_to_end();
+        assert!(buf == ~[10, 11]);
+    }
+
+    #[test]
+    fn test_read_write_le_mem() {
+        let uints = [0, 1, 2, 42, 10_123, 100_123_456, ::u64::max_value];
+
+        let mut writer = MemWriter::new();
+        for i in uints.iter() {
+            writer.write_le_u64(*i);
+        }
+
+        let mut reader = MemReader::new(writer.inner());
+        for i in uints.iter() {
+            assert!(reader.read_le_u64() == *i);
+        }
+    }
+
+
+    #[test]
+    fn test_read_write_be() {
+        let uints = [0, 1, 2, 42, 10_123, 100_123_456, ::u64::max_value];
+
+        let mut writer = MemWriter::new();
+        for i in uints.iter() {
+            writer.write_be_u64(*i);
+        }
+
+        let mut reader = MemReader::new(writer.inner());
+        for i in uints.iter() {
+            assert!(reader.read_be_u64() == *i);
+        }
+    }
+
+    #[test]
+    fn test_read_be_int_n() {
+        let ints = [::i32::min_value, -123456, -42, -5, 0, 1, ::i32::max_value];
+
+        let mut writer = MemWriter::new();
+        for i in ints.iter() {
+            writer.write_be_i32(*i);
+        }
+
+        let mut reader = MemReader::new(writer.inner());
+        for i in ints.iter() {
+            // this tests that the sign extension is working
+            // (comparing the values as i32 would not test this)
+            assert!(reader.read_be_int_n(4) == *i as i64);
+        }
+    }
+
+    #[test]
+    fn test_read_f32() {
+        //big-endian floating-point 8.1250
+        let buf = ~[0x41, 0x02, 0x00, 0x00];
+
+        let mut writer = MemWriter::new();
+        writer.write(buf);
+
+        let mut reader = MemReader::new(writer.inner());
+        let f = reader.read_be_f32();
+        assert!(f == 8.1250);
+    }
+
+    #[test]
+    fn test_read_write_f32() {
+        let f:f32 = 8.1250;
+
+        let mut writer = MemWriter::new();
+        writer.write_be_f32(f);
+        writer.write_le_f32(f);
+
+        let mut reader = MemReader::new(writer.inner());
+        assert!(reader.read_be_f32() == 8.1250);
+        assert!(reader.read_le_f32() == 8.1250);
+    }
+
+}
diff --git a/src/libstd/io/flate.rs b/src/libstd/io/flate.rs
new file mode 100644 (file)
index 0000000..8a5aa17
--- /dev/null
@@ -0,0 +1,123 @@
+// 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.
+
+//! Some various other I/O types
+
+// FIXME(#3660): should move to libextra
+
+use prelude::*;
+use super::*;
+
+/// A Writer decorator that compresses using the 'deflate' scheme
+pub struct DeflateWriter<W> {
+    priv inner_writer: W
+}
+
+impl<W: Writer> DeflateWriter<W> {
+    pub fn new(inner_writer: W) -> DeflateWriter<W> {
+        DeflateWriter {
+            inner_writer: inner_writer
+        }
+    }
+}
+
+impl<W: Writer> Writer for DeflateWriter<W> {
+    fn write(&mut self, _buf: &[u8]) { fail!() }
+
+    fn flush(&mut self) { fail!() }
+}
+
+impl<W: Writer> Decorator<W> for DeflateWriter<W> {
+    fn inner(self) -> W {
+        match self {
+            DeflateWriter { inner_writer: w } => w
+        }
+    }
+
+    fn inner_ref<'a>(&'a self) -> &'a W {
+        match *self {
+            DeflateWriter { inner_writer: ref w } => w
+        }
+    }
+
+    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut W {
+        match *self {
+            DeflateWriter { inner_writer: ref mut w } => w
+        }
+    }
+}
+
+/// A Reader decorator that decompresses using the 'deflate' scheme
+pub struct InflateReader<R> {
+    priv inner_reader: R
+}
+
+impl<R: Reader> InflateReader<R> {
+    pub fn new(inner_reader: R) -> InflateReader<R> {
+        InflateReader {
+            inner_reader: inner_reader
+        }
+    }
+}
+
+impl<R: Reader> Reader for InflateReader<R> {
+    fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail!() }
+
+    fn eof(&mut self) -> bool { fail!() }
+}
+
+impl<R: Reader> Decorator<R> for InflateReader<R> {
+    fn inner(self) -> R {
+        match self {
+            InflateReader { inner_reader: r } => r
+        }
+    }
+
+    fn inner_ref<'a>(&'a self) -> &'a R {
+        match *self {
+            InflateReader { inner_reader: ref r } => r
+        }
+    }
+
+    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut R {
+        match *self {
+            InflateReader { inner_reader: ref mut r } => r
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::*;
+    use super::*;
+    use super::super::mem::*;
+    use super::super::Decorator;
+
+    use str;
+
+    #[test]
+    #[ignore]
+    fn smoke_test() {
+        let mem_writer = MemWriter::new();
+        let mut deflate_writer = DeflateWriter::new(mem_writer);
+        let in_msg = "test";
+        let in_bytes = in_msg.as_bytes();
+        deflate_writer.write(in_bytes);
+        deflate_writer.flush();
+        let buf = deflate_writer.inner().inner();
+        let mem_reader = MemReader::new(buf);
+        let mut inflate_reader = InflateReader::new(mem_reader);
+        let mut out_bytes = [0, .. 100];
+        let bytes_read = inflate_reader.read(out_bytes).unwrap();
+        assert_eq!(bytes_read, in_bytes.len());
+        let out_msg = str::from_utf8(out_bytes);
+        assert!(in_msg == out_msg);
+    }
+}
diff --git a/src/libstd/io/fs.rs b/src/libstd/io/fs.rs
new file mode 100644 (file)
index 0000000..d5514eb
--- /dev/null
@@ -0,0 +1,1289 @@
+// 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.
+
+/*! Synchronous File I/O
+
+This module provides a set of functions and traits for working
+with regular files & directories on a filesystem.
+
+At the top-level of the module are a set of freestanding functions, associated
+with various filesystem operations. They all operate on a `Path` object.
+
+All operations in this module, including those as part of `File` et al
+block the task during execution. Most will raise `std::io::io_error`
+conditions in the event of failure.
+
+Also included in this module is an implementation block on the `Path` object
+defined in `std::path::Path`. The impl adds useful methods about inspecting the
+metadata of a file. This includes getting the `stat` information, reading off
+particular bits of it, etc.
+
+# Example
+
+    use std::io::{File, fs};
+
+    let path = Path::new("foo.txt");
+
+    // create the file, whether it exists or not
+    let mut file = File::create(&path);
+    file.write(bytes!("foobar"));
+
+    // open the file in read-only mode
+    let mut file = File::open(&path);
+    file.read_to_end();
+
+    println!("{}", path.stat().size);
+    fs::symlink(&path, &Path::new("bar.txt"));
+    fs::unlink(&path);
+
+*/
+
+use c_str::ToCStr;
+use clone::Clone;
+use iter::Iterator;
+use super::{Reader, Writer, Seek};
+use super::{SeekStyle, Read, Write, Open, IoError, Truncate,
+            FileMode, FileAccess, FileStat, io_error, FilePermission};
+use rt::rtio::{RtioFileStream, IoFactory, with_local_io};
+use io;
+use option::{Some, None, Option};
+use result::{Ok, Err, Result};
+use path;
+use path::{Path, GenericPath};
+use vec::{OwnedVector, ImmutableVector};
+
+/// Unconstrained file access type that exposes read and write operations
+///
+/// Can be constructed via `File::open()`, `File::create()`, and
+/// `File::open_mode()`.
+///
+/// # Errors
+///
+/// This type will raise an io_error condition if operations are attempted against
+/// it for which its underlying file descriptor was not configured at creation
+/// time, via the `FileAccess` parameter to `File::open_mode()`.
+pub struct File {
+    priv fd: ~RtioFileStream,
+    priv path: Path,
+    priv last_nread: int,
+}
+
+fn io_raise<T>(f: &fn(io: &mut IoFactory) -> Result<T, IoError>) -> Option<T> {
+    do with_local_io |io| {
+        match f(io) {
+            Ok(t) => Some(t),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
+}
+
+impl File {
+    /// Open a file at `path` in the mode specified by the `mode` and `access`
+    /// arguments
+    ///
+    /// # Example
+    ///
+    ///     use std::io::{File, io_error, Open, ReadWrite};
+    ///
+    ///     let p = Path::new("/some/file/path.txt");
+    ///
+    ///     do io_error::cond.trap(|_| {
+    ///         // hoo-boy...
+    ///     }).inside {
+    ///         let file = match File::open_mode(&p, Open, ReadWrite) {
+    ///             Some(s) => s,
+    ///             None => fail!("whoops! I'm sure this raised, anyways..")
+    ///         };
+    ///         // do some stuff with that file
+    ///
+    ///         // the file will be closed at the end of this block
+    ///     }
+    ///     // ..
+    ///
+    /// `FileMode` and `FileAccess` provide information about the permissions
+    /// context in which a given stream is created. More information about them
+    /// can be found in `std::io`'s docs. If a file is opened with `Write`
+    /// or `ReadWrite` access, then it will be created it it does not already
+    /// exist.
+    ///
+    /// Note that, with this function, a `File` is returned regardless of the
+    /// access-limitations indicated by `FileAccess` (e.g. calling `write` on a
+    /// `File` opened as `Read` will raise an `io_error` condition at runtime).
+    ///
+    /// # Errors
+    ///
+    /// This function will raise an `io_error` condition under a number of
+    /// different circumstances, to include but not limited to:
+    ///
+    /// * Opening a file that does not exist with `Read` access.
+    /// * Attempting to open a file with a `FileAccess` that the user lacks
+    ///   permissions for
+    /// * Filesystem-level errors (full disk, etc)
+    pub fn open_mode(path: &Path,
+                     mode: FileMode,
+                     access: FileAccess) -> Option<File> {
+        do with_local_io |io| {
+            match io.fs_open(&path.to_c_str(), mode, access) {
+                Ok(fd) => Some(File {
+                    path: path.clone(),
+                    fd: fd,
+                    last_nread: -1
+                }),
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
+            }
+        }
+    }
+
+    /// Attempts to open a file in read-only mode. This function is equivalent to
+    /// `File::open_mode(path, Open, Read)`, and will raise all of the same
+    /// errors that `File::open_mode` does.
+    ///
+    /// For more information, see the `File::open_mode` function.
+    ///
+    /// # Example
+    ///
+    ///     use std::io::File;
+    ///
+    ///     let contents = File::open(&Path::new("foo.txt")).read_to_end();
+    pub fn open(path: &Path) -> Option<File> {
+        File::open_mode(path, Open, Read)
+    }
+
+    /// Attempts to create a file in write-only mode. This function is
+    /// equivalent to `File::open_mode(path, Truncate, Write)`, and will
+    /// raise all of the same errors that `File::open_mode` does.
+    ///
+    /// For more information, see the `File::open_mode` function.
+    ///
+    /// # Example
+    ///
+    ///     use std::io::File;
+    ///
+    ///     let mut f = File::create(&Path::new("foo.txt"));
+    ///     f.write(bytes!("This is a sample file"));
+    pub fn create(path: &Path) -> Option<File> {
+        File::open_mode(path, Truncate, Write)
+    }
+
+    /// Returns the original path which was used to open this file.
+    pub fn path<'a>(&'a self) -> &'a Path {
+        &self.path
+    }
+
+    /// Synchronizes all modifications to this file to its permanent storage
+    /// device. This will flush any internal buffers necessary to perform this
+    /// operation.
+    ///
+    /// # Errors
+    ///
+    /// This function will raise on the `io_error` condition on failure.
+    pub fn fsync(&mut self) {
+        self.fd.fsync();
+    }
+
+    /// This function is similar to `fsync`, except that it may not synchronize
+    /// file metadata to the filesystem. This is intended for use case which
+    /// must synchronize content, but don't need the metadata on disk. The goal
+    /// of this method is to reduce disk operations.
+    ///
+    /// # Errors
+    ///
+    /// This function will raise on the `io_error` condition on failure.
+    pub fn datasync(&mut self) {
+        self.fd.datasync();
+    }
+
+    /// Either truncates or extends the underlying file, as extended from the
+    /// file's current position. This is equivalent to the unix `truncate`
+    /// function.
+    ///
+    /// The offset given is added to the file's current position and the result
+    /// is the new size of the file. If the new size is less than the current
+    /// size, then the file is truncated. If the new size is greater than the
+    /// current size, then the file is expanded to be filled with 0s.
+    ///
+    /// # Errors
+    ///
+    /// On error, this function will raise on the `io_error` condition.
+    pub fn truncate(&mut self, offset: i64) {
+        self.fd.truncate(offset);
+    }
+}
+
+/// Unlink a file from the underlying filesystem.
+///
+/// # Example
+///
+///     use std::io::fs;
+///
+///     let p = Path::new("/some/file/path.txt");
+///     fs::unlink(&p);
+///     // if we made it here without failing, then the
+///     // unlink operation was successful
+///
+/// Note that, just because an unlink call was successful, it is not
+/// guaranteed that a file is immediately deleted (e.g. depending on
+/// platform, other open file descriptors may prevent immediate removal)
+///
+/// # Errors
+///
+/// This function will raise an `io_error` condition if the path points to a
+/// directory, the user lacks permissions to remove the file, or if some
+/// other filesystem-level error occurs.
+pub fn unlink(path: &Path) {
+    do io_raise |io| { io.fs_unlink(&path.to_c_str()) };
+}
+
+/// Given a path, query the file system to get information about a file,
+/// directory, etc. This function will traverse symlinks to query
+/// information about the destination file.
+///
+/// Returns a fully-filled out stat structure on succes, and on failure it
+/// will return a dummy stat structure (it is expected that the condition
+/// raised is handled as well).
+///
+/// # Example
+///
+///     use std::io;
+///     use std::io::fs;
+///
+///     let p = Path::new("/some/file/path.txt");
+///     match io::result(|| fs::stat(&p)) {
+///         Ok(stat) => { /* ... */ }
+///         Err(e) => { /* handle error */ }
+///     }
+///
+/// # Errors
+///
+/// This call will raise an `io_error` condition if the user lacks the
+/// requisite permissions to perform a `stat` call on the given path or if
+/// there is no entry in the filesystem at the provided path.
+pub fn stat(path: &Path) -> FileStat {
+    do io_raise |io| {
+        io.fs_stat(&path.to_c_str())
+    }.unwrap_or_else(dummystat)
+}
+
+fn dummystat() -> FileStat {
+    FileStat {
+        path: Path::new(""),
+        size: 0,
+        kind: io::TypeFile,
+        perm: 0,
+        created: 0,
+        modified: 0,
+        accessed: 0,
+        unstable: io::UnstableFileStat {
+            device: 0,
+            inode: 0,
+            rdev: 0,
+            nlink: 0,
+            uid: 0,
+            gid: 0,
+            blksize: 0,
+            blocks: 0,
+            flags: 0,
+            gen: 0,
+        }
+    }
+}
+
+/// Perform the same operation as the `stat` function, except that this
+/// function does not traverse through symlinks. This will return
+/// information about the symlink file instead of the file that it points
+/// to.
+///
+/// # Errors
+///
+/// See `stat`
+pub fn lstat(path: &Path) -> FileStat {
+    do io_raise |io| {
+        io.fs_lstat(&path.to_c_str())
+    }.unwrap_or_else(dummystat)
+}
+
+/// Rename a file or directory to a new name.
+///
+/// # Example
+///
+///     use std::io::fs;
+///
+///     fs::rename(&Path::new("foo"), &Path::new("bar"));
+///     // Oh boy, nothing was raised!
+///
+/// # Errors
+///
+/// Will raise an `io_error` condition if the provided `path` doesn't exist,
+/// the process lacks permissions to view the contents, or if some other
+/// intermittent I/O error occurs.
+pub fn rename(from: &Path, to: &Path) {
+    do io_raise |io| {
+        io.fs_rename(&from.to_c_str(), &to.to_c_str())
+    };
+}
+
+/// Copies the contents of one file to another. This function will also
+/// copy the permission bits of the original file to the destination file.
+///
+/// Note that if `from` and `to` both point to the same file, then the file
+/// will likely get truncated by this operation.
+///
+/// # Example
+///
+///     use std::io::fs;
+///
+///     fs::copy(&Path::new("foo.txt"), &Path::new("bar.txt"));
+///     // Oh boy, nothing was raised!
+///
+/// # Errors
+///
+/// Will raise an `io_error` condition is the following situtations, but is
+/// not limited to just these cases:
+///
+/// * The `from` path is not a file
+/// * The `from` file does not exist
+/// * The current process does not have the permission rights to access
+///   `from` or write `to`
+///
+/// Note that this copy is not atomic in that once the destination is
+/// ensured to not exist, there is nothing preventing the destination from
+/// being created and then destroyed by this operation.
+pub fn copy(from: &Path, to: &Path) {
+    if !from.is_file() {
+        return io_error::cond.raise(IoError {
+            kind: io::MismatchedFileTypeForOperation,
+            desc: "the source path is not an existing file",
+            detail: None,
+        });
+    }
+
+    let mut reader = match File::open(from) { Some(f) => f, None => return };
+    let mut writer = match File::create(to) { Some(f) => f, None => return };
+    let mut buf = [0, ..io::DEFAULT_BUF_SIZE];
+
+    loop {
+        match reader.read(buf) {
+            Some(amt) => writer.write(buf.slice_to(amt)),
+            None => break
+        }
+    }
+
+    chmod(to, from.stat().perm)
+}
+
+/// Changes the permission mode bits found on a file or a directory. This
+/// function takes a mask from the `io` module
+///
+/// # Example
+///
+///     use std::io;
+///     use std::io::fs;
+///
+///     fs::chmod(&Path::new("file.txt"), io::UserFile);
+///     fs::chmod(&Path::new("file.txt"), io::UserRead | io::UserWrite);
+///     fs::chmod(&Path::new("dir"),      io::UserDir);
+///     fs::chmod(&Path::new("file.exe"), io::UserExec);
+///
+/// # Errors
+///
+/// If this funciton encounters an I/O error, it will raise on the `io_error`
+/// condition. Some possible error situations are not having the permission to
+/// change the attributes of a file or the file not existing.
+pub fn chmod(path: &Path, mode: io::FilePermission) {
+    do io_raise |io| {
+        io.fs_chmod(&path.to_c_str(), mode)
+    };
+}
+
+/// Change the user and group owners of a file at the specified path.
+///
+/// # Errors
+///
+/// This funtion will raise on the `io_error` condition on failure.
+pub fn chown(path: &Path, uid: int, gid: int) {
+    do io_raise |io| { io.fs_chown(&path.to_c_str(), uid, gid) };
+}
+
+/// Creates a new hard link on the filesystem. The `dst` path will be a
+/// link pointing to the `src` path. Note that systems often require these
+/// two paths to both be located on the same filesystem.
+///
+/// # Errors
+///
+/// This function will raise on the `io_error` condition on failure.
+pub fn link(src: &Path, dst: &Path) {
+    do io_raise |io| { io.fs_link(&src.to_c_str(), &dst.to_c_str()) };
+}
+
+/// Creates a new symbolic link on the filesystem. The `dst` path will be a
+/// symlink pointing to the `src` path.
+///
+/// # Errors
+///
+/// This function will raise on the `io_error` condition on failure.
+pub fn symlink(src: &Path, dst: &Path) {
+    do io_raise |io| { io.fs_symlink(&src.to_c_str(), &dst.to_c_str()) };
+}
+
+/// Reads a symlink, returning the file that the symlink points to.
+///
+/// # Errors
+///
+/// This function will raise on the `io_error` condition on failure. Failure
+/// conditions include reading a file that does not exist or reading a file
+/// which is not a symlink.
+pub fn readlink(path: &Path) -> Option<Path> {
+    do io_raise |io| { io.fs_readlink(&path.to_c_str()) }
+}
+
+/// Create a new, empty directory at the provided path
+///
+/// # Example
+///
+///     use std::libc::S_IRWXU;
+///     use std::io::fs;
+///
+///     let p = Path::new("/some/dir");
+///     fs::mkdir(&p, S_IRWXU as int);
+///     // If we got here, our directory exists! Horray!
+///
+/// # Errors
+///
+/// This call will raise an `io_error` condition if the user lacks permissions
+/// to make a new directory at the provided path, or if the directory already
+/// exists.
+pub fn mkdir(path: &Path, mode: FilePermission) {
+    do io_raise |io| {
+        io.fs_mkdir(&path.to_c_str(), mode)
+    };
+}
+
+/// Remove an existing, empty directory
+///
+/// # Example
+///
+///     use std::io::fs;
+///
+///     let p = Path::new("/some/dir");
+///     fs::rmdir(&p);
+///     // good riddance, you mean ol' directory
+///
+/// # Errors
+///
+/// This call will raise an `io_error` condition if the user lacks permissions
+/// to remove the directory at the provided path, or if the directory isn't
+/// empty.
+pub fn rmdir(path: &Path) {
+    do io_raise |io| {
+        io.fs_rmdir(&path.to_c_str())
+    };
+}
+
+/// Retrieve a vector containing all entries within a provided directory
+///
+/// # Example
+///
+///     use std::io::fs;
+///
+///     // one possible implementation of fs::walk_dir only visiting files
+///     fn visit_dirs(dir: &Path, cb: &fn(&Path)) {
+///         if dir.is_dir() {
+///             let contents = fs::readdir(dir).unwrap();
+///             for entry in contents.iter() {
+///                 if entry.is_dir() { visit_dirs(entry, cb); }
+///                 else { cb(entry); }
+///             }
+///         }
+///         else { fail!("nope"); }
+///     }
+///
+/// # Errors
+///
+/// Will raise an `io_error` condition if the provided `from` doesn't exist,
+/// the process lacks permissions to view the contents or if the `path` points
+/// at a non-directory file
+pub fn readdir(path: &Path) -> ~[Path] {
+    do io_raise |io| {
+        io.fs_readdir(&path.to_c_str(), 0)
+    }.unwrap_or_else(|| ~[])
+}
+
+/// Returns an iterator which will recursively walk the directory structure
+/// rooted at `path`. The path given will not be iterated over, and this will
+/// perform iteration in a top-down order.
+pub fn walk_dir(path: &Path) -> WalkIterator {
+    WalkIterator { stack: readdir(path) }
+}
+
+/// An iterator which walks over a directory
+pub struct WalkIterator {
+    priv stack: ~[Path],
+}
+
+impl Iterator<Path> for WalkIterator {
+    fn next(&mut self) -> Option<Path> {
+        match self.stack.shift_opt() {
+            Some(path) => {
+                if path.is_dir() {
+                    self.stack.push_all_move(readdir(&path));
+                }
+                Some(path)
+            }
+            None => None
+        }
+    }
+}
+
+/// Recursively create a directory and all of its parent components if they
+/// are missing.
+///
+/// # Errors
+///
+/// This function will raise on the `io_error` condition if an error
+/// happens, see `fs::mkdir` for more information about error conditions
+/// and performance.
+pub fn mkdir_recursive(path: &Path, mode: FilePermission) {
+    // tjc: if directory exists but with different permissions,
+    // should we return false?
+    if path.is_dir() {
+        return
+    }
+    if path.filename().is_some() {
+        mkdir_recursive(&path.dir_path(), mode);
+    }
+    mkdir(path, mode)
+}
+
+/// Removes a directory at this path, after removing all its contents. Use
+/// carefully!
+///
+/// # Errors
+///
+/// This function will raise on the `io_error` condition if an error
+/// happens. See `file::unlink` and `fs::readdir` for possible error
+/// conditions.
+pub fn rmdir_recursive(path: &Path) {
+    let children = readdir(path);
+    for child in children.iter() {
+        if child.is_dir() {
+            rmdir_recursive(child);
+        } else {
+            unlink(child);
+        }
+    }
+    // Directory should now be empty
+    rmdir(path);
+}
+
+/// Changes the timestamps for a file's last modification and access time.
+/// The file at the path specified will have its last access time set to
+/// `atime` and its modification time set to `mtime`. The times specified should
+/// be in milliseconds.
+///
+/// # Errors
+///
+/// This function will raise on the `io_error` condition if an error
+/// happens.
+// FIXME(#10301) these arguments should not be u64
+pub fn change_file_times(path: &Path, atime: u64, mtime: u64) {
+    do io_raise |io| {
+        io.fs_utime(&path.to_c_str(), atime, mtime)
+    };
+}
+
+impl Reader for File {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        match self.fd.read(buf) {
+            Ok(read) => {
+                self.last_nread = read;
+                match read {
+                    0 => None,
+                    _ => Some(read as uint)
+                }
+            },
+            Err(ioerr) => {
+                // EOF is indicated by returning None
+                if ioerr.kind != io::EndOfFile {
+                    io_error::cond.raise(ioerr);
+                }
+                return None;
+            }
+        }
+    }
+
+    fn eof(&mut self) -> bool { self.last_nread == 0 }
+}
+
+impl Writer for File {
+    fn write(&mut self, buf: &[u8]) {
+        match self.fd.write(buf) {
+            Ok(()) => (),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+            }
+        }
+    }
+}
+
+impl Seek for File {
+    fn tell(&self) -> u64 {
+        let res = self.fd.tell();
+        match res {
+            Ok(cursor) => cursor,
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                return -1;
+            }
+        }
+    }
+
+    fn seek(&mut self, pos: i64, style: SeekStyle) {
+        match self.fd.seek(pos, style) {
+            Ok(_) => {
+                // successful seek resets EOF indicator
+                self.last_nread = -1;
+                ()
+            },
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+            }
+        }
+    }
+}
+
+impl path::Path {
+    /// Get information on the file, directory, etc at this path.
+    ///
+    /// Consult the `file::stat` documentation for more info.
+    ///
+    /// This call preserves identical runtime/error semantics with `file::stat`.
+    pub fn stat(&self) -> FileStat { stat(self) }
+
+    /// Boolean value indicator whether the underlying file exists on the local
+    /// filesystem. This will return true if the path points to either a
+    /// directory or a file.
+    ///
+    /// # Errors
+    ///
+    /// Will not raise a condition
+    pub fn exists(&self) -> bool {
+        io::result(|| self.stat()).is_ok()
+    }
+
+    /// Whether the underlying implemention (be it a file path, or something
+    /// else) points at a "regular file" on the FS. Will return false for paths
+    /// to non-existent locations or directories or other non-regular files
+    /// (named pipes, etc).
+    ///
+    /// # Errors
+    ///
+    /// Will not raise a condition
+    pub fn is_file(&self) -> bool {
+        match io::result(|| self.stat()) {
+            Ok(s) => s.kind == io::TypeFile,
+            Err(*) => false
+        }
+    }
+
+    /// Whether the underlying implemention (be it a file path,
+    /// or something else) is pointing at a directory in the underlying FS.
+    /// Will return false for paths to non-existent locations or if the item is
+    /// not a directory (eg files, named pipes, links, etc)
+    ///
+    /// # Errors
+    ///
+    /// Will not raise a condition
+    pub fn is_dir(&self) -> bool {
+        match io::result(|| self.stat()) {
+            Ok(s) => s.kind == io::TypeDirectory,
+            Err(*) => false
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::*;
+    use io::{SeekSet, SeekCur, SeekEnd, io_error, Read, Open, ReadWrite};
+    use io;
+    use str;
+    use super::{File, rmdir, mkdir, readdir, rmdir_recursive, mkdir_recursive,
+                copy, unlink, stat, symlink, link, readlink, chmod,
+                lstat, change_file_times};
+
+    fn tmpdir() -> Path {
+        use os;
+        use rand;
+        let ret = os::tmpdir().join(format!("rust-{}", rand::random::<u32>()));
+        mkdir(&ret, io::UserRWX);
+        ret
+    }
+
+    fn free<T>(_: T) {}
+
+    #[test]
+    fn file_test_io_smoke_test() {
+        let message = "it's alright. have a good time";
+        let filename = &Path::new("./tmp/file_rt_io_file_test.txt");
+        {
+            let mut write_stream = File::open_mode(filename, Open, ReadWrite);
+            write_stream.write(message.as_bytes());
+        }
+        {
+            let mut read_stream = File::open_mode(filename, Open, Read);
+            let mut read_buf = [0, .. 1028];
+            let read_str = match read_stream.read(read_buf).unwrap() {
+                -1|0 => fail!("shouldn't happen"),
+                n => str::from_utf8(read_buf.slice_to(n))
+            };
+            assert!(read_str == message.to_owned());
+        }
+        unlink(filename);
+    }
+
+    #[test]
+    fn file_test_io_invalid_path_opened_without_create_should_raise_condition() {
+        let filename = &Path::new("./tmp/file_that_does_not_exist.txt");
+        let mut called = false;
+        do io_error::cond.trap(|_| {
+            called = true;
+        }).inside {
+            let result = File::open_mode(filename, Open, Read);
+            assert!(result.is_none());
+        }
+        assert!(called);
+    }
+
+    #[test]
+    fn file_test_iounlinking_invalid_path_should_raise_condition() {
+        let filename = &Path::new("./tmp/file_another_file_that_does_not_exist.txt");
+        let mut called = false;
+        do io_error::cond.trap(|_| {
+            called = true;
+        }).inside {
+            unlink(filename);
+        }
+        assert!(called);
+    }
+
+    #[test]
+    fn file_test_io_non_positional_read() {
+        let message = "ten-four";
+        let mut read_mem = [0, .. 8];
+        let filename = &Path::new("./tmp/file_rt_io_file_test_positional.txt");
+        {
+            let mut rw_stream = File::open_mode(filename, Open, ReadWrite);
+            rw_stream.write(message.as_bytes());
+        }
+        {
+            let mut read_stream = File::open_mode(filename, Open, Read);
+            {
+                let read_buf = read_mem.mut_slice(0, 4);
+                read_stream.read(read_buf);
+            }
+            {
+                let read_buf = read_mem.mut_slice(4, 8);
+                read_stream.read(read_buf);
+            }
+        }
+        unlink(filename);
+        let read_str = str::from_utf8(read_mem);
+        assert!(read_str == message.to_owned());
+    }
+
+    #[test]
+    fn file_test_io_seek_and_tell_smoke_test() {
+        let message = "ten-four";
+        let mut read_mem = [0, .. 4];
+        let set_cursor = 4 as u64;
+        let mut tell_pos_pre_read;
+        let mut tell_pos_post_read;
+        let filename = &Path::new("./tmp/file_rt_io_file_test_seeking.txt");
+        {
+            let mut rw_stream = File::open_mode(filename, Open, ReadWrite);
+            rw_stream.write(message.as_bytes());
+        }
+        {
+            let mut read_stream = File::open_mode(filename, Open, Read);
+            read_stream.seek(set_cursor as i64, SeekSet);
+            tell_pos_pre_read = read_stream.tell();
+            read_stream.read(read_mem);
+            tell_pos_post_read = read_stream.tell();
+        }
+        unlink(filename);
+        let read_str = str::from_utf8(read_mem);
+        assert!(read_str == message.slice(4, 8).to_owned());
+        assert!(tell_pos_pre_read == set_cursor);
+        assert!(tell_pos_post_read == message.len() as u64);
+    }
+
+    #[test]
+    fn file_test_io_seek_and_write() {
+        let initial_msg =   "food-is-yummy";
+        let overwrite_msg =    "-the-bar!!";
+        let final_msg =     "foo-the-bar!!";
+        let seek_idx = 3;
+        let mut read_mem = [0, .. 13];
+        let filename = &Path::new("./tmp/file_rt_io_file_test_seek_and_write.txt");
+        {
+            let mut rw_stream = File::open_mode(filename, Open, ReadWrite);
+            rw_stream.write(initial_msg.as_bytes());
+            rw_stream.seek(seek_idx as i64, SeekSet);
+            rw_stream.write(overwrite_msg.as_bytes());
+        }
+        {
+            let mut read_stream = File::open_mode(filename, Open, Read);
+            read_stream.read(read_mem);
+        }
+        unlink(filename);
+        let read_str = str::from_utf8(read_mem);
+        assert!(read_str == final_msg.to_owned());
+    }
+
+    #[test]
+    fn file_test_io_seek_shakedown() {
+        use std::str;          // 01234567890123
+        let initial_msg =   "qwer-asdf-zxcv";
+        let chunk_one = "qwer";
+        let chunk_two = "asdf";
+        let chunk_three = "zxcv";
+        let mut read_mem = [0, .. 4];
+        let filename = &Path::new("./tmp/file_rt_io_file_test_seek_shakedown.txt");
+        {
+            let mut rw_stream = File::open_mode(filename, Open, ReadWrite);
+            rw_stream.write(initial_msg.as_bytes());
+        }
+        {
+            let mut read_stream = File::open_mode(filename, Open, Read);
+
+            read_stream.seek(-4, SeekEnd);
+            read_stream.read(read_mem);
+            let read_str = str::from_utf8(read_mem);
+            assert!(read_str == chunk_three.to_owned());
+
+            read_stream.seek(-9, SeekCur);
+            read_stream.read(read_mem);
+            let read_str = str::from_utf8(read_mem);
+            assert!(read_str == chunk_two.to_owned());
+
+            read_stream.seek(0, SeekSet);
+            read_stream.read(read_mem);
+            let read_str = str::from_utf8(read_mem);
+            assert!(read_str == chunk_one.to_owned());
+        }
+        unlink(filename);
+    }
+
+    #[test]
+    fn file_test_stat_is_correct_on_is_file() {
+        let filename = &Path::new("./tmp/file_stat_correct_on_is_file.txt");
+        {
+            let mut fs = File::open_mode(filename, Open, ReadWrite);
+            let msg = "hw";
+            fs.write(msg.as_bytes());
+        }
+        let stat_res = stat(filename);
+        assert_eq!(stat_res.kind, io::TypeFile);
+        unlink(filename);
+    }
+
+    #[test]
+    fn file_test_stat_is_correct_on_is_dir() {
+        let filename = &Path::new("./tmp/file_stat_correct_on_is_dir");
+        mkdir(filename, io::UserRWX);
+        let stat_res = filename.stat();
+        assert!(stat_res.kind == io::TypeDirectory);
+        rmdir(filename);
+    }
+
+    #[test]
+    fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() {
+        let dir = &Path::new("./tmp/fileinfo_false_on_dir");
+        mkdir(dir, io::UserRWX);
+        assert!(dir.is_file() == false);
+        rmdir(dir);
+    }
+
+    #[test]
+    fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
+        let file = &Path::new("./tmp/fileinfo_check_exists_b_and_a.txt");
+        File::create(file).write(bytes!("foo"));
+        assert!(file.exists());
+        unlink(file);
+        assert!(!file.exists());
+    }
+
+    #[test]
+    fn file_test_directoryinfo_check_exists_before_and_after_mkdir() {
+        let dir = &Path::new("./tmp/before_and_after_dir");
+        assert!(!dir.exists());
+        mkdir(dir, io::UserRWX);
+        assert!(dir.exists());
+        assert!(dir.is_dir());
+        rmdir(dir);
+        assert!(!dir.exists());
+    }
+
+    #[test]
+    fn file_test_directoryinfo_readdir() {
+        use std::str;
+        let dir = &Path::new("./tmp/di_readdir");
+        mkdir(dir, io::UserRWX);
+        let prefix = "foo";
+        for n in range(0,3) {
+            let f = dir.join(format!("{}.txt", n));
+            let mut w = File::create(&f);
+            let msg_str = (prefix + n.to_str().to_owned()).to_owned();
+            let msg = msg_str.as_bytes();
+            w.write(msg);
+        }
+        let files = readdir(dir);
+        let mut mem = [0u8, .. 4];
+        for f in files.iter() {
+            {
+                let n = f.filestem_str();
+                File::open(f).read(mem);
+                let read_str = str::from_utf8(mem);
+                let expected = match n {
+                    None|Some("") => fail!("really shouldn't happen.."),
+                    Some(n) => prefix+n
+                };
+                assert!(expected == read_str);
+            }
+            unlink(f);
+        }
+        rmdir(dir);
+    }
+
+    #[test]
+    fn recursive_mkdir_slash() {
+        mkdir_recursive(&Path::new("/"), io::UserRWX);
+    }
+
+    #[test]
+    fn unicode_path_is_dir() {
+        assert!(Path::new(".").is_dir());
+        assert!(!Path::new("test/stdtest/fs.rs").is_dir());
+
+        let tmpdir = tmpdir();
+
+        let mut dirpath = tmpdir.clone();
+        dirpath.push(format!("test-가一ー你好"));
+        mkdir(&dirpath, io::UserRWX);
+        assert!(dirpath.is_dir());
+
+        let mut filepath = dirpath;
+        filepath.push("unicode-file-\uac00\u4e00\u30fc\u4f60\u597d.rs");
+        File::create(&filepath); // ignore return; touch only
+        assert!(!filepath.is_dir());
+        assert!(filepath.exists());
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn unicode_path_exists() {
+        assert!(Path::new(".").exists());
+        assert!(!Path::new("test/nonexistent-bogus-path").exists());
+
+        let tmpdir = tmpdir();
+        let unicode = tmpdir.clone();
+        let unicode = unicode.join(format!("test-각丁ー再见"));
+        mkdir(&unicode, io::UserRWX);
+        assert!(unicode.exists());
+        assert!(!Path::new("test/unicode-bogus-path-각丁ー再见").exists());
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn copy_file_does_not_exist() {
+        let from = Path::new("test/nonexistent-bogus-path");
+        let to = Path::new("test/other-bogus-path");
+        match io::result(|| copy(&from, &to)) {
+            Ok(*) => fail!(),
+            Err(*) => {
+                assert!(!from.exists());
+                assert!(!to.exists());
+            }
+        }
+    }
+
+    #[test]
+    fn copy_file_ok() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        File::create(&input).write(bytes!("hello"));
+        copy(&input, &out);
+        let contents = File::open(&out).read_to_end();
+        assert_eq!(contents.as_slice(), bytes!("hello"));
+
+        assert_eq!(input.stat().perm, out.stat().perm);
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn copy_file_dst_dir() {
+        let tmpdir = tmpdir();
+        let out = tmpdir.join("out");
+
+        File::create(&out);
+        match io::result(|| copy(&out, &tmpdir)) {
+            Ok(*) => fail!(), Err(*) => {}
+        }
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn copy_file_dst_exists() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in");
+        let output = tmpdir.join("out");
+
+        File::create(&input).write("foo".as_bytes());
+        File::create(&output).write("bar".as_bytes());
+        copy(&input, &output);
+
+        assert_eq!(File::open(&output).read_to_end(),
+                   (bytes!("foo")).to_owned());
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn copy_file_src_dir() {
+        let tmpdir = tmpdir();
+        let out = tmpdir.join("out");
+
+        match io::result(|| copy(&tmpdir, &out)) {
+            Ok(*) => fail!(), Err(*) => {}
+        }
+        assert!(!out.exists());
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn copy_file_preserves_perm_bits() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        File::create(&input);
+        chmod(&input, io::UserRead);
+        copy(&input, &out);
+        assert!(out.stat().perm & io::UserWrite == 0);
+
+        chmod(&input, io::UserFile);
+        chmod(&out, io::UserFile);
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    #[ignore(cfg(windows))] // FIXME(#10264) operation not permitted?
+    fn symlinks_work() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        File::create(&input).write("foobar".as_bytes());
+        symlink(&input, &out);
+        assert_eq!(lstat(&out).kind, io::TypeSymlink);
+        assert_eq!(stat(&out).size, stat(&input).size);
+        assert_eq!(File::open(&out).read_to_end(), (bytes!("foobar")).to_owned());
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    #[ignore(cfg(windows))] // apparently windows doesn't like symlinks
+    fn symlink_noexist() {
+        let tmpdir = tmpdir();
+        // symlinks can point to things that don't exist
+        symlink(&tmpdir.join("foo"), &tmpdir.join("bar"));
+        assert!(readlink(&tmpdir.join("bar")).unwrap() == tmpdir.join("foo"));
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn readlink_not_symlink() {
+        let tmpdir = tmpdir();
+        match io::result(|| readlink(&tmpdir)) {
+            Ok(*) => fail!("wanted a failure"),
+            Err(*) => {}
+        }
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn links_work() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        File::create(&input).write("foobar".as_bytes());
+        link(&input, &out);
+        assert_eq!(lstat(&out).kind, io::TypeFile);
+        assert_eq!(stat(&out).size, stat(&input).size);
+        assert_eq!(stat(&out).unstable.nlink, 2);
+        assert_eq!(File::open(&out).read_to_end(), (bytes!("foobar")).to_owned());
+
+        // can't link to yourself
+        match io::result(|| link(&input, &input)) {
+            Ok(*) => fail!("wanted a failure"),
+            Err(*) => {}
+        }
+        // can't link to something that doesn't exist
+        match io::result(|| link(&tmpdir.join("foo"), &tmpdir.join("bar"))) {
+            Ok(*) => fail!("wanted a failure"),
+            Err(*) => {}
+        }
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn chmod_works() {
+        let tmpdir = tmpdir();
+        let file = tmpdir.join("in.txt");
+
+        File::create(&file);
+        assert!(stat(&file).perm & io::UserWrite == io::UserWrite);
+        chmod(&file, io::UserRead);
+        assert!(stat(&file).perm & io::UserWrite == 0);
+
+        match io::result(|| chmod(&tmpdir.join("foo"), io::UserRWX)) {
+            Ok(*) => fail!("wanted a failure"),
+            Err(*) => {}
+        }
+
+        chmod(&file, io::UserFile);
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn sync_doesnt_kill_anything() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("in.txt");
+
+        let mut file = File::open_mode(&path, io::Open, io::ReadWrite).unwrap();
+        file.fsync();
+        file.datasync();
+        file.write(bytes!("foo"));
+        file.fsync();
+        file.datasync();
+        free(file);
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn truncate_works() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("in.txt");
+
+        let mut file = File::open_mode(&path, io::Open, io::ReadWrite).unwrap();
+        file.write(bytes!("foo"));
+
+        // Do some simple things with truncation
+        assert_eq!(stat(&path).size, 3);
+        file.truncate(10);
+        assert_eq!(stat(&path).size, 10);
+        file.write(bytes!("bar"));
+        assert_eq!(stat(&path).size, 10);
+        assert_eq!(File::open(&path).read_to_end(),
+                   (bytes!("foobar", 0, 0, 0, 0)).to_owned());
+
+        // Truncate to a smaller length, don't seek, and then write something.
+        // Ensure that the intermediate zeroes are all filled in (we're seeked
+        // past the end of the file).
+        file.truncate(2);
+        assert_eq!(stat(&path).size, 2);
+        file.write(bytes!("wut"));
+        assert_eq!(stat(&path).size, 9);
+        assert_eq!(File::open(&path).read_to_end(),
+                   (bytes!("fo", 0, 0, 0, 0, "wut")).to_owned());
+        free(file);
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn open_flavors() {
+        let tmpdir = tmpdir();
+
+        match io::result(|| File::open_mode(&tmpdir.join("a"), io::Open,
+                                            io::Read)) {
+            Ok(*) => fail!(), Err(*) => {}
+        }
+        File::open_mode(&tmpdir.join("b"), io::Open, io::Write).unwrap();
+        File::open_mode(&tmpdir.join("c"), io::Open, io::ReadWrite).unwrap();
+        File::open_mode(&tmpdir.join("d"), io::Append, io::Write).unwrap();
+        File::open_mode(&tmpdir.join("e"), io::Append, io::ReadWrite).unwrap();
+        File::open_mode(&tmpdir.join("f"), io::Truncate, io::Write).unwrap();
+        File::open_mode(&tmpdir.join("g"), io::Truncate, io::ReadWrite).unwrap();
+
+        File::create(&tmpdir.join("h")).write("foo".as_bytes());
+        File::open_mode(&tmpdir.join("h"), io::Open, io::Read).unwrap();
+        {
+            let mut f = File::open_mode(&tmpdir.join("h"), io::Open,
+                                        io::Read).unwrap();
+            match io::result(|| f.write("wut".as_bytes())) {
+                Ok(*) => fail!(), Err(*) => {}
+            }
+        }
+        assert_eq!(stat(&tmpdir.join("h")).size, 3);
+        {
+            let mut f = File::open_mode(&tmpdir.join("h"), io::Append,
+                                        io::Write).unwrap();
+            f.write("bar".as_bytes());
+        }
+        assert_eq!(stat(&tmpdir.join("h")).size, 6);
+        {
+            let mut f = File::open_mode(&tmpdir.join("h"), io::Truncate,
+                                        io::Write).unwrap();
+            f.write("bar".as_bytes());
+        }
+        assert_eq!(stat(&tmpdir.join("h")).size, 3);
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn utime() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("a");
+        File::create(&path);
+
+        change_file_times(&path, 1000, 2000);
+        assert_eq!(path.stat().accessed, 1000);
+        assert_eq!(path.stat().modified, 2000);
+
+        rmdir_recursive(&tmpdir);
+    }
+
+    #[test]
+    fn utime_noexist() {
+        let tmpdir = tmpdir();
+
+        match io::result(|| change_file_times(&tmpdir.join("a"), 100, 200)) {
+            Ok(*) => fail!(),
+            Err(*) => {}
+        }
+
+        rmdir_recursive(&tmpdir);
+    }
+}
diff --git a/src/libstd/io/mem.rs b/src/libstd/io/mem.rs
new file mode 100644 (file)
index 0000000..e754d9b
--- /dev/null
@@ -0,0 +1,308 @@
+// 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.
+
+//! Readers and Writers for in-memory buffers
+//!
+//! # XXX
+//!
+//! * Should probably have something like this for strings.
+//! * Should they implement Closable? Would take extra state.
+
+use cmp::min;
+use prelude::*;
+use super::*;
+use vec;
+
+/// Writes to an owned, growable byte vector
+pub struct MemWriter {
+    priv buf: ~[u8],
+    priv pos: uint,
+}
+
+impl MemWriter {
+    pub fn new() -> MemWriter {
+        MemWriter { buf: vec::with_capacity(128), pos: 0 }
+    }
+}
+
+impl Writer for MemWriter {
+    fn write(&mut self, buf: &[u8]) {
+        // Make sure the internal buffer is as least as big as where we
+        // currently are
+        let difference = self.pos as i64 - self.buf.len() as i64;
+        if difference > 0 {
+            self.buf.grow(difference as uint, &0);
+        }
+
+        // Figure out what bytes will be used to overwrite what's currently
+        // there (left), and what will be appended on the end (right)
+        let cap = self.buf.len() - self.pos;
+        let (left, right) = if cap <= buf.len() {
+            (buf.slice_to(cap), buf.slice_from(cap))
+        } else {
+            (buf, &[])
+        };
+
+        // Do the necessary writes
+        if left.len() > 0 {
+            vec::bytes::copy_memory(self.buf.mut_slice_from(self.pos),
+                                    left, left.len());
+        }
+        if right.len() > 0 {
+            self.buf.push_all(right);
+        }
+
+        // Bump us forward
+        self.pos += buf.len();
+    }
+}
+
+impl Seek for MemWriter {
+    fn tell(&self) -> u64 { self.pos as u64 }
+
+    fn seek(&mut self, pos: i64, style: SeekStyle) {
+        match style {
+            SeekSet => { self.pos = pos as uint; }
+            SeekEnd => { self.pos = self.buf.len() + pos as uint; }
+            SeekCur => { self.pos += pos as uint; }
+        }
+    }
+}
+
+impl Decorator<~[u8]> for MemWriter {
+    fn inner(self) -> ~[u8] { self.buf }
+    fn inner_ref<'a>(&'a self) -> &'a ~[u8] { &self.buf }
+    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] { &mut self.buf }
+}
+
+/// Reads from an owned byte vector
+pub struct MemReader {
+    priv buf: ~[u8],
+    priv pos: uint
+}
+
+impl MemReader {
+    pub fn new(buf: ~[u8]) -> MemReader {
+        MemReader {
+            buf: buf,
+            pos: 0
+        }
+    }
+}
+
+impl Reader for MemReader {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        { if self.eof() { return None; } }
+
+        let write_len = min(buf.len(), self.buf.len() - self.pos);
+        {
+            let input = self.buf.slice(self.pos, self.pos + write_len);
+            let output = buf.mut_slice(0, write_len);
+            assert_eq!(input.len(), output.len());
+            vec::bytes::copy_memory(output, input, write_len);
+        }
+        self.pos += write_len;
+        assert!(self.pos <= self.buf.len());
+
+        return Some(write_len);
+    }
+
+    fn eof(&mut self) -> bool { self.pos == self.buf.len() }
+}
+
+impl Seek for MemReader {
+    fn tell(&self) -> u64 { self.pos as u64 }
+
+    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
+}
+
+impl Decorator<~[u8]> for MemReader {
+
+    fn inner(self) -> ~[u8] {
+        match self {
+            MemReader { buf: buf, _ } => buf
+        }
+    }
+
+    fn inner_ref<'a>(&'a self) -> &'a ~[u8] {
+        match *self {
+            MemReader { buf: ref buf, _ } => buf
+        }
+    }
+
+    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] {
+        match *self {
+            MemReader { buf: ref mut buf, _ } => buf
+        }
+    }
+}
+
+
+/// Writes to a fixed-size byte slice
+pub struct BufWriter<'self> {
+    priv buf: &'self mut [u8],
+    priv pos: uint
+}
+
+impl<'self> BufWriter<'self> {
+    pub fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> {
+        BufWriter {
+            buf: buf,
+            pos: 0
+        }
+    }
+}
+
+impl<'self> Writer for BufWriter<'self> {
+    fn write(&mut self, _buf: &[u8]) { fail!() }
+
+    fn flush(&mut self) { fail!() }
+}
+
+impl<'self> Seek for BufWriter<'self> {
+    fn tell(&self) -> u64 { fail!() }
+
+    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
+}
+
+
+/// Reads from a fixed-size byte slice
+pub struct BufReader<'self> {
+    priv buf: &'self [u8],
+    priv pos: uint
+}
+
+impl<'self> BufReader<'self> {
+    pub fn new<'a>(buf: &'a [u8]) -> BufReader<'a> {
+        BufReader {
+            buf: buf,
+            pos: 0
+        }
+    }
+}
+
+impl<'self> Reader for BufReader<'self> {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        { if self.eof() { return None; } }
+
+        let write_len = min(buf.len(), self.buf.len() - self.pos);
+        {
+            let input = self.buf.slice(self.pos, self.pos + write_len);
+            let output = buf.mut_slice(0, write_len);
+            assert_eq!(input.len(), output.len());
+            vec::bytes::copy_memory(output, input, write_len);
+        }
+        self.pos += write_len;
+        assert!(self.pos <= self.buf.len());
+
+        return Some(write_len);
+     }
+
+    fn eof(&mut self) -> bool { self.pos == self.buf.len() }
+}
+
+impl<'self> Seek for BufReader<'self> {
+    fn tell(&self) -> u64 { self.pos as u64 }
+
+    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
+}
+
+///Calls a function with a MemWriter and returns
+///the writer's stored vector.
+pub fn with_mem_writer(writeFn:&fn(&mut MemWriter)) -> ~[u8] {
+    let mut writer = MemWriter::new();
+    writeFn(&mut writer);
+    writer.inner()
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::*;
+    use super::*;
+    use io::*;
+
+    #[test]
+    fn test_mem_writer() {
+        let mut writer = MemWriter::new();
+        assert_eq!(writer.tell(), 0);
+        writer.write([0]);
+        assert_eq!(writer.tell(), 1);
+        writer.write([1, 2, 3]);
+        writer.write([4, 5, 6, 7]);
+        assert_eq!(writer.tell(), 8);
+        assert_eq!(*writer.inner_ref(), ~[0, 1, 2, 3, 4, 5, 6, 7]);
+
+        writer.seek(0, SeekSet);
+        assert_eq!(writer.tell(), 0);
+        writer.write([3, 4]);
+        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 3, 4, 5, 6, 7]);
+
+        writer.seek(1, SeekCur);
+        writer.write([0, 1]);
+        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 7]);
+
+        writer.seek(-1, SeekEnd);
+        writer.write([1, 2]);
+        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 1, 2]);
+
+        writer.seek(1, SeekEnd);
+        writer.write([1]);
+        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]);
+    }
+
+    #[test]
+    fn test_mem_reader() {
+        let mut reader = MemReader::new(~[0, 1, 2, 3, 4, 5, 6, 7]);
+        let mut buf = [];
+        assert_eq!(reader.read(buf), Some(0));
+        assert_eq!(reader.tell(), 0);
+        let mut buf = [0];
+        assert_eq!(reader.read(buf), Some(1));
+        assert_eq!(reader.tell(), 1);
+        assert_eq!(buf, [0]);
+        let mut buf = [0, ..4];
+        assert_eq!(reader.read(buf), Some(4));
+        assert_eq!(reader.tell(), 5);
+        assert_eq!(buf, [1, 2, 3, 4]);
+        assert_eq!(reader.read(buf), Some(3));
+        assert_eq!(buf.slice(0, 3), [5, 6, 7]);
+        assert!(reader.eof());
+        assert_eq!(reader.read(buf), None);
+        assert!(reader.eof());
+    }
+
+    #[test]
+    fn test_buf_reader() {
+        let in_buf = ~[0, 1, 2, 3, 4, 5, 6, 7];
+        let mut reader = BufReader::new(in_buf);
+        let mut buf = [];
+        assert_eq!(reader.read(buf), Some(0));
+        assert_eq!(reader.tell(), 0);
+        let mut buf = [0];
+        assert_eq!(reader.read(buf), Some(1));
+        assert_eq!(reader.tell(), 1);
+        assert_eq!(buf, [0]);
+        let mut buf = [0, ..4];
+        assert_eq!(reader.read(buf), Some(4));
+        assert_eq!(reader.tell(), 5);
+        assert_eq!(buf, [1, 2, 3, 4]);
+        assert_eq!(reader.read(buf), Some(3));
+        assert_eq!(buf.slice(0, 3), [5, 6, 7]);
+        assert!(reader.eof());
+        assert_eq!(reader.read(buf), None);
+        assert!(reader.eof());
+    }
+
+    #[test]
+    fn test_with_mem_writer() {
+        let buf = with_mem_writer(|wr| wr.write([1,2,3,4,5,6,7]));
+        assert_eq!(buf, ~[1,2,3,4,5,6,7]);
+    }
+}
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
new file mode 100644 (file)
index 0000000..8858d0a
--- /dev/null
@@ -0,0 +1,1226 @@
+// 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.
+
+/*! Synchronous I/O
+
+This module defines the Rust interface for synchronous I/O.
+It models byte-oriented input and output with the Reader and Writer traits.
+Types that implement both `Reader` and `Writer` are called 'streams',
+and automatically implement the `Stream` trait.
+Implementations are provided for common I/O streams like
+file, TCP, UDP, Unix domain sockets.
+Readers and Writers may be composed to add capabilities like string
+parsing, encoding, and compression.
+
+# Examples
+
+Some examples of obvious things you might want to do
+
+* Read lines from stdin
+
+    for stdin().each_line |line| {
+        println(line)
+    }
+
+* Read a complete file to a string, (converting newlines?)
+
+    let contents = File::open("message.txt").read_to_str(); // read_to_str??
+
+* Write a line to a file
+
+    let file = File::open("message.txt", Create, Write);
+    file.write_line("hello, file!");
+
+* Iterate over the lines of a file
+
+    do File::open("message.txt").each_line |line| {
+        println(line)
+    }
+
+* Pull the lines of a file into a vector of strings
+
+    let lines = File::open("message.txt").line_iter().to_vec();
+
+* Make an simple HTTP request
+
+    let socket = TcpStream::open("localhost:8080");
+    socket.write_line("GET / HTTP/1.0");
+    socket.write_line("");
+    let response = socket.read_to_end();
+
+* Connect based on URL? Requires thinking about where the URL type lives
+  and how to make protocol handlers extensible, e.g. the "tcp" protocol
+  yields a `TcpStream`.
+
+    connect("tcp://localhost:8080");
+
+# Terms
+
+* Reader - An I/O source, reads bytes into a buffer
+* Writer - An I/O sink, writes bytes from a buffer
+* Stream - Typical I/O sources like files and sockets are both Readers and Writers,
+  and are collectively referred to a `streams`.
+* Decorator - A Reader or Writer that composes with others to add additional capabilities
+  such as encoding or decoding
+
+# Blocking and synchrony
+
+When discussing I/O you often hear the terms 'synchronous' and
+'asynchronous', along with 'blocking' and 'non-blocking' compared and
+contrasted. A synchronous I/O interface performs each I/O operation to
+completion before proceeding to the next. Synchronous interfaces are
+usually used in imperative style as a sequence of commands. An
+asynchronous interface allows multiple I/O requests to be issued
+simultaneously, without waiting for each to complete before proceeding
+to the next.
+
+Asynchronous interfaces are used to achieve 'non-blocking' I/O. In
+traditional single-threaded systems, performing a synchronous I/O
+operation means that the program stops all activity (it 'blocks')
+until the I/O is complete. Blocking is bad for performance when
+there are other computations that could be done.
+
+Asynchronous interfaces are most often associated with the callback
+(continuation-passing) style popularised by node.js. Such systems rely
+on all computations being run inside an event loop which maintains a
+list of all pending I/O events; when one completes the registered
+callback is run and the code that made the I/O request continues.
+Such interfaces achieve non-blocking at the expense of being more
+difficult to reason about.
+
+Rust's I/O interface is synchronous - easy to read - and non-blocking by default.
+
+Remember that Rust tasks are 'green threads', lightweight threads that
+are multiplexed onto a single operating system thread. If that system
+thread blocks then no other task may proceed. Rust tasks are
+relatively cheap to create, so as long as other tasks are free to
+execute then non-blocking code may be written by simply creating a new
+task.
+
+When discussing blocking in regards to Rust's I/O model, we are
+concerned with whether performing I/O blocks other Rust tasks from
+proceeding. In other words, when a task calls `read`, it must then
+wait (or 'sleep', or 'block') until the call to `read` is complete.
+During this time, other tasks may or may not be executed, depending on
+how `read` is implemented.
+
+
+Rust's default I/O implementation is non-blocking; by cooperating
+directly with the task scheduler it arranges to never block progress
+of *other* tasks. Under the hood, Rust uses asynchronous I/O via a
+per-scheduler (and hence per-thread) event loop. Synchronous I/O
+requests are implemented by descheduling the running task and
+performing an asynchronous request; the task is only resumed once the
+asynchronous request completes.
+
+For blocking (but possibly more efficient) implementations, look
+in the `io::native` module.
+
+# Error Handling
+
+I/O is an area where nearly every operation can result in unexpected
+errors. It should allow errors to be handled efficiently.
+It needs to be convenient to use I/O when you don't care
+about dealing with specific errors.
+
+Rust's I/O employs a combination of techniques to reduce boilerplate
+while still providing feedback about errors. The basic strategy:
+
+* Errors are fatal by default, resulting in task failure
+* Errors raise the `io_error` condition which provides an opportunity to inspect
+  an IoError object containing details.
+* Return values must have a sensible null or zero value which is returned
+  if a condition is handled successfully. This may be an `Option`, an empty
+  vector, or other designated error value.
+* Common traits are implemented for `Option`, e.g. `impl<R: Reader> Reader for Option<R>`,
+  so that nullable values do not have to be 'unwrapped' before use.
+
+These features combine in the API to allow for expressions like
+`File::new("diary.txt").write_line("met a girl")` without having to
+worry about whether "diary.txt" exists or whether the write
+succeeds. As written, if either `new` or `write_line` encounters
+an error the task will fail.
+
+If you wanted to handle the error though you might write
+
+    let mut error = None;
+    do io_error::cond(|e: IoError| {
+        error = Some(e);
+    }).in {
+        File::new("diary.txt").write_line("met a girl");
+    }
+
+    if error.is_some() {
+        println("failed to write my diary");
+    }
+
+XXX: Need better condition handling syntax
+
+In this case the condition handler will have the opportunity to
+inspect the IoError raised by either the call to `new` or the call to
+`write_line`, but then execution will continue.
+
+So what actually happens if `new` encounters an error? To understand
+that it's important to know that what `new` returns is not a `File`
+but an `Option<File>`.  If the file does not open, and the condition
+is handled, then `new` will simply return `None`. Because there is an
+implementation of `Writer` (the trait required ultimately required for
+types to implement `write_line`) there is no need to inspect or unwrap
+the `Option<File>` and we simply call `write_line` on it.  If `new`
+returned a `None` then the followup call to `write_line` will also
+raise an error.
+
+## Concerns about this strategy
+
+This structure will encourage a programming style that is prone
+to errors similar to null pointer dereferences.
+In particular code written to ignore errors and expect conditions to be unhandled
+will start passing around null or zero objects when wrapped in a condition handler.
+
+* XXX: How should we use condition handlers that return values?
+* XXX: Should EOF raise default conditions when EOF is not an error?
+
+# Issues with i/o scheduler affinity, work stealing, task pinning
+
+# Resource management
+
+* `close` vs. RAII
+
+# Paths, URLs and overloaded constructors
+
+
+
+# Scope
+
+In scope for core
+
+* Url?
+
+Some I/O things don't belong in core
+
+  - url
+  - net - `fn connect`
+    - http
+  - flate
+
+Out of scope
+
+* Async I/O. We'll probably want it eventually
+
+
+# XXX Questions and issues
+
+* Should default constructors take `Path` or `&str`? `Path` makes simple cases verbose.
+  Overloading would be nice.
+* Add overloading for Path and &str and Url &str
+* stdin/err/out
+* print, println, etc.
+* fsync
+* relationship with filesystem querying, Directory, File types etc.
+* Rename Reader/Writer to ByteReader/Writer, make Reader/Writer generic?
+* Can Port and Chan be implementations of a generic Reader<T>/Writer<T>?
+* Trait for things that are both readers and writers, Stream?
+* How to handle newline conversion
+* String conversion
+* open vs. connect for generic stream opening
+* Do we need `close` at all? dtors might be good enough
+* How does I/O relate to the Iterator trait?
+* std::base64 filters
+* Using conditions is a big unknown since we don't have much experience with them
+* Too many uses of OtherIoError
+
+*/
+
+#[allow(missing_doc)];
+
+use cast;
+use container::Container;
+use int;
+use iter::Iterator;
+use option::{Option, Some, None};
+use path::Path;
+use result::{Ok, Err, Result};
+use str::{StrSlice, OwnedStr};
+use to_str::ToStr;
+use uint;
+use unstable::finally::Finally;
+use vec::{OwnedVector, MutableVector};
+use vec;
+
+// Reexports
+pub use self::stdio::stdin;
+pub use self::stdio::stdout;
+pub use self::stdio::stderr;
+pub use self::stdio::print;
+pub use self::stdio::println;
+
+pub use self::fs::File;
+pub use self::timer::Timer;
+pub use self::net::ip::IpAddr;
+pub use self::net::tcp::TcpListener;
+pub use self::net::tcp::TcpStream;
+pub use self::net::udp::UdpStream;
+pub use self::pipe::PipeStream;
+pub use self::process::Process;
+
+/// Synchronous, non-blocking filesystem operations.
+pub mod fs;
+
+/// Synchronous, in-memory I/O.
+pub mod pipe;
+
+/// Child process management.
+pub mod process;
+
+/// Synchronous, non-blocking network I/O.
+pub mod net;
+
+/// Readers and Writers for memory buffers and strings.
+pub mod mem;
+
+/// Non-blocking access to stdin, stdout, stderr
+pub mod stdio;
+
+/// Implementations for Option
+mod option;
+
+/// Basic stream compression. XXX: Belongs with other flate code
+pub mod flate;
+
+/// Interop between byte streams and pipes. Not sure where it belongs
+pub mod comm_adapters;
+
+/// Extension traits
+pub mod extensions;
+
+/// Basic Timer
+pub mod timer;
+
+/// Buffered I/O wrappers
+pub mod buffered;
+
+/// Thread-blocking implementations
+pub mod native {
+    /// Posix file I/O
+    pub mod file;
+    /// Process spawning and child management
+    pub mod process;
+    /// Posix stdio
+    pub mod stdio;
+
+    /// Sockets
+    /// # XXX - implement this
+    pub mod net {
+        pub mod tcp { }
+        pub mod udp { }
+        #[cfg(unix)]
+        pub mod unix { }
+    }
+}
+
+/// Signal handling
+pub mod signal;
+
+/// The default buffer size for various I/O operations
+static DEFAULT_BUF_SIZE: uint = 1024 * 64;
+
+/// The type passed to I/O condition handlers to indicate error
+///
+/// # XXX
+///
+/// Is something like this sufficient? It's kind of archaic
+pub struct IoError {
+    kind: IoErrorKind,
+    desc: &'static str,
+    detail: Option<~str>
+}
+
+// FIXME: #8242 implementing manually because deriving doesn't work for some reason
+impl ToStr for IoError {
+    fn to_str(&self) -> ~str {
+        let mut s = ~"IoError { kind: ";
+        s.push_str(self.kind.to_str());
+        s.push_str(", desc: ");
+        s.push_str(self.desc);
+        s.push_str(", detail: ");
+        s.push_str(self.detail.to_str());
+        s.push_str(" }");
+        s
+    }
+}
+
+#[deriving(Eq)]
+pub enum IoErrorKind {
+    PreviousIoError,
+    OtherIoError,
+    EndOfFile,
+    FileNotFound,
+    PermissionDenied,
+    ConnectionFailed,
+    Closed,
+    ConnectionRefused,
+    ConnectionReset,
+    ConnectionAborted,
+    NotConnected,
+    BrokenPipe,
+    PathAlreadyExists,
+    PathDoesntExist,
+    MismatchedFileTypeForOperation,
+    ResourceUnavailable,
+    IoUnavailable,
+}
+
+// FIXME: #8242 implementing manually because deriving doesn't work for some reason
+impl ToStr for IoErrorKind {
+    fn to_str(&self) -> ~str {
+        match *self {
+            PreviousIoError => ~"PreviousIoError",
+            OtherIoError => ~"OtherIoError",
+            EndOfFile => ~"EndOfFile",
+            FileNotFound => ~"FileNotFound",
+            PermissionDenied => ~"PermissionDenied",
+            ConnectionFailed => ~"ConnectionFailed",
+            Closed => ~"Closed",
+            ConnectionRefused => ~"ConnectionRefused",
+            ConnectionReset => ~"ConnectionReset",
+            NotConnected => ~"NotConnected",
+            BrokenPipe => ~"BrokenPipe",
+            PathAlreadyExists => ~"PathAlreadyExists",
+            PathDoesntExist => ~"PathDoesntExist",
+            MismatchedFileTypeForOperation => ~"MismatchedFileTypeForOperation",
+            IoUnavailable => ~"IoUnavailable",
+            ResourceUnavailable => ~"ResourceUnavailable",
+            ConnectionAborted => ~"ConnectionAborted",
+        }
+    }
+}
+
+// XXX: Can't put doc comments on macros
+// Raised by `I/O` operations on error.
+condition! {
+    pub io_error: IoError -> ();
+}
+
+/// Helper for wrapper calls where you want to
+/// ignore any io_errors that might be raised
+pub fn ignore_io_error<T>(cb: &fn() -> T) -> T {
+    do io_error::cond.trap(|_| {
+        // just swallow the error.. downstream users
+        // who can make a decision based on a None result
+        // won't care
+    }).inside {
+        cb()
+    }
+}
+
+/// Helper for catching an I/O error and wrapping it in a Result object. The
+/// return result will be the last I/O error that happened or the result of the
+/// closure if no error occurred.
+pub fn result<T>(cb: &fn() -> T) -> Result<T, IoError> {
+    let mut err = None;
+    let ret = io_error::cond.trap(|e| {
+        if err.is_none() {
+            err = Some(e);
+        }
+    }).inside(cb);
+    match err {
+        Some(e) => Err(e),
+        None => Ok(ret),
+    }
+}
+
+pub trait Reader {
+
+    // Only two methods which need to get implemented for this trait
+
+    /// Read bytes, up to the length of `buf` and place them in `buf`.
+    /// Returns the number of bytes read. The number of bytes read my
+    /// be less than the number requested, even 0. Returns `None` on EOF.
+    ///
+    /// # Failure
+    ///
+    /// Raises the `io_error` condition on error. If the condition
+    /// is handled then no guarantee is made about the number of bytes
+    /// read and the contents of `buf`. If the condition is handled
+    /// returns `None` (XXX see below).
+    ///
+    /// # XXX
+    ///
+    /// * Should raise_default error on eof?
+    /// * If the condition is handled it should still return the bytes read,
+    ///   in which case there's no need to return Option - but then you *have*
+    ///   to install a handler to detect eof.
+    ///
+    /// This doesn't take a `len` argument like the old `read`.
+    /// Will people often need to slice their vectors to call this
+    /// and will that be annoying?
+    /// Is it actually possible for 0 bytes to be read successfully?
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint>;
+
+    /// Return whether the Reader has reached the end of the stream.
+    ///
+    /// # Example
+    ///
+    ///     let reader = File::open(&Path::new("foo.txt"))
+    ///     while !reader.eof() {
+    ///         println(reader.read_line());
+    ///     }
+    ///
+    /// # Failure
+    ///
+    /// Returns `true` on failure.
+    fn eof(&mut self) -> bool;
+
+    // Convenient helper methods based on the above methods
+
+    /// Reads a single byte. Returns `None` on EOF.
+    ///
+    /// # Failure
+    ///
+    /// Raises the same conditions as the `read` method. Returns
+    /// `None` if the condition is handled.
+    fn read_byte(&mut self) -> Option<u8> {
+        let mut buf = [0];
+        match self.read(buf) {
+            Some(0) => {
+                debug!("read 0 bytes. trying again");
+                self.read_byte()
+            }
+            Some(1) => Some(buf[0]),
+            Some(_) => unreachable!(),
+            None => None
+        }
+    }
+
+    /// Reads `len` bytes and appends them to a vector.
+    ///
+    /// May push fewer than the requested number of bytes on error
+    /// or EOF. Returns true on success, false on EOF or error.
+    ///
+    /// # Failure
+    ///
+    /// Raises the same conditions as `read`. Additionally raises `io_error`
+    /// on EOF. If `io_error` is handled then `push_bytes` may push less
+    /// than the requested number of bytes.
+    fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) {
+        unsafe {
+            let start_len = buf.len();
+            let mut total_read = 0;
+
+            buf.reserve_additional(len);
+            vec::raw::set_len(buf, start_len + len);
+
+            do (|| {
+                while total_read < len {
+                    let len = buf.len();
+                    let slice = buf.mut_slice(start_len + total_read, len);
+                    match self.read(slice) {
+                        Some(nread) => {
+                            total_read += nread;
+                        }
+                        None => {
+                            io_error::cond.raise(standard_error(EndOfFile));
+                            break;
+                        }
+                    }
+                }
+            }).finally {
+                vec::raw::set_len(buf, start_len + total_read);
+            }
+        }
+    }
+
+    /// Reads `len` bytes and gives you back a new vector of length `len`
+    ///
+    /// # Failure
+    ///
+    /// Raises the same conditions as `read`. Additionally raises `io_error`
+    /// on EOF. If `io_error` is handled then the returned vector may
+    /// contain less than the requested number of bytes.
+    fn read_bytes(&mut self, len: uint) -> ~[u8] {
+        let mut buf = vec::with_capacity(len);
+        self.push_bytes(&mut buf, len);
+        return buf;
+    }
+
+    /// Reads all remaining bytes from the stream.
+    ///
+    /// # Failure
+    ///
+    /// Raises the same conditions as the `read` method.
+    fn read_to_end(&mut self) -> ~[u8] {
+        let mut buf = vec::with_capacity(DEFAULT_BUF_SIZE);
+        let mut keep_reading = true;
+        do io_error::cond.trap(|e| {
+            if e.kind == EndOfFile {
+                keep_reading = false;
+            } else {
+                io_error::cond.raise(e)
+            }
+        }).inside {
+            while keep_reading {
+                self.push_bytes(&mut buf, DEFAULT_BUF_SIZE)
+            }
+        }
+        return buf;
+    }
+
+    /// Create an iterator that reads a single byte on
+    /// each iteration, until EOF.
+    ///
+    /// # Failure
+    ///
+    /// Raises the same conditions as the `read` method, for
+    /// each call to its `.next()` method.
+    /// Ends the iteration if the condition is handled.
+    fn bytes(self) -> extensions::ByteIterator<Self> {
+        extensions::ByteIterator::new(self)
+    }
+
+    // Byte conversion helpers
+
+    /// Reads `n` little-endian unsigned integer bytes.
+    ///
+    /// `n` must be between 1 and 8, inclusive.
+    fn read_le_uint_n(&mut self, nbytes: uint) -> u64 {
+        assert!(nbytes > 0 && nbytes <= 8);
+
+        let mut val = 0u64;
+        let mut pos = 0;
+        let mut i = nbytes;
+        while i > 0 {
+            val += (self.read_u8() as u64) << pos;
+            pos += 8;
+            i -= 1;
+        }
+        val
+    }
+
+    /// Reads `n` little-endian signed integer bytes.
+    ///
+    /// `n` must be between 1 and 8, inclusive.
+    fn read_le_int_n(&mut self, nbytes: uint) -> i64 {
+        extend_sign(self.read_le_uint_n(nbytes), nbytes)
+    }
+
+    /// Reads `n` big-endian unsigned integer bytes.
+    ///
+    /// `n` must be between 1 and 8, inclusive.
+    fn read_be_uint_n(&mut self, nbytes: uint) -> u64 {
+        assert!(nbytes > 0 && nbytes <= 8);
+
+        let mut val = 0u64;
+        let mut i = nbytes;
+        while i > 0 {
+            i -= 1;
+            val += (self.read_u8() as u64) << i * 8;
+        }
+        val
+    }
+
+    /// Reads `n` big-endian signed integer bytes.
+    ///
+    /// `n` must be between 1 and 8, inclusive.
+    fn read_be_int_n(&mut self, nbytes: uint) -> i64 {
+        extend_sign(self.read_be_uint_n(nbytes), nbytes)
+    }
+
+    /// Reads a little-endian unsigned integer.
+    ///
+    /// The number of bytes returned is system-dependant.
+    fn read_le_uint(&mut self) -> uint {
+        self.read_le_uint_n(uint::bytes) as uint
+    }
+
+    /// Reads a little-endian integer.
+    ///
+    /// The number of bytes returned is system-dependant.
+    fn read_le_int(&mut self) -> int {
+        self.read_le_int_n(int::bytes) as int
+    }
+
+    /// Reads a big-endian unsigned integer.
+    ///
+    /// The number of bytes returned is system-dependant.
+    fn read_be_uint(&mut self) -> uint {
+        self.read_be_uint_n(uint::bytes) as uint
+    }
+
+    /// Reads a big-endian integer.
+    ///
+    /// The number of bytes returned is system-dependant.
+    fn read_be_int(&mut self) -> int {
+        self.read_be_int_n(int::bytes) as int
+    }
+
+    /// Reads a big-endian `u64`.
+    ///
+    /// `u64`s are 8 bytes long.
+    fn read_be_u64(&mut self) -> u64 {
+        self.read_be_uint_n(8) as u64
+    }
+
+    /// Reads a big-endian `u32`.
+    ///
+    /// `u32`s are 4 bytes long.
+    fn read_be_u32(&mut self) -> u32 {
+        self.read_be_uint_n(4) as u32
+    }
+
+    /// Reads a big-endian `u16`.
+    ///
+    /// `u16`s are 2 bytes long.
+    fn read_be_u16(&mut self) -> u16 {
+        self.read_be_uint_n(2) as u16
+    }
+
+    /// Reads a big-endian `i64`.
+    ///
+    /// `i64`s are 8 bytes long.
+    fn read_be_i64(&mut self) -> i64 {
+        self.read_be_int_n(8) as i64
+    }
+
+    /// Reads a big-endian `i32`.
+    ///
+    /// `i32`s are 4 bytes long.
+    fn read_be_i32(&mut self) -> i32 {
+        self.read_be_int_n(4) as i32
+    }
+
+    /// Reads a big-endian `i16`.
+    ///
+    /// `i16`s are 2 bytes long.
+    fn read_be_i16(&mut self) -> i16 {
+        self.read_be_int_n(2) as i16
+    }
+
+    /// Reads a big-endian `f64`.
+    ///
+    /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
+    fn read_be_f64(&mut self) -> f64 {
+        unsafe {
+            cast::transmute::<u64, f64>(self.read_be_u64())
+        }
+    }
+
+    /// Reads a big-endian `f32`.
+    ///
+    /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
+    fn read_be_f32(&mut self) -> f32 {
+        unsafe {
+            cast::transmute::<u32, f32>(self.read_be_u32())
+        }
+    }
+
+    /// Reads a little-endian `u64`.
+    ///
+    /// `u64`s are 8 bytes long.
+    fn read_le_u64(&mut self) -> u64 {
+        self.read_le_uint_n(8) as u64
+    }
+
+    /// Reads a little-endian `u32`.
+    ///
+    /// `u32`s are 4 bytes long.
+    fn read_le_u32(&mut self) -> u32 {
+        self.read_le_uint_n(4) as u32
+    }
+
+    /// Reads a little-endian `u16`.
+    ///
+    /// `u16`s are 2 bytes long.
+    fn read_le_u16(&mut self) -> u16 {
+        self.read_le_uint_n(2) as u16
+    }
+
+    /// Reads a little-endian `i64`.
+    ///
+    /// `i64`s are 8 bytes long.
+    fn read_le_i64(&mut self) -> i64 {
+        self.read_le_int_n(8) as i64
+    }
+
+    /// Reads a little-endian `i32`.
+    ///
+    /// `i32`s are 4 bytes long.
+    fn read_le_i32(&mut self) -> i32 {
+        self.read_le_int_n(4) as i32
+    }
+
+    /// Reads a little-endian `i16`.
+    ///
+    /// `i16`s are 2 bytes long.
+    fn read_le_i16(&mut self) -> i16 {
+        self.read_le_int_n(2) as i16
+    }
+
+    /// Reads a little-endian `f64`.
+    ///
+    /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
+    fn read_le_f64(&mut self) -> f64 {
+        unsafe {
+            cast::transmute::<u64, f64>(self.read_le_u64())
+        }
+    }
+
+    /// Reads a little-endian `f32`.
+    ///
+    /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
+    fn read_le_f32(&mut self) -> f32 {
+        unsafe {
+            cast::transmute::<u32, f32>(self.read_le_u32())
+        }
+    }
+
+    /// Read a u8.
+    ///
+    /// `u8`s are 1 byte.
+    fn read_u8(&mut self) -> u8 {
+        match self.read_byte() {
+            Some(b) => b as u8,
+            None => 0
+        }
+    }
+
+    /// Read an i8.
+    ///
+    /// `i8`s are 1 byte.
+    fn read_i8(&mut self) -> i8 {
+        match self.read_byte() {
+            Some(b) => b as i8,
+            None => 0
+        }
+    }
+
+}
+
+impl Reader for ~Reader {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.read(buf) }
+    fn eof(&mut self) -> bool { self.eof() }
+}
+
+impl<'self> Reader for &'self mut Reader {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.read(buf) }
+    fn eof(&mut self) -> bool { self.eof() }
+}
+
+fn extend_sign(val: u64, nbytes: uint) -> i64 {
+    let shift = (8 - nbytes) * 8;
+    (val << shift) as i64 >> shift
+}
+
+pub trait Writer {
+    /// Write the given buffer
+    ///
+    /// # Failure
+    ///
+    /// Raises the `io_error` condition on error
+    fn write(&mut self, buf: &[u8]);
+
+    /// Flush this output stream, ensuring that all intermediately buffered
+    /// contents reach their destination.
+    ///
+    /// This is by default a no-op and implementors of the `Writer` trait should
+    /// decide whether their stream needs to be buffered or not.
+    fn flush(&mut self) {}
+
+    /// Write the result of passing n through `int::to_str_bytes`.
+    fn write_int(&mut self, n: int) {
+        int::to_str_bytes(n, 10u, |bytes| self.write(bytes))
+    }
+
+    /// Write the result of passing n through `uint::to_str_bytes`.
+    fn write_uint(&mut self, n: uint) {
+        uint::to_str_bytes(n, 10u, |bytes| self.write(bytes))
+    }
+
+    /// Write a little-endian uint (number of bytes depends on system).
+    fn write_le_uint(&mut self, n: uint) {
+        extensions::u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v))
+    }
+
+    /// Write a little-endian int (number of bytes depends on system).
+    fn write_le_int(&mut self, n: int) {
+        extensions::u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v))
+    }
+
+    /// Write a big-endian uint (number of bytes depends on system).
+    fn write_be_uint(&mut self, n: uint) {
+        extensions::u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v))
+    }
+
+    /// Write a big-endian int (number of bytes depends on system).
+    fn write_be_int(&mut self, n: int) {
+        extensions::u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v))
+    }
+
+    /// Write a big-endian u64 (8 bytes).
+    fn write_be_u64(&mut self, n: u64) {
+        extensions::u64_to_be_bytes(n, 8u, |v| self.write(v))
+    }
+
+    /// Write a big-endian u32 (4 bytes).
+    fn write_be_u32(&mut self, n: u32) {
+        extensions::u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
+    }
+
+    /// Write a big-endian u16 (2 bytes).
+    fn write_be_u16(&mut self, n: u16) {
+        extensions::u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
+    }
+
+    /// Write a big-endian i64 (8 bytes).
+    fn write_be_i64(&mut self, n: i64) {
+        extensions::u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
+    }
+
+    /// Write a big-endian i32 (4 bytes).
+    fn write_be_i32(&mut self, n: i32) {
+        extensions::u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
+    }
+
+    /// Write a big-endian i16 (2 bytes).
+    fn write_be_i16(&mut self, n: i16) {
+        extensions::u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
+    }
+
+    /// Write a big-endian IEEE754 double-precision floating-point (8 bytes).
+    fn write_be_f64(&mut self, f: f64) {
+        unsafe {
+            self.write_be_u64(cast::transmute(f))
+        }
+    }
+
+    /// Write a big-endian IEEE754 single-precision floating-point (4 bytes).
+    fn write_be_f32(&mut self, f: f32) {
+        unsafe {
+            self.write_be_u32(cast::transmute(f))
+        }
+    }
+
+    /// Write a little-endian u64 (8 bytes).
+    fn write_le_u64(&mut self, n: u64) {
+        extensions::u64_to_le_bytes(n, 8u, |v| self.write(v))
+    }
+
+    /// Write a little-endian u32 (4 bytes).
+    fn write_le_u32(&mut self, n: u32) {
+        extensions::u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
+    }
+
+    /// Write a little-endian u16 (2 bytes).
+    fn write_le_u16(&mut self, n: u16) {
+        extensions::u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
+    }
+
+    /// Write a little-endian i64 (8 bytes).
+    fn write_le_i64(&mut self, n: i64) {
+        extensions::u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
+    }
+
+    /// Write a little-endian i32 (4 bytes).
+    fn write_le_i32(&mut self, n: i32) {
+        extensions::u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
+    }
+
+    /// Write a little-endian i16 (2 bytes).
+    fn write_le_i16(&mut self, n: i16) {
+        extensions::u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
+    }
+
+    /// Write a little-endian IEEE754 double-precision floating-point
+    /// (8 bytes).
+    fn write_le_f64(&mut self, f: f64) {
+        unsafe {
+            self.write_le_u64(cast::transmute(f))
+        }
+    }
+
+    /// Write a little-endian IEEE754 single-precision floating-point
+    /// (4 bytes).
+    fn write_le_f32(&mut self, f: f32) {
+        unsafe {
+            self.write_le_u32(cast::transmute(f))
+        }
+    }
+
+    /// Write a u8 (1 byte).
+    fn write_u8(&mut self, n: u8) {
+        self.write([n])
+    }
+
+    /// Write a i8 (1 byte).
+    fn write_i8(&mut self, n: i8) {
+        self.write([n as u8])
+    }
+}
+
+impl Writer for ~Writer {
+    fn write(&mut self, buf: &[u8]) { self.write(buf) }
+    fn flush(&mut self) { self.flush() }
+}
+
+impl<'self> Writer for &'self mut Writer {
+    fn write(&mut self, buf: &[u8]) { self.write(buf) }
+    fn flush(&mut self) { self.flush() }
+}
+
+pub trait Stream: Reader + Writer { }
+
+impl<T: Reader + Writer> Stream for T {}
+
+pub enum SeekStyle {
+    /// Seek from the beginning of the stream
+    SeekSet,
+    /// Seek from the end of the stream
+    SeekEnd,
+    /// Seek from the current position
+    SeekCur,
+}
+
+/// # XXX
+/// * Are `u64` and `i64` the right choices?
+pub trait Seek {
+    /// Return position of file cursor in the stream
+    fn tell(&self) -> u64;
+
+    /// Seek to an offset in a stream
+    ///
+    /// A successful seek clears the EOF indicator.
+    ///
+    /// # XXX
+    ///
+    /// * What is the behavior when seeking past the end of a stream?
+    fn seek(&mut self, pos: i64, style: SeekStyle);
+}
+
+/// A listener is a value that can consume itself to start listening for connections.
+/// Doing so produces some sort of Acceptor.
+pub trait Listener<T, A: Acceptor<T>> {
+    /// Spin up the listener and start queueing incoming connections
+    ///
+    /// # Failure
+    ///
+    /// Raises `io_error` condition. If the condition is handled,
+    /// then `listen` returns `None`.
+    fn listen(self) -> Option<A>;
+}
+
+/// An acceptor is a value that presents incoming connections
+pub trait Acceptor<T> {
+    /// Wait for and accept an incoming connection
+    ///
+    /// # Failure
+    /// Raise `io_error` condition. If the condition is handled,
+    /// then `accept` returns `None`.
+    fn accept(&mut self) -> Option<T>;
+
+    /// Create an iterator over incoming connection attempts
+    fn incoming<'r>(&'r mut self) -> IncomingIterator<'r, Self> {
+        IncomingIterator { inc: self }
+    }
+}
+
+/// An infinite iterator over incoming connection attempts.
+/// Calling `next` will block the task until a connection is attempted.
+///
+/// Since connection attempts can continue forever, this iterator always returns Some.
+/// The Some contains another Option representing whether the connection attempt was succesful.
+/// A successful connection will be wrapped in Some.
+/// A failed connection is represented as a None and raises a condition.
+struct IncomingIterator<'self, A> {
+    priv inc: &'self mut A,
+}
+
+impl<'self, T, A: Acceptor<T>> Iterator<Option<T>> for IncomingIterator<'self, A> {
+    fn next(&mut self) -> Option<Option<T>> {
+        Some(self.inc.accept())
+    }
+}
+
+/// Common trait for decorator types.
+///
+/// Provides accessors to get the inner, 'decorated' values. The I/O library
+/// uses decorators to add functionality like compression and encryption to I/O
+/// streams.
+///
+/// # XXX
+///
+/// Is this worth having a trait for? May be overkill
+pub trait Decorator<T> {
+    /// Destroy the decorator and extract the decorated value
+    ///
+    /// # XXX
+    ///
+    /// Because this takes `self' one could never 'undecorate' a Reader/Writer
+    /// that has been boxed. Is that ok? This feature is mostly useful for
+    /// extracting the buffer from MemWriter
+    fn inner(self) -> T;
+
+    /// Take an immutable reference to the decorated value
+    fn inner_ref<'a>(&'a self) -> &'a T;
+
+    /// Take a mutable reference to the decorated value
+    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut T;
+}
+
+pub fn standard_error(kind: IoErrorKind) -> IoError {
+    match kind {
+        PreviousIoError => {
+            IoError {
+                kind: PreviousIoError,
+                desc: "Failing due to a previous I/O error",
+                detail: None
+            }
+        }
+        EndOfFile => {
+            IoError {
+                kind: EndOfFile,
+                desc: "End of file",
+                detail: None
+            }
+        }
+        IoUnavailable => {
+            IoError {
+                kind: IoUnavailable,
+                desc: "I/O is unavailable",
+                detail: None
+            }
+        }
+        _ => fail!()
+    }
+}
+
+pub fn placeholder_error() -> IoError {
+    IoError {
+        kind: OtherIoError,
+        desc: "Placeholder error. You shouldn't be seeing this",
+        detail: None
+    }
+}
+
+/// A mode specifies how a file should be opened or created. These modes are
+/// passed to `File::open_mode` and are used to control where the file is
+/// positioned when it is initially opened.
+pub enum FileMode {
+    /// Opens a file positioned at the beginning.
+    Open,
+    /// Opens a file positioned at EOF.
+    Append,
+    /// Opens a file, truncating it if it already exists.
+    Truncate,
+}
+
+/// Access permissions with which the file should be opened. `File`s
+/// opened with `Read` will raise an `io_error` condition if written to.
+pub enum FileAccess {
+    Read,
+    Write,
+    ReadWrite,
+}
+
+/// Different kinds of files which can be identified by a call to stat
+#[deriving(Eq)]
+pub enum FileType {
+    TypeFile,
+    TypeDirectory,
+    TypeNamedPipe,
+    TypeBlockSpecial,
+    TypeSymlink,
+    TypeUnknown,
+}
+
+pub struct FileStat {
+    /// The path that this stat structure is describing
+    path: Path,
+    /// The size of the file, in bytes
+    size: u64,
+    /// The kind of file this path points to (directory, file, pipe, etc.)
+    kind: FileType,
+    /// The file permissions currently on the file
+    perm: FilePermission,
+
+    // FIXME(#10301): These time fields are pretty useless without an actual
+    //                time representation, what are the milliseconds relative
+    //                to?
+
+    /// The time that the file was created at, in platform-dependent
+    /// milliseconds
+    created: u64,
+    /// The time that this file was last modified, in platform-dependent
+    /// milliseconds
+    modified: u64,
+    /// The time that this file was last accessed, in platform-dependent
+    /// milliseconds
+    accessed: u64,
+
+    /// Information returned by stat() which is not guaranteed to be
+    /// platform-independent. This information may be useful on some platforms,
+    /// but it may have different meanings or no meaning at all on other
+    /// platforms.
+    ///
+    /// Usage of this field is discouraged, but if access is desired then the
+    /// fields are located here.
+    #[unstable]
+    unstable: UnstableFileStat,
+}
+
+/// This structure represents all of the possible information which can be
+/// returned from a `stat` syscall which is not contained in the `FileStat`
+/// structure. This information is not necessarily platform independent, and may
+/// have different meanings or no meaning at all on some platforms.
+#[unstable]
+pub struct UnstableFileStat {
+    device: u64,
+    inode: u64,
+    rdev: u64,
+    nlink: u64,
+    uid: u64,
+    gid: u64,
+    blksize: u64,
+    blocks: u64,
+    flags: u64,
+    gen: u64,
+}
+
+/// A set of permissions for a file or directory is represented by a set of
+/// flags which are or'd together.
+pub type FilePermission = u32;
+
+// Each permission bit
+pub static UserRead: FilePermission     = 0x100;
+pub static UserWrite: FilePermission    = 0x080;
+pub static UserExecute: FilePermission  = 0x040;
+pub static GroupRead: FilePermission    = 0x020;
+pub static GroupWrite: FilePermission   = 0x010;
+pub static GroupExecute: FilePermission = 0x008;
+pub static OtherRead: FilePermission    = 0x004;
+pub static OtherWrite: FilePermission   = 0x002;
+pub static OtherExecute: FilePermission = 0x001;
+
+// Common combinations of these bits
+pub static UserRWX: FilePermission  = UserRead | UserWrite | UserExecute;
+pub static GroupRWX: FilePermission = GroupRead | GroupWrite | GroupExecute;
+pub static OtherRWX: FilePermission = OtherRead | OtherWrite | OtherExecute;
+
+/// A set of permissions for user owned files, this is equivalent to 0644 on
+/// unix-like systems.
+pub static UserFile: FilePermission = UserRead | UserWrite | GroupRead | OtherRead;
+/// A set of permissions for user owned directories, this is equivalent to 0755
+/// on unix-like systems.
+pub static UserDir: FilePermission = UserRWX | GroupRead | GroupExecute |
+                                     OtherRead | OtherExecute;
+/// A set of permissions for user owned executables, this is equivalent to 0755
+/// on unix-like systems.
+pub static UserExec: FilePermission = UserDir;
+
+/// A mask for all possible permission bits
+pub static AllPermissions: FilePermission = 0x1ff;
diff --git a/src/libstd/io/native/file.rs b/src/libstd/io/native/file.rs
new file mode 100644 (file)
index 0000000..0f1a64e
--- /dev/null
@@ -0,0 +1,761 @@
+// 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.
+
+//! Blocking posix-based file I/O
+
+#[allow(non_camel_case_types)];
+
+use libc;
+use os;
+use prelude::*;
+use super::super::*;
+
+#[cfg(windows)]
+fn get_err(errno: i32) -> (IoErrorKind, &'static str) {
+    match errno {
+        libc::EOF => (EndOfFile, "end of file"),
+        _ => (OtherIoError, "unknown error"),
+    }
+}
+
+#[cfg(not(windows))]
+fn get_err(errno: i32) -> (IoErrorKind, &'static str) {
+    // XXX: this should probably be a bit more descriptive...
+    match errno {
+        libc::EOF => (EndOfFile, "end of file"),
+
+        // These two constants can have the same value on some systems, but
+        // different values on others, so we can't use a match clause
+        x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
+            (ResourceUnavailable, "resource temporarily unavailable"),
+
+        _ => (OtherIoError, "unknown error"),
+    }
+}
+
+fn raise_error() {
+    let (kind, desc) = get_err(os::errno() as i32);
+    io_error::cond.raise(IoError {
+        kind: kind,
+        desc: desc,
+        detail: Some(os::last_os_error())
+    });
+}
+
+fn keep_going(data: &[u8], f: &fn(*u8, uint) -> i64) -> i64 {
+    #[cfg(windows)] static eintr: int = 0; // doesn't matter
+    #[cfg(not(windows))] static eintr: int = libc::EINTR as int;
+
+    let (data, origamt) = do data.as_imm_buf |data, amt| { (data, amt) };
+    let mut data = data;
+    let mut amt = origamt;
+    while amt > 0 {
+        let mut ret;
+        loop {
+            ret = f(data, amt);
+            if cfg!(not(windows)) { break } // windows has no eintr
+            // if we get an eintr, then try again
+            if ret != -1 || os::errno() as int != eintr { break }
+        }
+        if ret == 0 {
+            break
+        } else if ret != -1 {
+            amt -= ret as uint;
+            data = unsafe { data.offset(ret as int) };
+        } else {
+            return ret;
+        }
+    }
+    return (origamt - amt) as i64;
+}
+
+pub type fd_t = libc::c_int;
+
+pub struct FileDesc {
+    priv fd: fd_t,
+    priv close_on_drop: bool,
+}
+
+impl FileDesc {
+    /// Create a `FileDesc` from an open C file descriptor.
+    ///
+    /// The `FileDesc` will take ownership of the specified file descriptor and
+    /// close it upon destruction if the `close_on_drop` flag is true, otherwise
+    /// it will not close the file descriptor when this `FileDesc` is dropped.
+    ///
+    /// Note that all I/O operations done on this object will be *blocking*, but
+    /// they do not require the runtime to be active.
+    pub fn new(fd: fd_t, close_on_drop: bool) -> FileDesc {
+        FileDesc { fd: fd, close_on_drop: close_on_drop }
+    }
+}
+
+impl Reader for FileDesc {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        #[cfg(windows)] type rlen = libc::c_uint;
+        #[cfg(not(windows))] type rlen = libc::size_t;
+        let ret = do keep_going(buf) |buf, len| {
+            unsafe {
+                libc::read(self.fd, buf as *mut libc::c_void, len as rlen) as i64
+            }
+        };
+        if ret == 0 {
+            None
+        } else if ret < 0 {
+            raise_error();
+            None
+        } else {
+            Some(ret as uint)
+        }
+    }
+
+    fn eof(&mut self) -> bool { false }
+}
+
+impl Writer for FileDesc {
+    fn write(&mut self, buf: &[u8]) {
+        #[cfg(windows)] type wlen = libc::c_uint;
+        #[cfg(not(windows))] type wlen = libc::size_t;
+        let ret = do keep_going(buf) |buf, len| {
+            unsafe {
+                libc::write(self.fd, buf as *libc::c_void, len as wlen) as i64
+            }
+        };
+        if ret < 0 {
+            raise_error();
+        }
+    }
+}
+
+impl Drop for FileDesc {
+    fn drop(&mut self) {
+        if self.close_on_drop {
+            unsafe { libc::close(self.fd); }
+        }
+    }
+}
+
+pub struct CFile {
+    priv file: *libc::FILE
+}
+
+impl CFile {
+    /// Create a `CFile` from an open `FILE` pointer.
+    ///
+    /// The `CFile` takes ownership of the `FILE` pointer and will close it upon
+    /// destruction.
+    pub fn new(file: *libc::FILE) -> CFile { CFile { file: file } }
+}
+
+impl Reader for CFile {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        let ret = do keep_going(buf) |buf, len| {
+            unsafe {
+                libc::fread(buf as *mut libc::c_void, 1, len as libc::size_t,
+                            self.file) as i64
+            }
+        };
+        if ret == 0 {
+            None
+        } else if ret < 0 {
+            raise_error();
+            None
+        } else {
+            Some(ret as uint)
+        }
+    }
+
+    fn eof(&mut self) -> bool {
+        unsafe { libc::feof(self.file) != 0 }
+    }
+}
+
+impl Writer for CFile {
+    fn write(&mut self, buf: &[u8]) {
+        let ret = do keep_going(buf) |buf, len| {
+            unsafe {
+                libc::fwrite(buf as *libc::c_void, 1, len as libc::size_t,
+                            self.file) as i64
+            }
+        };
+        if ret < 0 {
+            raise_error();
+        }
+    }
+
+    fn flush(&mut self) {
+        if unsafe { libc::fflush(self.file) } < 0 {
+            raise_error();
+        }
+    }
+}
+
+impl Seek for CFile {
+    fn tell(&self) -> u64 {
+        let ret = unsafe { libc::ftell(self.file) };
+        if ret < 0 {
+            raise_error();
+        }
+        return ret as u64;
+    }
+
+    fn seek(&mut self, pos: i64, style: SeekStyle) {
+        let whence = match style {
+            SeekSet => libc::SEEK_SET,
+            SeekEnd => libc::SEEK_END,
+            SeekCur => libc::SEEK_CUR,
+        };
+        if unsafe { libc::fseek(self.file, pos as libc::c_long, whence) } < 0 {
+            raise_error();
+        }
+    }
+}
+
+impl Drop for CFile {
+    fn drop(&mut self) {
+        unsafe { libc::fclose(self.file); }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use libc;
+    use os;
+    use prelude::*;
+    use io::{io_error, SeekSet};
+    use super::*;
+
+    #[ignore(cfg(target_os = "freebsd"))] // hmm, maybe pipes have a tiny buffer
+    fn test_file_desc() {
+        // Run this test with some pipes so we don't have to mess around with
+        // opening or closing files.
+        unsafe {
+            let os::Pipe { input, out } = os::pipe();
+            let mut reader = FileDesc::new(input, true);
+            let mut writer = FileDesc::new(out, true);
+
+            writer.write(bytes!("test"));
+            let mut buf = [0u8, ..4];
+            match reader.read(buf) {
+                Some(4) => {
+                    assert_eq!(buf[0], 't' as u8);
+                    assert_eq!(buf[1], 'e' as u8);
+                    assert_eq!(buf[2], 's' as u8);
+                    assert_eq!(buf[3], 't' as u8);
+                }
+                r => fail!("invalid read: {:?}", r)
+            }
+
+            let mut raised = false;
+            do io_error::cond.trap(|_| { raised = true; }).inside {
+                writer.read(buf);
+            }
+            assert!(raised);
+
+            raised = false;
+            do io_error::cond.trap(|_| { raised = true; }).inside {
+                reader.write(buf);
+            }
+            assert!(raised);
+        }
+    }
+
+    #[ignore(cfg(windows))] // apparently windows doesn't like tmpfile
+    fn test_cfile() {
+        unsafe {
+            let f = libc::tmpfile();
+            assert!(!f.is_null());
+            let mut file = CFile::new(f);
+
+            file.write(bytes!("test"));
+            let mut buf = [0u8, ..4];
+            file.seek(0, SeekSet);
+            match file.read(buf) {
+                Some(4) => {
+                    assert_eq!(buf[0], 't' as u8);
+                    assert_eq!(buf[1], 'e' as u8);
+                    assert_eq!(buf[2], 's' as u8);
+                    assert_eq!(buf[3], 't' as u8);
+                }
+                r => fail!("invalid read: {:?}", r)
+            }
+        }
+    }
+}
+
+// n.b. these functions were all part of the old `std::os` module. There's lots
+//      of fun little nuances that were taken care of by these functions, but
+//      they are all thread-blocking versions that are no longer desired (we now
+//      use a non-blocking event loop implementation backed by libuv).
+//
+//      In theory we will have a thread-blocking version of the event loop (if
+//      desired), so these functions may just need to get adapted to work in
+//      those situtations. For now, I'm leaving the code around so it doesn't
+//      get bitrotted instantaneously.
+mod old_os {
+    use prelude::*;
+    use libc::{size_t, c_void, c_int};
+    use libc;
+    use vec;
+
+    #[cfg(not(windows))] use c_str::CString;
+    #[cfg(not(windows))] use libc::fclose;
+    #[cfg(test)] #[cfg(windows)] use os;
+    #[cfg(test)] use rand;
+    #[cfg(windows)] use str;
+    #[cfg(windows)] use ptr;
+
+    // On Windows, wide character version of function must be used to support
+    // unicode, so functions should be split into at least two versions,
+    // which are for Windows and for non-Windows, if necessary.
+    // See https://github.com/mozilla/rust/issues/9822 for more information.
+
+    mod rustrt {
+        use libc::{c_char, c_int};
+        use libc;
+
+        extern {
+            pub fn rust_path_is_dir(path: *libc::c_char) -> c_int;
+            pub fn rust_path_exists(path: *libc::c_char) -> c_int;
+        }
+
+        // Uses _wstat instead of stat.
+        #[cfg(windows)]
+        extern {
+            pub fn rust_path_is_dir_u16(path: *u16) -> c_int;
+            pub fn rust_path_exists_u16(path: *u16) -> c_int;
+        }
+    }
+
+    /// Recursively walk a directory structure
+    pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool {
+        let r = list_dir(p);
+        r.iter().advance(|q| {
+            let path = &p.join(q);
+            f(path) && (!path_is_dir(path) || walk_dir(path, |p| f(p)))
+        })
+    }
+
+    #[cfg(unix)]
+    /// Indicates whether a path represents a directory
+    pub fn path_is_dir(p: &Path) -> bool {
+        unsafe {
+            do p.with_c_str |buf| {
+                rustrt::rust_path_is_dir(buf) != 0 as c_int
+            }
+        }
+    }
+
+
+    #[cfg(windows)]
+    pub fn path_is_dir(p: &Path) -> bool {
+        unsafe {
+            do os::win32::as_utf16_p(p.as_str().unwrap()) |buf| {
+                rustrt::rust_path_is_dir_u16(buf) != 0 as c_int
+            }
+        }
+    }
+
+    #[cfg(unix)]
+    /// Indicates whether a path exists
+    pub fn path_exists(p: &Path) -> bool {
+        unsafe {
+            do p.with_c_str |buf| {
+                rustrt::rust_path_exists(buf) != 0 as c_int
+            }
+        }
+    }
+
+    #[cfg(windows)]
+    pub fn path_exists(p: &Path) -> bool {
+        unsafe {
+            do os::win32::as_utf16_p(p.as_str().unwrap()) |buf| {
+                rustrt::rust_path_exists_u16(buf) != 0 as c_int
+            }
+        }
+    }
+
+    /// Creates a directory at the specified path
+    pub fn make_dir(p: &Path, mode: c_int) -> bool {
+        return mkdir(p, mode);
+
+        #[cfg(windows)]
+        fn mkdir(p: &Path, _mode: c_int) -> bool {
+            unsafe {
+                use os::win32::as_utf16_p;
+                // FIXME: turn mode into something useful? #2623
+                do as_utf16_p(p.as_str().unwrap()) |buf| {
+                    libc::CreateDirectoryW(buf, ptr::mut_null())
+                        != (0 as libc::BOOL)
+                }
+            }
+        }
+
+        #[cfg(unix)]
+        fn mkdir(p: &Path, mode: c_int) -> bool {
+            do p.with_c_str |buf| {
+                unsafe {
+                    libc::mkdir(buf, mode as libc::mode_t) == (0 as c_int)
+                }
+            }
+        }
+    }
+
+    /// Creates a directory with a given mode.
+    /// Returns true iff creation
+    /// succeeded. Also creates all intermediate subdirectories
+    /// if they don't already exist, giving all of them the same mode.
+
+    // tjc: if directory exists but with different permissions,
+    // should we return false?
+    pub fn mkdir_recursive(p: &Path, mode: c_int) -> bool {
+        if path_is_dir(p) {
+            return true;
+        }
+        if p.filename().is_some() {
+            let mut p_ = p.clone();
+            p_.pop();
+            if !mkdir_recursive(&p_, mode) {
+                return false;
+            }
+        }
+        return make_dir(p, mode);
+    }
+
+    /// Lists the contents of a directory
+    ///
+    /// Each resulting Path is a relative path with no directory component.
+    pub fn list_dir(p: &Path) -> ~[Path] {
+        unsafe {
+            #[cfg(target_os = "linux")]
+            #[cfg(target_os = "android")]
+            #[cfg(target_os = "freebsd")]
+            #[cfg(target_os = "macos")]
+            unsafe fn get_list(p: &Path) -> ~[Path] {
+                use libc::{dirent_t};
+                use libc::{opendir, readdir, closedir};
+                extern {
+                    fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char;
+                }
+                let mut paths = ~[];
+                debug!("os::list_dir -- BEFORE OPENDIR");
+
+                let dir_ptr = do p.with_c_str |buf| {
+                    opendir(buf)
+                };
+
+                if (dir_ptr as uint != 0) {
+                    debug!("os::list_dir -- opendir() SUCCESS");
+                    let mut entry_ptr = readdir(dir_ptr);
+                    while (entry_ptr as uint != 0) {
+                        let cstr = CString::new(rust_list_dir_val(entry_ptr), false);
+                        paths.push(Path::new(cstr));
+                        entry_ptr = readdir(dir_ptr);
+                    }
+                    closedir(dir_ptr);
+                }
+                else {
+                    debug!("os::list_dir -- opendir() FAILURE");
+                }
+                debug!("os::list_dir -- AFTER -- \\#: {}", paths.len());
+                paths
+            }
+            #[cfg(windows)]
+            unsafe fn get_list(p: &Path) -> ~[Path] {
+                use libc::consts::os::extra::INVALID_HANDLE_VALUE;
+                use libc::{wcslen, free};
+                use libc::funcs::extra::kernel32::{
+                    FindFirstFileW,
+                    FindNextFileW,
+                    FindClose,
+                };
+                use libc::types::os::arch::extra::HANDLE;
+                use os::win32::{
+                    as_utf16_p
+                };
+                use rt::global_heap::malloc_raw;
+
+                #[nolink]
+                extern {
+                    fn rust_list_dir_wfd_size() -> libc::size_t;
+                    fn rust_list_dir_wfd_fp_buf(wfd: *libc::c_void) -> *u16;
+                }
+                let star = p.join("*");
+                do as_utf16_p(star.as_str().unwrap()) |path_ptr| {
+                    let mut paths = ~[];
+                    let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
+                    let find_handle = FindFirstFileW(path_ptr, wfd_ptr as HANDLE);
+                    if find_handle as libc::c_int != INVALID_HANDLE_VALUE {
+                        let mut more_files = 1 as libc::c_int;
+                        while more_files != 0 {
+                            let fp_buf = rust_list_dir_wfd_fp_buf(wfd_ptr);
+                            if fp_buf as uint == 0 {
+                                fail!("os::list_dir() failure: got null ptr from wfd");
+                            }
+                            else {
+                                let fp_vec = vec::from_buf(
+                                    fp_buf, wcslen(fp_buf) as uint);
+                                let fp_str = str::from_utf16(fp_vec);
+                                paths.push(Path::new(fp_str));
+                            }
+                            more_files = FindNextFileW(find_handle, wfd_ptr as HANDLE);
+                        }
+                        FindClose(find_handle);
+                        free(wfd_ptr)
+                    }
+                    paths
+                }
+            }
+            do get_list(p).move_iter().filter |path| {
+                path.as_vec() != bytes!(".") && path.as_vec() != bytes!("..")
+            }.collect()
+        }
+    }
+
+    /// Removes a directory at the specified path, after removing
+    /// all its contents. Use carefully!
+    pub fn remove_dir_recursive(p: &Path) -> bool {
+        let mut error_happened = false;
+        do walk_dir(p) |inner| {
+            if !error_happened {
+                if path_is_dir(inner) {
+                    if !remove_dir_recursive(inner) {
+                        error_happened = true;
+                    }
+                }
+                else {
+                    if !remove_file(inner) {
+                        error_happened = true;
+                    }
+                }
+            }
+            true
+        };
+        // Directory should now be empty
+        !error_happened && remove_dir(p)
+    }
+
+    /// Removes a directory at the specified path
+    pub fn remove_dir(p: &Path) -> bool {
+       return rmdir(p);
+
+        #[cfg(windows)]
+        fn rmdir(p: &Path) -> bool {
+            unsafe {
+                use os::win32::as_utf16_p;
+                return do as_utf16_p(p.as_str().unwrap()) |buf| {
+                    libc::RemoveDirectoryW(buf) != (0 as libc::BOOL)
+                };
+            }
+        }
+
+        #[cfg(unix)]
+        fn rmdir(p: &Path) -> bool {
+            do p.with_c_str |buf| {
+                unsafe {
+                    libc::rmdir(buf) == (0 as c_int)
+                }
+            }
+        }
+    }
+
+    /// Deletes an existing file
+    pub fn remove_file(p: &Path) -> bool {
+        return unlink(p);
+
+        #[cfg(windows)]
+        fn unlink(p: &Path) -> bool {
+            unsafe {
+                use os::win32::as_utf16_p;
+                return do as_utf16_p(p.as_str().unwrap()) |buf| {
+                    libc::DeleteFileW(buf) != (0 as libc::BOOL)
+                };
+            }
+        }
+
+        #[cfg(unix)]
+        fn unlink(p: &Path) -> bool {
+            unsafe {
+                do p.with_c_str |buf| {
+                    libc::unlink(buf) == (0 as c_int)
+                }
+            }
+        }
+    }
+
+    /// Renames an existing file or directory
+    pub fn rename_file(old: &Path, new: &Path) -> bool {
+        unsafe {
+           do old.with_c_str |old_buf| {
+                do new.with_c_str |new_buf| {
+                    libc::rename(old_buf, new_buf) == (0 as c_int)
+                }
+           }
+        }
+    }
+
+    /// Copies a file from one location to another
+    pub fn copy_file(from: &Path, to: &Path) -> bool {
+        return do_copy_file(from, to);
+
+        #[cfg(windows)]
+        fn do_copy_file(from: &Path, to: &Path) -> bool {
+            unsafe {
+                use os::win32::as_utf16_p;
+                return do as_utf16_p(from.as_str().unwrap()) |fromp| {
+                    do as_utf16_p(to.as_str().unwrap()) |top| {
+                        libc::CopyFileW(fromp, top, (0 as libc::BOOL)) !=
+                            (0 as libc::BOOL)
+                    }
+                }
+            }
+        }
+
+        #[cfg(unix)]
+        fn do_copy_file(from: &Path, to: &Path) -> bool {
+            unsafe {
+                let istream = do from.with_c_str |fromp| {
+                    do "rb".with_c_str |modebuf| {
+                        libc::fopen(fromp, modebuf)
+                    }
+                };
+                if istream as uint == 0u {
+                    return false;
+                }
+                // Preserve permissions
+                let from_mode = from.stat().perm;
+
+                let ostream = do to.with_c_str |top| {
+                    do "w+b".with_c_str |modebuf| {
+                        libc::fopen(top, modebuf)
+                    }
+                };
+                if ostream as uint == 0u {
+                    fclose(istream);
+                    return false;
+                }
+                let bufsize = 8192u;
+                let mut buf = vec::with_capacity::<u8>(bufsize);
+                let mut done = false;
+                let mut ok = true;
+                while !done {
+                    do buf.as_mut_buf |b, _sz| {
+                      let nread = libc::fread(b as *mut c_void, 1u as size_t,
+                                              bufsize as size_t,
+                                              istream);
+                      if nread > 0 as size_t {
+                          if libc::fwrite(b as *c_void, 1u as size_t, nread,
+                                          ostream) != nread {
+                              ok = false;
+                              done = true;
+                          }
+                      } else {
+                          done = true;
+                      }
+                  }
+                }
+                fclose(istream);
+                fclose(ostream);
+
+                // Give the new file the old file's permissions
+                if do to.with_c_str |to_buf| {
+                    libc::chmod(to_buf, from_mode as libc::mode_t)
+                } != 0 {
+                    return false; // should be a condition...
+                }
+                return ok;
+            }
+        }
+    }
+
+    #[test]
+    fn tmpdir() {
+        let p = os::tmpdir();
+        let s = p.as_str();
+        assert!(s.is_some() && s.unwrap() != ".");
+    }
+
+    // Issue #712
+    #[test]
+    fn test_list_dir_no_invalid_memory_access() {
+        list_dir(&Path::new("."));
+    }
+
+    #[test]
+    fn test_list_dir() {
+        let dirs = list_dir(&Path::new("."));
+        // Just assuming that we've got some contents in the current directory
+        assert!(dirs.len() > 0u);
+
+        for dir in dirs.iter() {
+            debug!("{:?}", (*dir).clone());
+        }
+    }
+
+    #[test]
+    #[cfg(not(windows))]
+    fn test_list_dir_root() {
+        let dirs = list_dir(&Path::new("/"));
+        assert!(dirs.len() > 1);
+    }
+    #[test]
+    #[cfg(windows)]
+    fn test_list_dir_root() {
+        let dirs = list_dir(&Path::new("C:\\"));
+        assert!(dirs.len() > 1);
+    }
+
+    #[test]
+    fn test_path_is_dir() {
+        use io::fs::{mkdir_recursive};
+        use io::{File, UserRWX};
+
+        assert!((path_is_dir(&Path::new("."))));
+        assert!((!path_is_dir(&Path::new("test/stdtest/fs.rs"))));
+
+        let mut dirpath = os::tmpdir();
+        dirpath.push(format!("rust-test-{}/test-\uac00\u4e00\u30fc\u4f60\u597d",
+            rand::random::<u32>())); // 가一ー你好
+        debug!("path_is_dir dirpath: {}", dirpath.display());
+
+        mkdir_recursive(&dirpath, UserRWX);
+
+        assert!((path_is_dir(&dirpath)));
+
+        let mut filepath = dirpath;
+        filepath.push("unicode-file-\uac00\u4e00\u30fc\u4f60\u597d.rs");
+        debug!("path_is_dir filepath: {}", filepath.display());
+
+        File::create(&filepath); // ignore return; touch only
+        assert!((!path_is_dir(&filepath)));
+
+        assert!((!path_is_dir(&Path::new(
+                     "test/unicode-bogus-dir-\uac00\u4e00\u30fc\u4f60\u597d"))));
+    }
+
+    #[test]
+    fn test_path_exists() {
+        use io::fs::mkdir_recursive;
+        use io::UserRWX;
+
+        assert!((path_exists(&Path::new("."))));
+        assert!((!path_exists(&Path::new(
+                     "test/nonexistent-bogus-path"))));
+
+        let mut dirpath = os::tmpdir();
+        dirpath.push(format!("rust-test-{}/test-\uac01\u4e01\u30fc\u518d\u89c1",
+            rand::random::<u32>())); // 각丁ー再见
+
+        mkdir_recursive(&dirpath, UserRWX);
+        assert!((path_exists(&dirpath)));
+        assert!((!path_exists(&Path::new(
+                     "test/unicode-bogus-path-\uac01\u4e01\u30fc\u518d\u89c1"))));
+    }
+}
diff --git a/src/libstd/io/native/process.rs b/src/libstd/io/native/process.rs
new file mode 100644 (file)
index 0000000..de03ac1
--- /dev/null
@@ -0,0 +1,734 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use cast;
+use libc::{pid_t, c_void, c_int};
+use libc;
+use os;
+use prelude::*;
+use ptr;
+use io;
+use super::file;
+
+/**
+ * A value representing a child process.
+ *
+ * The lifetime of this value is linked to the lifetime of the actual
+ * process - the Process destructor calls self.finish() which waits
+ * for the process to terminate.
+ */
+pub struct Process {
+    /// The unique id of the process (this should never be negative).
+    priv pid: pid_t,
+
+    /// A handle to the process - on unix this will always be NULL, but on
+    /// windows it will be a HANDLE to the process, which will prevent the
+    /// pid being re-used until the handle is closed.
+    priv handle: *(),
+
+    /// Currently known stdin of the child, if any
+    priv input: Option<file::FileDesc>,
+    /// Currently known stdout of the child, if any
+    priv output: Option<file::FileDesc>,
+    /// Currently known stderr of the child, if any
+    priv error: Option<file::FileDesc>,
+
+    /// None until finish() is called.
+    priv exit_code: Option<int>,
+}
+
+impl Process {
+    /// Creates a new process using native process-spawning abilities provided
+    /// by the OS. Operations on this process will be blocking instead of using
+    /// the runtime for sleeping just this current task.
+    ///
+    /// # Arguments
+    ///
+    /// * prog - the program to run
+    /// * args - the arguments to pass to the program, not including the program
+    ///          itself
+    /// * env - an optional envrionment to specify for the child process. If
+    ///         this value is `None`, then the child will inherit the parent's
+    ///         environment
+    /// * cwd - an optionally specified current working directory of the child,
+    ///         defaulting to the parent's current working directory
+    /// * stdin, stdout, stderr - These optionally specified file descriptors
+    ///     dictate where the stdin/out/err of the child process will go. If
+    ///     these are `None`, then this module will bind the input/output to an
+    ///     os pipe instead. This process takes ownership of these file
+    ///     descriptors, closing them upon destruction of the process.
+    pub fn new(prog: &str, args: &[~str], env: Option<~[(~str, ~str)]>,
+               cwd: Option<&Path>,
+               stdin: Option<file::fd_t>,
+               stdout: Option<file::fd_t>,
+               stderr: Option<file::fd_t>) -> Process {
+        let (in_pipe, in_fd) = match stdin {
+            None => {
+                let pipe = os::pipe();
+                (Some(pipe), pipe.input)
+            },
+            Some(fd) => (None, fd)
+        };
+        let (out_pipe, out_fd) = match stdout {
+            None => {
+                let pipe = os::pipe();
+                (Some(pipe), pipe.out)
+            },
+            Some(fd) => (None, fd)
+        };
+        let (err_pipe, err_fd) = match stderr {
+            None => {
+                let pipe = os::pipe();
+                (Some(pipe), pipe.out)
+            },
+            Some(fd) => (None, fd)
+        };
+
+        let res = spawn_process_os(prog, args, env, cwd,
+                                   in_fd, out_fd, err_fd);
+
+        unsafe {
+            for pipe in in_pipe.iter() { libc::close(pipe.input); }
+            for pipe in out_pipe.iter() { libc::close(pipe.out); }
+            for pipe in err_pipe.iter() { libc::close(pipe.out); }
+        }
+
+        Process {
+            pid: res.pid,
+            handle: res.handle,
+            input: in_pipe.map(|pipe| file::FileDesc::new(pipe.out, true)),
+            output: out_pipe.map(|pipe| file::FileDesc::new(pipe.input, true)),
+            error: err_pipe.map(|pipe| file::FileDesc::new(pipe.input, true)),
+            exit_code: None,
+        }
+    }
+
+    /// Returns the unique id of the process
+    pub fn id(&self) -> pid_t { self.pid }
+
+    /**
+     * Returns an io::Writer that can be used to write to this Process's stdin.
+     *
+     * Fails if there is no stdinavailable (it's already been removed by
+     * take_input)
+     */
+    pub fn input<'a>(&'a mut self) -> &'a mut io::Writer {
+        match self.input {
+            Some(ref mut fd) => fd as &mut io::Writer,
+            None => fail!("This process has no stdin")
+        }
+    }
+
+    /**
+     * Returns an io::Reader that can be used to read from this Process's
+     * stdout.
+     *
+     * Fails if there is no stdin available (it's already been removed by
+     * take_output)
+     */
+    pub fn output<'a>(&'a mut self) -> &'a mut io::Reader {
+        match self.input {
+            Some(ref mut fd) => fd as &mut io::Reader,
+            None => fail!("This process has no stdout")
+        }
+    }
+
+    /**
+     * Returns an io::Reader that can be used to read from this Process's
+     * stderr.
+     *
+     * Fails if there is no stdin available (it's already been removed by
+     * take_error)
+     */
+    pub fn error<'a>(&'a mut self) -> &'a mut io::Reader {
+        match self.error {
+            Some(ref mut fd) => fd as &mut io::Reader,
+            None => fail!("This process has no stderr")
+        }
+    }
+
+    /**
+     * Takes the stdin of this process, transferring ownership to the caller.
+     * Note that when the return value is destroyed, the handle will be closed
+     * for the child process.
+     */
+    pub fn take_input(&mut self) -> Option<~io::Writer> {
+        self.input.take().map(|fd| ~fd as ~io::Writer)
+    }
+
+    /**
+     * Takes the stdout of this process, transferring ownership to the caller.
+     * Note that when the return value is destroyed, the handle will be closed
+     * for the child process.
+     */
+    pub fn take_output(&mut self) -> Option<~io::Reader> {
+        self.output.take().map(|fd| ~fd as ~io::Reader)
+    }
+
+    /**
+     * Takes the stderr of this process, transferring ownership to the caller.
+     * Note that when the return value is destroyed, the handle will be closed
+     * for the child process.
+     */
+    pub fn take_error(&mut self) -> Option<~io::Reader> {
+        self.error.take().map(|fd| ~fd as ~io::Reader)
+    }
+
+    pub fn wait(&mut self) -> int {
+        for &code in self.exit_code.iter() {
+            return code;
+        }
+        let code = waitpid(self.pid);
+        self.exit_code = Some(code);
+        return code;
+    }
+
+    pub fn signal(&mut self, signum: int) -> Result<(), io::IoError> {
+        // if the process has finished, and therefore had waitpid called,
+        // and we kill it, then on unix we might ending up killing a
+        // newer process that happens to have the same (re-used) id
+        match self.exit_code {
+            Some(*) => return Err(io::IoError {
+                kind: io::OtherIoError,
+                desc: "can't kill an exited process",
+                detail: None,
+            }),
+            None => {}
+        }
+        return unsafe { killpid(self.pid, signum) };
+
+        #[cfg(windows)]
+        unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> {
+            match signal {
+                io::process::PleaseExitSignal |
+                io::process::MustDieSignal => {
+                    libc::funcs::extra::kernel32::TerminateProcess(
+                        cast::transmute(pid), 1);
+                    Ok(())
+                }
+                _ => Err(io::IoError {
+                    kind: io::OtherIoError,
+                    desc: "unsupported signal on windows",
+                    detail: None,
+                })
+            }
+        }
+
+        #[cfg(not(windows))]
+        unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> {
+            libc::funcs::posix88::signal::kill(pid, signal as c_int);
+            Ok(())
+        }
+    }
+}
+
+impl Drop for Process {
+    fn drop(&mut self) {
+        // close all these handles
+        self.take_input();
+        self.take_output();
+        self.take_error();
+        self.wait();
+        free_handle(self.handle);
+    }
+}
+
+struct SpawnProcessResult {
+    pid: pid_t,
+    handle: *(),
+}
+
+#[cfg(windows)]
+fn spawn_process_os(prog: &str, args: &[~str],
+                    env: Option<~[(~str, ~str)]>,
+                    dir: Option<&Path>,
+                    in_fd: c_int, out_fd: c_int, err_fd: c_int) -> SpawnProcessResult {
+    use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO};
+    use libc::consts::os::extra::{
+        TRUE, FALSE,
+        STARTF_USESTDHANDLES,
+        INVALID_HANDLE_VALUE,
+        DUPLICATE_SAME_ACCESS
+    };
+    use libc::funcs::extra::kernel32::{
+        GetCurrentProcess,
+        DuplicateHandle,
+        CloseHandle,
+        CreateProcessA
+    };
+    use libc::funcs::extra::msvcrt::get_osfhandle;
+
+    use mem;
+
+    unsafe {
+
+        let mut si = zeroed_startupinfo();
+        si.cb = mem::size_of::<STARTUPINFO>() as DWORD;
+        si.dwFlags = STARTF_USESTDHANDLES;
+
+        let cur_proc = GetCurrentProcess();
+
+        let orig_std_in = get_osfhandle(in_fd) as HANDLE;
+        if orig_std_in == INVALID_HANDLE_VALUE as HANDLE {
+            fail!("failure in get_osfhandle: {}", os::last_os_error());
+        }
+        if DuplicateHandle(cur_proc, orig_std_in, cur_proc, &mut si.hStdInput,
+                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
+            fail!("failure in DuplicateHandle: {}", os::last_os_error());
+        }
+
+        let orig_std_out = get_osfhandle(out_fd) as HANDLE;
+        if orig_std_out == INVALID_HANDLE_VALUE as HANDLE {
+            fail!("failure in get_osfhandle: {}", os::last_os_error());
+        }
+        if DuplicateHandle(cur_proc, orig_std_out, cur_proc, &mut si.hStdOutput,
+                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
+            fail!("failure in DuplicateHandle: {}", os::last_os_error());
+        }
+
+        let orig_std_err = get_osfhandle(err_fd) as HANDLE;
+        if orig_std_err == INVALID_HANDLE_VALUE as HANDLE {
+            fail!("failure in get_osfhandle: {}", os::last_os_error());
+        }
+        if DuplicateHandle(cur_proc, orig_std_err, cur_proc, &mut si.hStdError,
+                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
+            fail!("failure in DuplicateHandle: {}", os::last_os_error());
+        }
+
+        let cmd = make_command_line(prog, args);
+        let mut pi = zeroed_process_information();
+        let mut create_err = None;
+
+        do with_envp(env) |envp| {
+            do with_dirp(dir) |dirp| {
+                do cmd.with_c_str |cmdp| {
+                    let created = CreateProcessA(ptr::null(), cast::transmute(cmdp),
+                                                 ptr::mut_null(), ptr::mut_null(), TRUE,
+                                                 0, envp, dirp, &mut si, &mut pi);
+                    if created == FALSE {
+                        create_err = Some(os::last_os_error());
+                    }
+                }
+            }
+        }
+
+        CloseHandle(si.hStdInput);
+        CloseHandle(si.hStdOutput);
+        CloseHandle(si.hStdError);
+
+        for msg in create_err.iter() {
+            fail!("failure in CreateProcess: {}", *msg);
+        }
+
+        // We close the thread handle because we don't care about keeping the
+        // thread id valid, and we aren't keeping the thread handle around to be
+        // able to close it later. We don't close the process handle however
+        // because we want the process id to stay valid at least until the
+        // calling code closes the process handle.
+        CloseHandle(pi.hThread);
+
+        SpawnProcessResult {
+            pid: pi.dwProcessId as pid_t,
+            handle: pi.hProcess as *()
+        }
+    }
+}
+
+#[cfg(windows)]
+fn zeroed_startupinfo() -> libc::types::os::arch::extra::STARTUPINFO {
+    libc::types::os::arch::extra::STARTUPINFO {
+        cb: 0,
+        lpReserved: ptr::mut_null(),
+        lpDesktop: ptr::mut_null(),
+        lpTitle: ptr::mut_null(),
+        dwX: 0,
+        dwY: 0,
+        dwXSize: 0,
+        dwYSize: 0,
+        dwXCountChars: 0,
+        dwYCountCharts: 0,
+        dwFillAttribute: 0,
+        dwFlags: 0,
+        wShowWindow: 0,
+        cbReserved2: 0,
+        lpReserved2: ptr::mut_null(),
+        hStdInput: ptr::mut_null(),
+        hStdOutput: ptr::mut_null(),
+        hStdError: ptr::mut_null()
+    }
+}
+
+#[cfg(windows)]
+fn zeroed_process_information() -> libc::types::os::arch::extra::PROCESS_INFORMATION {
+    libc::types::os::arch::extra::PROCESS_INFORMATION {
+        hProcess: ptr::mut_null(),
+        hThread: ptr::mut_null(),
+        dwProcessId: 0,
+        dwThreadId: 0
+    }
+}
+
+// FIXME: this is only pub so it can be tested (see issue #4536)
+#[cfg(windows)]
+pub fn make_command_line(prog: &str, args: &[~str]) -> ~str {
+    let mut cmd = ~"";
+    append_arg(&mut cmd, prog);
+    for arg in args.iter() {
+        cmd.push_char(' ');
+        append_arg(&mut cmd, *arg);
+    }
+    return cmd;
+
+    fn append_arg(cmd: &mut ~str, arg: &str) {
+        let quote = arg.iter().any(|c| c == ' ' || c == '\t');
+        if quote {
+            cmd.push_char('"');
+        }
+        for i in range(0u, arg.len()) {
+            append_char_at(cmd, arg, i);
+        }
+        if quote {
+            cmd.push_char('"');
+        }
+    }
+
+    fn append_char_at(cmd: &mut ~str, arg: &str, i: uint) {
+        match arg[i] as char {
+            '"' => {
+                // Escape quotes.
+                cmd.push_str("\\\"");
+            }
+            '\\' => {
+                if backslash_run_ends_in_quote(arg, i) {
+                    // Double all backslashes that are in runs before quotes.
+                    cmd.push_str("\\\\");
+                } else {
+                    // Pass other backslashes through unescaped.
+                    cmd.push_char('\\');
+                }
+            }
+            c => {
+                cmd.push_char(c);
+            }
+        }
+    }
+
+    fn backslash_run_ends_in_quote(s: &str, mut i: uint) -> bool {
+        while i < s.len() && s[i] as char == '\\' {
+            i += 1;
+        }
+        return i < s.len() && s[i] as char == '"';
+    }
+}
+
+#[cfg(unix)]
+fn spawn_process_os(prog: &str, args: &[~str],
+                    env: Option<~[(~str, ~str)]>,
+                    dir: Option<&Path>,
+                    in_fd: c_int, out_fd: c_int, err_fd: c_int) -> SpawnProcessResult {
+    use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
+    use libc::funcs::bsd44::getdtablesize;
+
+    mod rustrt {
+        #[abi = "cdecl"]
+        extern {
+            pub fn rust_unset_sigprocmask();
+        }
+    }
+
+    #[cfg(windows)]
+    unsafe fn set_environ(_envp: *c_void) {}
+    #[cfg(target_os = "macos")]
+    unsafe fn set_environ(envp: *c_void) {
+        extern { fn _NSGetEnviron() -> *mut *c_void; }
+
+        *_NSGetEnviron() = envp;
+    }
+    #[cfg(not(target_os = "macos"), not(windows))]
+    unsafe fn set_environ(envp: *c_void) {
+        extern {
+            static mut environ: *c_void;
+        }
+        environ = envp;
+    }
+
+    unsafe {
+
+        let pid = fork();
+        if pid < 0 {
+            fail!("failure in fork: {}", os::last_os_error());
+        } else if pid > 0 {
+            return SpawnProcessResult {pid: pid, handle: ptr::null()};
+        }
+
+        rustrt::rust_unset_sigprocmask();
+
+        if dup2(in_fd, 0) == -1 {
+            fail!("failure in dup2(in_fd, 0): {}", os::last_os_error());
+        }
+        if dup2(out_fd, 1) == -1 {
+            fail!("failure in dup2(out_fd, 1): {}", os::last_os_error());
+        }
+        if dup2(err_fd, 2) == -1 {
+            fail!("failure in dup3(err_fd, 2): {}", os::last_os_error());
+        }
+        // close all other fds
+        for fd in range(3, getdtablesize()).invert() {
+            close(fd as c_int);
+        }
+
+        do with_dirp(dir) |dirp| {
+            if !dirp.is_null() && chdir(dirp) == -1 {
+                fail!("failure in chdir: {}", os::last_os_error());
+            }
+        }
+
+        do with_envp(env) |envp| {
+            if !envp.is_null() {
+                set_environ(envp);
+            }
+            do with_argv(prog, args) |argv| {
+                execvp(*argv, argv);
+                // execvp only returns if an error occurred
+                fail!("failure in execvp: {}", os::last_os_error());
+            }
+        }
+    }
+}
+
+#[cfg(unix)]
+fn with_argv<T>(prog: &str, args: &[~str], cb: &fn(**libc::c_char) -> T) -> T {
+    use vec;
+
+    // We can't directly convert `str`s into `*char`s, as someone needs to hold
+    // a reference to the intermediary byte buffers. So first build an array to
+    // hold all the ~[u8] byte strings.
+    let mut tmps = vec::with_capacity(args.len() + 1);
+
+    tmps.push(prog.to_c_str());
+
+    for arg in args.iter() {
+        tmps.push(arg.to_c_str());
+    }
+
+    // Next, convert each of the byte strings into a pointer. This is
+    // technically unsafe as the caller could leak these pointers out of our
+    // scope.
+    let mut ptrs = do tmps.map |tmp| {
+        tmp.with_ref(|buf| buf)
+    };
+
+    // Finally, make sure we add a null pointer.
+    ptrs.push(ptr::null());
+
+    ptrs.as_imm_buf(|buf, _| cb(buf))
+}
+
+#[cfg(unix)]
+fn with_envp<T>(env: Option<~[(~str, ~str)]>, cb: &fn(*c_void) -> T) -> T {
+    use vec;
+
+    // On posixy systems we can pass a char** for envp, which is a
+    // null-terminated array of "k=v\n" strings. Like `with_argv`, we have to
+    // have a temporary buffer to hold the intermediary `~[u8]` byte strings.
+    match env {
+        Some(env) => {
+            let mut tmps = vec::with_capacity(env.len());
+
+            for pair in env.iter() {
+                let kv = format!("{}={}", pair.first(), pair.second());
+                tmps.push(kv.to_c_str());
+            }
+
+            // Once again, this is unsafe.
+            let mut ptrs = do tmps.map |tmp| {
+                tmp.with_ref(|buf| buf)
+            };
+            ptrs.push(ptr::null());
+
+            do ptrs.as_imm_buf |buf, _| {
+                unsafe { cb(cast::transmute(buf)) }
+            }
+        }
+        _ => cb(ptr::null())
+    }
+}
+
+#[cfg(windows)]
+fn with_envp<T>(env: Option<~[(~str, ~str)]>, cb: &fn(*mut c_void) -> T) -> T {
+    // On win32 we pass an "environment block" which is not a char**, but
+    // rather a concatenation of null-terminated k=v\0 sequences, with a final
+    // \0 to terminate.
+    match env {
+        Some(env) => {
+            let mut blk = ~[];
+
+            for pair in env.iter() {
+                let kv = format!("{}={}", pair.first(), pair.second());
+                blk.push_all(kv.as_bytes());
+                blk.push(0);
+            }
+
+            blk.push(0);
+
+            do blk.as_imm_buf |p, _len| {
+                unsafe { cb(cast::transmute(p)) }
+            }
+        }
+        _ => cb(ptr::mut_null())
+    }
+}
+
+fn with_dirp<T>(d: Option<&Path>, cb: &fn(*libc::c_char) -> T) -> T {
+    match d {
+      Some(dir) => dir.with_c_str(|buf| cb(buf)),
+      None => cb(ptr::null())
+    }
+}
+
+#[cfg(windows)]
+fn free_handle(handle: *()) {
+    unsafe {
+        libc::funcs::extra::kernel32::CloseHandle(cast::transmute(handle));
+    }
+}
+
+#[cfg(unix)]
+fn free_handle(_handle: *()) {
+    // unix has no process handle object, just a pid
+}
+
+/**
+ * Waits for a process to exit and returns the exit code, failing
+ * if there is no process with the specified id.
+ *
+ * Note that this is private to avoid race conditions on unix where if
+ * a user calls waitpid(some_process.get_id()) then some_process.finish()
+ * and some_process.destroy() and some_process.finalize() will then either
+ * operate on a none-existent process or, even worse, on a newer process
+ * with the same id.
+ */
+fn waitpid(pid: pid_t) -> int {
+    return waitpid_os(pid);
+
+    #[cfg(windows)]
+    fn waitpid_os(pid: pid_t) -> int {
+        use libc::types::os::arch::extra::DWORD;
+        use libc::consts::os::extra::{
+            SYNCHRONIZE,
+            PROCESS_QUERY_INFORMATION,
+            FALSE,
+            STILL_ACTIVE,
+            INFINITE,
+            WAIT_FAILED
+        };
+        use libc::funcs::extra::kernel32::{
+            OpenProcess,
+            GetExitCodeProcess,
+            CloseHandle,
+            WaitForSingleObject
+        };
+
+        unsafe {
+
+            let process = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
+                                      FALSE,
+                                      pid as DWORD);
+            if process.is_null() {
+                fail!("failure in OpenProcess: {}", os::last_os_error());
+            }
+
+            loop {
+                let mut status = 0;
+                if GetExitCodeProcess(process, &mut status) == FALSE {
+                    CloseHandle(process);
+                    fail!("failure in GetExitCodeProcess: {}", os::last_os_error());
+                }
+                if status != STILL_ACTIVE {
+                    CloseHandle(process);
+                    return status as int;
+                }
+                if WaitForSingleObject(process, INFINITE) == WAIT_FAILED {
+                    CloseHandle(process);
+                    fail!("failure in WaitForSingleObject: {}", os::last_os_error());
+                }
+            }
+        }
+    }
+
+    #[cfg(unix)]
+    fn waitpid_os(pid: pid_t) -> int {
+        use libc::funcs::posix01::wait::*;
+
+        #[cfg(target_os = "linux")]
+        #[cfg(target_os = "android")]
+        fn WIFEXITED(status: i32) -> bool {
+            (status & 0xffi32) == 0i32
+        }
+
+        #[cfg(target_os = "macos")]
+        #[cfg(target_os = "freebsd")]
+        fn WIFEXITED(status: i32) -> bool {
+            (status & 0x7fi32) == 0i32
+        }
+
+        #[cfg(target_os = "linux")]
+        #[cfg(target_os = "android")]
+        fn WEXITSTATUS(status: i32) -> i32 {
+            (status >> 8i32) & 0xffi32
+        }
+
+        #[cfg(target_os = "macos")]
+        #[cfg(target_os = "freebsd")]
+        fn WEXITSTATUS(status: i32) -> i32 {
+            status >> 8i32
+        }
+
+        let mut status = 0 as c_int;
+        if unsafe { waitpid(pid, &mut status, 0) } == -1 {
+            fail!("failure in waitpid: {}", os::last_os_error());
+        }
+
+        return if WIFEXITED(status) {
+            WEXITSTATUS(status) as int
+        } else {
+            1
+        };
+    }
+}
+
+#[cfg(test)]
+mod tests {
+
+    #[test] #[cfg(windows)]
+    fn test_make_command_line() {
+        use super::make_command_line;
+        assert_eq!(
+            make_command_line("prog", [~"aaa", ~"bbb", ~"ccc"]),
+            ~"prog aaa bbb ccc"
+        );
+        assert_eq!(
+            make_command_line("C:\\Program Files\\blah\\blah.exe", [~"aaa"]),
+            ~"\"C:\\Program Files\\blah\\blah.exe\" aaa"
+        );
+        assert_eq!(
+            make_command_line("C:\\Program Files\\test", [~"aa\"bb"]),
+            ~"\"C:\\Program Files\\test\" aa\\\"bb"
+        );
+        assert_eq!(
+            make_command_line("echo", [~"a b c"]),
+            ~"echo \"a b c\""
+        );
+    }
+
+    // Currently most of the tests of this functionality live inside std::run,
+    // but they may move here eventually as a non-blocking backend is added to
+    // std::run
+}
diff --git a/src/libstd/io/native/stdio.rs b/src/libstd/io/native/stdio.rs
new file mode 100644 (file)
index 0000000..68748ab
--- /dev/null
@@ -0,0 +1,63 @@
+// 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.
+
+use libc;
+use option::Option;
+use io::{Reader, Writer};
+use super::file;
+
+/// Creates a new handle to the stdin of this process
+pub fn stdin() -> StdIn { StdIn::new() }
+/// Creates a new handle to the stdout of this process
+pub fn stdout() -> StdOut { StdOut::new(libc::STDOUT_FILENO) }
+/// Creates a new handle to the stderr of this process
+pub fn stderr() -> StdOut { StdOut::new(libc::STDERR_FILENO) }
+
+pub fn print(s: &str) {
+    stdout().write(s.as_bytes())
+}
+
+pub fn println(s: &str) {
+    let mut out = stdout();
+    out.write(s.as_bytes());
+    out.write(['\n' as u8]);
+}
+
+pub struct StdIn {
+    priv fd: file::FileDesc
+}
+
+impl StdIn {
+    /// Duplicates the stdin file descriptor, returning an io::Reader
+    pub fn new() -> StdIn {
+        StdIn { fd: file::FileDesc::new(libc::STDIN_FILENO, false) }
+    }
+}
+
+impl Reader for StdIn {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.fd.read(buf) }
+    fn eof(&mut self) -> bool { self.fd.eof() }
+}
+
+pub struct StdOut {
+    priv fd: file::FileDesc
+}
+
+impl StdOut {
+    /// Duplicates the specified file descriptor, returning an io::Writer
+    pub fn new(fd: file::fd_t) -> StdOut {
+        StdOut { fd: file::FileDesc::new(fd, false) }
+    }
+}
+
+impl Writer for StdOut {
+    fn write(&mut self, buf: &[u8]) { self.fd.write(buf) }
+    fn flush(&mut self) { self.fd.flush() }
+}
diff --git a/src/libstd/io/net/addrinfo.rs b/src/libstd/io/net/addrinfo.rs
new file mode 100644 (file)
index 0000000..7e2d1fc
--- /dev/null
@@ -0,0 +1,128 @@
+// 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.
+
+/*!
+
+Synchronous DNS Resolution
+
+Contains the functionality to perform DNS resolution in a style related to
+getaddrinfo()
+
+*/
+
+use option::{Option, Some, None};
+use result::{Ok, Err};
+use io::{io_error};
+use io::net::ip::{SocketAddr, IpAddr};
+use rt::rtio::{IoFactory, with_local_io};
+use vec::ImmutableVector;
+
+/// Hints to the types of sockets that are desired when looking up hosts
+pub enum SocketType {
+    Stream, Datagram, Raw
+}
+
+/// Flags which can be or'd into the `flags` field of a `Hint`. These are used
+/// to manipulate how a query is performed.
+///
+/// The meaning of each of these flags can be found with `man -s 3 getaddrinfo`
+pub enum Flag {
+    AddrConfig,
+    All,
+    CanonName,
+    NumericHost,
+    NumericServ,
+    Passive,
+    V4Mapped,
+}
+
+/// A transport protocol associated with either a hint or a return value of
+/// `lookup`
+pub enum Protocol {
+    TCP, UDP
+}
+
+/// This structure is used to provide hints when fetching addresses for a
+/// remote host to control how the lookup is performed.
+///
+/// For details on these fields, see their corresponding definitions via
+/// `man -s 3 getaddrinfo`
+pub struct Hint {
+    family: uint,
+    socktype: Option<SocketType>,
+    protocol: Option<Protocol>,
+    flags: uint,
+}
+
+pub struct Info {
+    address: SocketAddr,
+    family: uint,
+    socktype: Option<SocketType>,
+    protocol: Option<Protocol>,
+    flags: uint,
+}
+
+/// Easy name resolution. Given a hostname, returns the list of IP addresses for
+/// that hostname.
+///
+/// # Failure
+///
+/// On failure, this will raise on the `io_error` condition.
+pub fn get_host_addresses(host: &str) -> Option<~[IpAddr]> {
+    lookup(Some(host), None, None).map(|a| a.map(|i| i.address.ip))
+}
+
+/// Full-fleged resolution. This function will perform a synchronous call to
+/// getaddrinfo, controlled by the parameters
+///
+/// # Arguments
+///
+/// * hostname - an optional hostname to lookup against
+/// * servname - an optional service name, listed in the system services
+/// * hint - see the hint structure, and "man -s 3 getaddrinfo", for how this
+///          controls lookup
+///
+/// # Failure
+///
+/// On failure, this will raise on the `io_error` condition.
+///
+/// XXX: this is not public because the `Hint` structure is not ready for public
+///      consumption just yet.
+fn lookup(hostname: Option<&str>, servname: Option<&str>,
+          hint: Option<Hint>) -> Option<~[Info]> {
+    do with_local_io |io| {
+        match io.get_host_addresses(hostname, servname, hint) {
+            Ok(i) => Some(i),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use option::Some;
+    use io::net::ip::Ipv4Addr;
+    use super::*;
+
+    #[test]
+    #[ignore(cfg(target_os="android"))] // cannot give tcp/ip permission without help of apk
+    fn dns_smoke_test() {
+        let ipaddrs = get_host_addresses("localhost").unwrap();
+        let mut found_local = false;
+        let local_addr = &Ipv4Addr(127, 0, 0, 1);
+        for addr in ipaddrs.iter() {
+            found_local = found_local || addr == local_addr;
+        }
+        assert!(found_local);
+    }
+}
diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs
new file mode 100644 (file)
index 0000000..07240a4
--- /dev/null
@@ -0,0 +1,449 @@
+// 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.
+
+use container::Container;
+use from_str::FromStr;
+use option::{Option, None, Some};
+use to_str::ToStr;
+use vec::{MutableCloneableVector, ImmutableVector};
+
+pub type Port = u16;
+
+#[deriving(Eq, TotalEq, Clone)]
+pub enum IpAddr {
+    Ipv4Addr(u8, u8, u8, u8),
+    Ipv6Addr(u16, u16, u16, u16, u16, u16, u16, u16)
+}
+
+impl ToStr for IpAddr {
+    fn to_str(&self) -> ~str {
+        match *self {
+            Ipv4Addr(a, b, c, d) =>
+                format!("{}.{}.{}.{}", a, b, c, d),
+
+            // Ipv4 Compatible address
+            Ipv6Addr(0, 0, 0, 0, 0, 0, g, h) => {
+                format!("::{}.{}.{}.{}", (g >> 8) as u8, g as u8,
+                        (h >> 8) as u8, h as u8)
+            }
+
+            // Ipv4-Mapped address
+            Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, g, h) => {
+                format!("::FFFF:{}.{}.{}.{}", (g >> 8) as u8, g as u8,
+                        (h >> 8) as u8, h as u8)
+            }
+
+            Ipv6Addr(a, b, c, d, e, f, g, h) =>
+                format!("{}:{}:{}:{}:{}:{}:{}:{}", a, b, c, d, e, f, g, h)
+        }
+    }
+}
+
+#[deriving(Eq, TotalEq, Clone)]
+pub struct SocketAddr {
+    ip: IpAddr,
+    port: Port,
+}
+
+
+impl ToStr for SocketAddr {
+    fn to_str(&self) -> ~str {
+        match self.ip {
+            Ipv4Addr(*) => format!("{}:{}", self.ip.to_str(), self.port),
+            Ipv6Addr(*) => format!("[{}]:{}", self.ip.to_str(), self.port),
+        }
+    }
+}
+
+struct Parser<'self> {
+    // parsing as ASCII, so can use byte array
+    s: &'self [u8],
+    pos: uint,
+}
+
+impl<'self> Parser<'self> {
+    fn new(s: &'self str) -> Parser<'self> {
+        Parser {
+            s: s.as_bytes(),
+            pos: 0,
+        }
+    }
+
+    fn is_eof(&self) -> bool {
+        self.pos == self.s.len()
+    }
+
+    // Commit only if parser returns Some
+    fn read_atomically<T>(&mut self, cb: &fn(&mut Parser) -> Option<T>) -> Option<T> {
+        let pos = self.pos;
+        let r = cb(self);
+        if r.is_none() {
+            self.pos = pos;
+        }
+        r
+    }
+
+    // Commit only if parser read till EOF
+    fn read_till_eof<T>(&mut self, cb: &fn(&mut Parser) -> Option<T>) -> Option<T> {
+        do self.read_atomically |p| {
+            cb(p).filtered(|_| p.is_eof())
+        }
+    }
+
+    // Return result of first successful parser
+    fn read_or<T>(&mut self, parsers: &[&fn(&mut Parser) -> Option<T>]) -> Option<T> {
+        for pf in parsers.iter() {
+            match self.read_atomically(|p: &mut Parser| (*pf)(p)) {
+                Some(r) => return Some(r),
+                None => {}
+            }
+        }
+        None
+    }
+
+    // Apply 3 parsers sequentially
+    fn read_seq_3<A, B, C>(&mut self,
+            pa: &fn(&mut Parser) -> Option<A>,
+            pb: &fn(&mut Parser) -> Option<B>,
+            pc: &fn(&mut Parser) -> Option<C>
+        ) -> Option<(A, B, C)>
+    {
+        do self.read_atomically |p| {
+            let a = pa(p);
+            let b = if a.is_some() { pb(p) } else { None };
+            let c = if b.is_some() { pc(p) } else { None };
+            match (a, b, c) {
+                (Some(a), Some(b), Some(c)) => Some((a, b, c)),
+                _ => None
+            }
+        }
+    }
+
+    // Read next char
+    fn read_char(&mut self) -> Option<char> {
+        if self.is_eof() {
+            None
+        } else {
+            let r = self.s[self.pos] as char;
+            self.pos += 1;
+            Some(r)
+        }
+    }
+
+    // Return char and advance iff next char is equal to requested
+    fn read_given_char(&mut self, c: char) -> Option<char> {
+        do self.read_atomically |p| {
+            p.read_char().filtered(|&next| next == c)
+        }
+    }
+
+    // Read digit
+    fn read_digit(&mut self, radix: u8) -> Option<u8> {
+        fn parse_digit(c: char, radix: u8) -> Option<u8> {
+            let c = c as u8;
+            // assuming radix is either 10 or 16
+            if c >= '0' as u8 && c <= '9' as u8 {
+                Some((c - '0' as u8) as u8)
+            } else if radix > 10 && c >= 'a' as u8 && c < 'a' as u8 + (radix - 10) {
+                Some((c - 'a' as u8 + 10) as u8)
+            } else if radix > 10 && c >= 'A' as u8 && c < 'A' as u8 + (radix - 10) {
+                Some((c - 'A' as u8 + 10) as u8)
+            } else {
+                None
+            }
+        }
+
+        do self.read_atomically |p| {
+            p.read_char().and_then(|c| parse_digit(c, radix))
+        }
+    }
+
+    fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
+        let mut r = 0u32;
+        let mut digit_count = 0;
+        loop {
+            match self.read_digit(radix) {
+                Some(d) => {
+                    r = r * (radix as u32) + (d as u32);
+                    digit_count += 1;
+                    if digit_count > max_digits || r >= upto {
+                        return None
+                    }
+                }
+                None => {
+                    if digit_count == 0 {
+                        return None
+                    } else {
+                        return Some(r)
+                    }
+                }
+            };
+        }
+    }
+
+    // Read number, failing if max_digits of number value exceeded
+    fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
+        do self.read_atomically |p| {
+            p.read_number_impl(radix, max_digits, upto)
+        }
+    }
+
+    fn read_ipv4_addr_impl(&mut self) -> Option<IpAddr> {
+        let mut bs = [0u8, ..4];
+        let mut i = 0;
+        while i < 4 {
+            if i != 0 && self.read_given_char('.').is_none() {
+                return None;
+            }
+
+            let octet = self.read_number(10, 3, 0x100).map(|n| n as u8);
+            match octet {
+                Some(d) => bs[i] = d,
+                None => return None,
+            };
+            i += 1;
+        }
+        Some(Ipv4Addr(bs[0], bs[1], bs[2], bs[3]))
+    }
+
+    // Read IPv4 address
+    fn read_ipv4_addr(&mut self) -> Option<IpAddr> {
+        do self.read_atomically |p| {
+            p.read_ipv4_addr_impl()
+        }
+    }
+
+    fn read_ipv6_addr_impl(&mut self) -> Option<IpAddr> {
+        fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> IpAddr {
+            assert!(head.len() + tail.len() <= 8);
+            let mut gs = [0u16, ..8];
+            gs.copy_from(head);
+            gs.mut_slice(8 - tail.len(), 8).copy_from(tail);
+            Ipv6Addr(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
+        }
+
+        fn read_groups(p: &mut Parser, groups: &mut [u16, ..8], limit: uint) -> (uint, bool) {
+            let mut i = 0;
+            while i < limit {
+                if i < limit - 1 {
+                    let ipv4 = do p.read_atomically |p| {
+                        if i == 0 || p.read_given_char(':').is_some() {
+                            p.read_ipv4_addr()
+                        } else {
+                            None
+                        }
+                    };
+                    match ipv4 {
+                        Some(Ipv4Addr(a, b, c, d)) => {
+                            groups[i + 0] = (a as u16 << 8) | (b as u16);
+                            groups[i + 1] = (c as u16 << 8) | (d as u16);
+                            return (i + 2, true);
+                        }
+                        _ => {}
+                    }
+                }
+
+                let group = do p.read_atomically |p| {
+                    if i == 0 || p.read_given_char(':').is_some() {
+                        p.read_number(16, 4, 0x10000).map(|n| n as u16)
+                    } else {
+                        None
+                    }
+                };
+                match group {
+                    Some(g) => groups[i] = g,
+                    None => return (i, false)
+                }
+                i += 1;
+            }
+            (i, false)
+        }
+
+        let mut head = [0u16, ..8];
+        let (head_size, head_ipv4) = read_groups(self, &mut head, 8);
+
+        if head_size == 8 {
+            return Some(Ipv6Addr(
+                head[0], head[1], head[2], head[3],
+                head[4], head[5], head[6], head[7]))
+        }
+
+        // IPv4 part is not allowed before `::`
+        if head_ipv4 {
+            return None
+        }
+
+        // read `::` if previous code parsed less than 8 groups
+        if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
+            return None;
+        }
+
+        let mut tail = [0u16, ..8];
+        let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
+        Some(ipv6_addr_from_head_tail(head.slice(0, head_size), tail.slice(0, tail_size)))
+    }
+
+    fn read_ipv6_addr(&mut self) -> Option<IpAddr> {
+        do self.read_atomically |p| {
+            p.read_ipv6_addr_impl()
+        }
+    }
+
+    fn read_ip_addr(&mut self) -> Option<IpAddr> {
+        let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr();
+        let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr();
+        self.read_or([ipv4_addr, ipv6_addr])
+    }
+
+    fn read_socket_addr(&mut self) -> Option<SocketAddr> {
+        let ip_addr = |p: &mut Parser| {
+            let ipv4_p = |p: &mut Parser| p.read_ip_addr();
+            let ipv6_p = |p: &mut Parser| {
+                let open_br = |p: &mut Parser| p.read_given_char('[');
+                let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
+                let clos_br = |p: &mut Parser| p.read_given_char(']');
+                p.read_seq_3::<char, IpAddr, char>(open_br, ip_addr, clos_br)
+                        .map(|t| match t { (_, ip, _) => ip })
+            };
+            p.read_or([ipv4_p, ipv6_p])
+        };
+        let colon = |p: &mut Parser| p.read_given_char(':');
+        let port  = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16);
+
+        // host, colon, port
+        self.read_seq_3::<IpAddr, char, u16>(ip_addr, colon, port)
+                .map(|t| match t { (ip, _, port) => SocketAddr { ip: ip, port: port } })
+    }
+}
+
+impl FromStr for IpAddr {
+    fn from_str(s: &str) -> Option<IpAddr> {
+        do Parser::new(s).read_till_eof |p| {
+            p.read_ip_addr()
+        }
+    }
+}
+
+impl FromStr for SocketAddr {
+    fn from_str(s: &str) -> Option<SocketAddr> {
+        do Parser::new(s).read_till_eof |p| {
+            p.read_socket_addr()
+        }
+    }
+}
+
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use from_str::FromStr;
+    use option::{Option, Some, None};
+
+    #[test]
+    fn test_from_str_ipv4() {
+        assert_eq!(Some(Ipv4Addr(127, 0, 0, 1)), FromStr::from_str("127.0.0.1"));
+        assert_eq!(Some(Ipv4Addr(255, 255, 255, 255)), FromStr::from_str("255.255.255.255"));
+        assert_eq!(Some(Ipv4Addr(0, 0, 0, 0)), FromStr::from_str("0.0.0.0"));
+
+        // out of range
+        let none: Option<IpAddr> = FromStr::from_str("256.0.0.1");
+        assert_eq!(None, none);
+        // too short
+        let none: Option<IpAddr> = FromStr::from_str("255.0.0");
+        assert_eq!(None, none);
+        // too long
+        let none: Option<IpAddr> = FromStr::from_str("255.0.0.1.2");
+        assert_eq!(None, none);
+        // no number between dots
+        let none: Option<IpAddr> = FromStr::from_str("255.0..1");
+        assert_eq!(None, none);
+    }
+
+    #[test]
+    fn test_from_str_ipv6() {
+        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("0:0:0:0:0:0:0:0"));
+        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("0:0:0:0:0:0:0:1"));
+
+        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("::1"));
+        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("::"));
+
+        assert_eq!(Some(Ipv6Addr(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
+                FromStr::from_str("2a02:6b8::11:11"));
+
+        // too long group
+        let none: Option<IpAddr> = FromStr::from_str("::00000");
+        assert_eq!(None, none);
+        // too short
+        let none: Option<IpAddr> = FromStr::from_str("1:2:3:4:5:6:7");
+        assert_eq!(None, none);
+        // too long
+        let none: Option<IpAddr> = FromStr::from_str("1:2:3:4:5:6:7:8:9");
+        assert_eq!(None, none);
+        // triple colon
+        let none: Option<IpAddr> = FromStr::from_str("1:2:::6:7:8");
+        assert_eq!(None, none);
+        // two double colons
+        let none: Option<IpAddr> = FromStr::from_str("1:2::6::8");
+        assert_eq!(None, none);
+    }
+
+    #[test]
+    fn test_from_str_ipv4_in_ipv6() {
+        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 49152, 545)),
+                FromStr::from_str("::192.0.2.33"));
+        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
+                FromStr::from_str("::FFFF:192.0.2.33"));
+        assert_eq!(Some(Ipv6Addr(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
+                FromStr::from_str("64:ff9b::192.0.2.33"));
+        assert_eq!(Some(Ipv6Addr(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
+                FromStr::from_str("2001:db8:122:c000:2:2100:192.0.2.33"));
+
+        // colon after v4
+        let none: Option<IpAddr> = FromStr::from_str("::127.0.0.1:");
+        assert_eq!(None, none);
+        // not enought groups
+        let none: Option<IpAddr> = FromStr::from_str("1.2.3.4.5:127.0.0.1");
+        assert_eq!(None, none);
+        // too many groups
+        let none: Option<IpAddr> =
+            FromStr::from_str("1.2.3.4.5:6:7:127.0.0.1");
+        assert_eq!(None, none);
+    }
+
+    #[test]
+    fn test_from_str_socket_addr() {
+        assert_eq!(Some(SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 80 }),
+                FromStr::from_str("77.88.21.11:80"));
+        assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 }),
+                FromStr::from_str("[2a02:6b8:0:1::1]:53"));
+        assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0, 0, 0, 0, 0, 0, 0x7F00, 1), port: 22 }),
+                FromStr::from_str("[::127.0.0.1]:22"));
+
+        // without port
+        let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1");
+        assert_eq!(None, none);
+        // without port
+        let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1:");
+        assert_eq!(None, none);
+        // wrong brackets around v4
+        let none: Option<SocketAddr> = FromStr::from_str("[127.0.0.1]:22");
+        assert_eq!(None, none);
+        // port out of range
+        let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1:123456");
+        assert_eq!(None, none);
+    }
+
+    #[test]
+    fn ipv6_addr_to_str() {
+        let a1 = Ipv6Addr(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
+        assert!(a1.to_str() == ~"::ffff:192.0.2.128" || a1.to_str() == ~"::FFFF:192.0.2.128");
+    }
+
+}
diff --git a/src/libstd/io/net/mod.rs b/src/libstd/io/net/mod.rs
new file mode 100644 (file)
index 0000000..cf10916
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+pub use self::addrinfo::get_host_addresses;
+
+pub mod addrinfo;
+pub mod tcp;
+pub mod udp;
+pub mod ip;
+#[cfg(unix)]
+pub mod unix;
diff --git a/src/libstd/io/net/tcp.rs b/src/libstd/io/net/tcp.rs
new file mode 100644 (file)
index 0000000..a59d652
--- /dev/null
@@ -0,0 +1,725 @@
+// 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.
+
+use option::{Option, Some, None};
+use result::{Ok, Err};
+use io::net::ip::SocketAddr;
+use io::{Reader, Writer, Listener, Acceptor};
+use io::{io_error, EndOfFile};
+use rt::rtio::{IoFactory, with_local_io,
+               RtioSocket, RtioTcpListener, RtioTcpAcceptor, RtioTcpStream};
+
+pub struct TcpStream {
+    priv obj: ~RtioTcpStream
+}
+
+impl TcpStream {
+    fn new(s: ~RtioTcpStream) -> TcpStream {
+        TcpStream { obj: s }
+    }
+
+    pub fn connect(addr: SocketAddr) -> Option<TcpStream> {
+        do with_local_io |io| {
+            match io.tcp_connect(addr) {
+                Ok(s) => Some(TcpStream::new(s)),
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
+            }
+        }
+    }
+
+    pub fn peer_name(&mut self) -> Option<SocketAddr> {
+        match self.obj.peer_name() {
+            Ok(pn) => Some(pn),
+            Err(ioerr) => {
+                debug!("failed to get peer name: {:?}", ioerr);
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
+
+    pub fn socket_name(&mut self) -> Option<SocketAddr> {
+        match self.obj.socket_name() {
+            Ok(sn) => Some(sn),
+            Err(ioerr) => {
+                debug!("failed to get socket name: {:?}", ioerr);
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
+}
+
+impl Reader for TcpStream {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        match self.obj.read(buf) {
+            Ok(read) => Some(read),
+            Err(ioerr) => {
+                // EOF is indicated by returning None
+                if ioerr.kind != EndOfFile {
+                    io_error::cond.raise(ioerr);
+                }
+                return None;
+            }
+        }
+    }
+
+    fn eof(&mut self) -> bool { fail!() }
+}
+
+impl Writer for TcpStream {
+    fn write(&mut self, buf: &[u8]) {
+        match self.obj.write(buf) {
+            Ok(_) => (),
+            Err(ioerr) => io_error::cond.raise(ioerr),
+        }
+    }
+}
+
+pub struct TcpListener {
+    priv obj: ~RtioTcpListener
+}
+
+impl TcpListener {
+    pub fn bind(addr: SocketAddr) -> Option<TcpListener> {
+        do with_local_io |io| {
+            match io.tcp_bind(addr) {
+                Ok(l) => Some(TcpListener { obj: l }),
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
+            }
+        }
+    }
+
+    pub fn socket_name(&mut self) -> Option<SocketAddr> {
+        match self.obj.socket_name() {
+            Ok(sn) => Some(sn),
+            Err(ioerr) => {
+                debug!("failed to get socket name: {:?}", ioerr);
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
+}
+
+impl Listener<TcpStream, TcpAcceptor> for TcpListener {
+    fn listen(self) -> Option<TcpAcceptor> {
+        match self.obj.listen() {
+            Ok(acceptor) => Some(TcpAcceptor { obj: acceptor }),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
+}
+
+pub struct TcpAcceptor {
+    priv obj: ~RtioTcpAcceptor
+}
+
+impl Acceptor<TcpStream> for TcpAcceptor {
+    fn accept(&mut self) -> Option<TcpStream> {
+        match self.obj.accept() {
+            Ok(s) => Some(TcpStream::new(s)),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use cell::Cell;
+    use rt::test::*;
+    use io::net::ip::{Ipv4Addr, SocketAddr};
+    use io::*;
+    use prelude::*;
+    use rt::comm::oneshot;
+
+    #[test] #[ignore]
+    fn bind_error() {
+        do run_in_mt_newsched_task {
+            let mut called = false;
+            do io_error::cond.trap(|e| {
+                assert!(e.kind == PermissionDenied);
+                called = true;
+            }).inside {
+                let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
+                let listener = TcpListener::bind(addr);
+                assert!(listener.is_none());
+            }
+            assert!(called);
+        }
+    }
+
+    #[test]
+    fn connect_error() {
+        do run_in_mt_newsched_task {
+            let mut called = false;
+            do io_error::cond.trap(|e| {
+                let expected_error = if cfg!(unix) {
+                    ConnectionRefused
+                } else {
+                    // On Win32, opening port 1 gives WSAEADDRNOTAVAIL error.
+                    OtherIoError
+                };
+                assert_eq!(e.kind, expected_error);
+                called = true;
+            }).inside {
+                let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
+                let stream = TcpStream::connect(addr);
+                assert!(stream.is_none());
+            }
+            assert!(called);
+        }
+    }
+
+    #[test]
+    fn smoke_test_ip4() {
+        do run_in_mt_newsched_task {
+            let addr = next_test_ip4();
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+                let mut stream = acceptor.accept();
+                let mut buf = [0];
+                stream.read(buf);
+                assert!(buf[0] == 99);
+            }
+
+            do spawntask {
+                port.take().recv();
+                let mut stream = TcpStream::connect(addr);
+                stream.write([99]);
+            }
+        }
+    }
+
+    #[test]
+    fn smoke_test_ip6() {
+        do run_in_mt_newsched_task {
+            let addr = next_test_ip6();
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+                let mut stream = acceptor.accept();
+                let mut buf = [0];
+                stream.read(buf);
+                assert!(buf[0] == 99);
+            }
+
+            do spawntask {
+                port.take().recv();
+                let mut stream = TcpStream::connect(addr);
+                stream.write([99]);
+            }
+        }
+    }
+
+    #[test]
+    fn read_eof_ip4() {
+        do run_in_mt_newsched_task {
+            let addr = next_test_ip4();
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+                let mut stream = acceptor.accept();
+                let mut buf = [0];
+                let nread = stream.read(buf);
+                assert!(nread.is_none());
+            }
+
+            do spawntask {
+                port.take().recv();
+                let _stream = TcpStream::connect(addr);
+                // Close
+            }
+        }
+    }
+
+    #[test]
+    fn read_eof_ip6() {
+        do run_in_mt_newsched_task {
+            let addr = next_test_ip6();
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+                let mut stream = acceptor.accept();
+                let mut buf = [0];
+                let nread = stream.read(buf);
+                assert!(nread.is_none());
+            }
+
+            do spawntask {
+                port.take().recv();
+                let _stream = TcpStream::connect(addr);
+                // Close
+            }
+        }
+    }
+
+    #[test]
+    fn read_eof_twice_ip4() {
+        do run_in_mt_newsched_task {
+            let addr = next_test_ip4();
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+                let mut stream = acceptor.accept();
+                let mut buf = [0];
+                let nread = stream.read(buf);
+                assert!(nread.is_none());
+                do io_error::cond.trap(|e| {
+                    if cfg!(windows) {
+                        assert_eq!(e.kind, NotConnected);
+                    } else {
+                        fail!();
+                    }
+                }).inside {
+                    let nread = stream.read(buf);
+                    assert!(nread.is_none());
+                }
+            }
+
+            do spawntask {
+                port.take().recv();
+                let _stream = TcpStream::connect(addr);
+                // Close
+            }
+        }
+    }
+
+    #[test]
+    fn read_eof_twice_ip6() {
+        do run_in_mt_newsched_task {
+            let addr = next_test_ip6();
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+                let mut stream = acceptor.accept();
+                let mut buf = [0];
+                let nread = stream.read(buf);
+                assert!(nread.is_none());
+                do io_error::cond.trap(|e| {
+                    if cfg!(windows) {
+                        assert_eq!(e.kind, NotConnected);
+                    } else {
+                        fail!();
+                    }
+                }).inside {
+                    let nread = stream.read(buf);
+                    assert!(nread.is_none());
+                }
+            }
+
+            do spawntask {
+                port.take().recv();
+                let _stream = TcpStream::connect(addr);
+                // Close
+            }
+        }
+    }
+
+    #[test]
+    fn write_close_ip4() {
+        do run_in_mt_newsched_task {
+            let addr = next_test_ip4();
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+                let mut stream = acceptor.accept();
+                let buf = [0];
+                loop {
+                    let mut stop = false;
+                    do io_error::cond.trap(|e| {
+                        // NB: ECONNRESET on linux, EPIPE on mac, ECONNABORTED
+                        //     on windows
+                        assert!(e.kind == ConnectionReset ||
+                                e.kind == BrokenPipe ||
+                                e.kind == ConnectionAborted,
+                                "unknown error: {:?}", e);
+                        stop = true;
+                    }).inside {
+                        stream.write(buf);
+                    }
+                    if stop { break }
+                }
+            }
+
+            do spawntask {
+                port.take().recv();
+                let _stream = TcpStream::connect(addr);
+                // Close
+            }
+        }
+    }
+
+    #[test]
+    fn write_close_ip6() {
+        do run_in_mt_newsched_task {
+            let addr = next_test_ip6();
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+                let mut stream = acceptor.accept();
+                let buf = [0];
+                loop {
+                    let mut stop = false;
+                    do io_error::cond.trap(|e| {
+                        // NB: ECONNRESET on linux, EPIPE on mac, ECONNABORTED
+                        //     on windows
+                        assert!(e.kind == ConnectionReset ||
+                                e.kind == BrokenPipe ||
+                                e.kind == ConnectionAborted,
+                                "unknown error: {:?}", e);
+                        stop = true;
+                    }).inside {
+                        stream.write(buf);
+                    }
+                    if stop { break }
+                }
+            }
+
+            do spawntask {
+                port.take().recv();
+                let _stream = TcpStream::connect(addr);
+                // Close
+            }
+        }
+    }
+
+    #[test]
+    fn multiple_connect_serial_ip4() {
+        do run_in_mt_newsched_task {
+            let addr = next_test_ip4();
+            let max = 10;
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+                for ref mut stream in acceptor.incoming().take(max) {
+                    let mut buf = [0];
+                    stream.read(buf);
+                    assert_eq!(buf[0], 99);
+                }
+            }
+
+            do spawntask {
+                port.take().recv();
+                do max.times {
+                    let mut stream = TcpStream::connect(addr);
+                    stream.write([99]);
+                }
+            }
+        }
+    }
+
+    #[test]
+    fn multiple_connect_serial_ip6() {
+        do run_in_mt_newsched_task {
+            let addr = next_test_ip6();
+            let max = 10;
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+                for ref mut stream in acceptor.incoming().take(max) {
+                    let mut buf = [0];
+                    stream.read(buf);
+                    assert_eq!(buf[0], 99);
+                }
+            }
+
+            do spawntask {
+                port.take().recv();
+                do max.times {
+                    let mut stream = TcpStream::connect(addr);
+                    stream.write([99]);
+                }
+            }
+        }
+    }
+
+    #[test]
+    fn multiple_connect_interleaved_greedy_schedule_ip4() {
+        do run_in_mt_newsched_task {
+            let addr = next_test_ip4();
+            static MAX: int = 10;
+            let (port, chan) = oneshot();
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+                for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) {
+                    let stream = Cell::new(stream);
+                    // Start another task to handle the connection
+                    do spawntask {
+                        let mut stream = stream.take();
+                        let mut buf = [0];
+                        stream.read(buf);
+                        assert!(buf[0] == i as u8);
+                        debug!("read");
+                    }
+                }
+            }
+
+            port.recv();
+            connect(0, addr);
+
+            fn connect(i: int, addr: SocketAddr) {
+                if i == MAX { return }
+
+                do spawntask {
+                    debug!("connecting");
+                    let mut stream = TcpStream::connect(addr);
+                    // Connect again before writing
+                    connect(i + 1, addr);
+                    debug!("writing");
+                    stream.write([i as u8]);
+                }
+            }
+        }
+    }
+
+    #[test]
+    fn multiple_connect_interleaved_greedy_schedule_ip6() {
+        do run_in_mt_newsched_task {
+            let addr = next_test_ip6();
+            static MAX: int = 10;
+            let (port, chan) = oneshot();
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+                for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) {
+                    let stream = Cell::new(stream);
+                    // Start another task to handle the connection
+                    do spawntask {
+                        let mut stream = stream.take();
+                        let mut buf = [0];
+                        stream.read(buf);
+                        assert!(buf[0] == i as u8);
+                        debug!("read");
+                    }
+                }
+            }
+
+            port.recv();
+            connect(0, addr);
+
+            fn connect(i: int, addr: SocketAddr) {
+                if i == MAX { return }
+
+                do spawntask {
+                    debug!("connecting");
+                    let mut stream = TcpStream::connect(addr);
+                    // Connect again before writing
+                    connect(i + 1, addr);
+                    debug!("writing");
+                    stream.write([i as u8]);
+                }
+            }
+        }
+    }
+
+    #[test]
+    fn multiple_connect_interleaved_lazy_schedule_ip4() {
+        do run_in_mt_newsched_task {
+            let addr = next_test_ip4();
+            static MAX: int = 10;
+            let (port, chan) = oneshot();
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+                for stream in acceptor.incoming().take(MAX as uint) {
+                    let stream = Cell::new(stream);
+                    // Start another task to handle the connection
+                    do spawntask_later {
+                        let mut stream = stream.take();
+                        let mut buf = [0];
+                        stream.read(buf);
+                        assert!(buf[0] == 99);
+                        debug!("read");
+                    }
+                }
+            }
+
+            port.recv();
+            connect(0, addr);
+
+            fn connect(i: int, addr: SocketAddr) {
+                if i == MAX { return }
+
+                do spawntask_later {
+                    debug!("connecting");
+                    let mut stream = TcpStream::connect(addr);
+                    // Connect again before writing
+                    connect(i + 1, addr);
+                    debug!("writing");
+                    stream.write([99]);
+                }
+            }
+        }
+    }
+    #[test]
+    fn multiple_connect_interleaved_lazy_schedule_ip6() {
+        do run_in_mt_newsched_task {
+            let addr = next_test_ip6();
+            static MAX: int = 10;
+            let (port, chan) = oneshot();
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+                for stream in acceptor.incoming().take(MAX as uint) {
+                    let stream = Cell::new(stream);
+                    // Start another task to handle the connection
+                    do spawntask_later {
+                        let mut stream = stream.take();
+                        let mut buf = [0];
+                        stream.read(buf);
+                        assert!(buf[0] == 99);
+                        debug!("read");
+                    }
+                }
+            }
+
+            port.recv();
+            connect(0, addr);
+
+            fn connect(i: int, addr: SocketAddr) {
+                if i == MAX { return }
+
+                do spawntask_later {
+                    debug!("connecting");
+                    let mut stream = TcpStream::connect(addr);
+                    // Connect again before writing
+                    connect(i + 1, addr);
+                    debug!("writing");
+                    stream.write([99]);
+                }
+            }
+        }
+    }
+
+    #[cfg(test)]
+    fn socket_name(addr: SocketAddr) {
+        do run_in_mt_newsched_task {
+            do spawntask {
+                let mut listener = TcpListener::bind(addr).unwrap();
+
+                // Make sure socket_name gives
+                // us the socket we binded to.
+                let so_name = listener.socket_name();
+                assert!(so_name.is_some());
+                assert_eq!(addr, so_name.unwrap());
+
+            }
+        }
+    }
+
+    #[cfg(test)]
+    fn peer_name(addr: SocketAddr) {
+        do run_in_mt_newsched_task {
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = TcpListener::bind(addr).listen();
+                chan.take().send(());
+
+                acceptor.accept();
+            }
+
+            do spawntask {
+                port.take().recv();
+                let stream = TcpStream::connect(addr);
+
+                assert!(stream.is_some());
+                let mut stream = stream.unwrap();
+
+                // Make sure peer_name gives us the
+                // address/port of the peer we've
+                // connected to.
+                let peer_name = stream.peer_name();
+                assert!(peer_name.is_some());
+                assert_eq!(addr, peer_name.unwrap());
+            }
+        }
+    }
+
+    #[test]
+    fn socket_and_peer_name_ip4() {
+        peer_name(next_test_ip4());
+        socket_name(next_test_ip4());
+    }
+
+    #[test]
+    fn socket_and_peer_name_ip6() {
+        // XXX: peer name is not consistent
+        //peer_name(next_test_ip6());
+        socket_name(next_test_ip6());
+    }
+
+}
diff --git a/src/libstd/io/net/udp.rs b/src/libstd/io/net/udp.rs
new file mode 100644 (file)
index 0000000..1a2245a
--- /dev/null
@@ -0,0 +1,321 @@
+// 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.
+
+use option::{Option, Some, None};
+use result::{Ok, Err};
+use io::net::ip::SocketAddr;
+use io::{Reader, Writer};
+use io::{io_error, EndOfFile};
+use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, with_local_io};
+
+pub struct UdpSocket {
+    priv obj: ~RtioUdpSocket
+}
+
+impl UdpSocket {
+    pub fn bind(addr: SocketAddr) -> Option<UdpSocket> {
+        do with_local_io |io| {
+            match io.udp_bind(addr) {
+                Ok(s) => Some(UdpSocket { obj: s }),
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
+            }
+        }
+    }
+
+    pub fn recvfrom(&mut self, buf: &mut [u8]) -> Option<(uint, SocketAddr)> {
+        match self.obj.recvfrom(buf) {
+            Ok((nread, src)) => Some((nread, src)),
+            Err(ioerr) => {
+                // EOF is indicated by returning None
+                if ioerr.kind != EndOfFile {
+                    io_error::cond.raise(ioerr);
+                }
+                None
+            }
+        }
+    }
+
+    pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) {
+        match self.obj.sendto(buf, dst) {
+            Ok(_) => (),
+            Err(ioerr) => io_error::cond.raise(ioerr),
+        }
+    }
+
+    pub fn connect(self, other: SocketAddr) -> UdpStream {
+        UdpStream { socket: self, connectedTo: other }
+    }
+
+    pub fn socket_name(&mut self) -> Option<SocketAddr> {
+        match self.obj.socket_name() {
+            Ok(sn) => Some(sn),
+            Err(ioerr) => {
+                debug!("failed to get socket name: {:?}", ioerr);
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
+}
+
+pub struct UdpStream {
+    priv socket: UdpSocket,
+    priv connectedTo: SocketAddr
+}
+
+impl UdpStream {
+    pub fn as_socket<T>(&mut self, f: &fn(&mut UdpSocket) -> T) -> T { f(&mut self.socket) }
+
+    pub fn disconnect(self) -> UdpSocket { self.socket }
+}
+
+impl Reader for UdpStream {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        let peer = self.connectedTo;
+        do self.as_socket |sock| {
+            match sock.recvfrom(buf) {
+                Some((_nread, src)) if src != peer => Some(0),
+                Some((nread, _src)) => Some(nread),
+                None => None,
+            }
+        }
+    }
+
+    fn eof(&mut self) -> bool { fail!() }
+}
+
+impl Writer for UdpStream {
+    fn write(&mut self, buf: &[u8]) {
+        do self.as_socket |sock| {
+            sock.sendto(buf, self.connectedTo);
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use rt::test::*;
+    use io::net::ip::{Ipv4Addr, SocketAddr};
+    use io::*;
+    use option::{Some, None};
+    use rt::comm::oneshot;
+    use cell::Cell;
+
+    #[test]  #[ignore]
+    fn bind_error() {
+        do run_in_mt_newsched_task {
+            let mut called = false;
+            do io_error::cond.trap(|e| {
+                assert!(e.kind == PermissionDenied);
+                called = true;
+            }).inside {
+                let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
+                let socket = UdpSocket::bind(addr);
+                assert!(socket.is_none());
+            }
+            assert!(called);
+        }
+    }
+
+    #[test]
+    fn socket_smoke_test_ip4() {
+        do run_in_mt_newsched_task {
+            let server_ip = next_test_ip4();
+            let client_ip = next_test_ip4();
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                match UdpSocket::bind(server_ip) {
+                    Some(ref mut server) => {
+                        chan.take().send(());
+                        let mut buf = [0];
+                        match server.recvfrom(buf) {
+                            Some((nread, src)) => {
+                                assert_eq!(nread, 1);
+                                assert_eq!(buf[0], 99);
+                                assert_eq!(src, client_ip);
+                            }
+                            None => fail!()
+                        }
+                    }
+                    None => fail!()
+                }
+            }
+
+            do spawntask {
+                match UdpSocket::bind(client_ip) {
+                    Some(ref mut client) => {
+                        port.take().recv();
+                        client.sendto([99], server_ip)
+                    }
+                    None => fail!()
+                }
+            }
+        }
+    }
+
+    #[test]
+    fn socket_smoke_test_ip6() {
+        do run_in_mt_newsched_task {
+            let server_ip = next_test_ip6();
+            let client_ip = next_test_ip6();
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                match UdpSocket::bind(server_ip) {
+                    Some(ref mut server) => {
+                        chan.take().send(());
+                        let mut buf = [0];
+                        match server.recvfrom(buf) {
+                            Some((nread, src)) => {
+                                assert_eq!(nread, 1);
+                                assert_eq!(buf[0], 99);
+                                assert_eq!(src, client_ip);
+                            }
+                            None => fail!()
+                        }
+                    }
+                    None => fail!()
+                }
+            }
+
+            do spawntask {
+                match UdpSocket::bind(client_ip) {
+                    Some(ref mut client) => {
+                        port.take().recv();
+                        client.sendto([99], server_ip)
+                    }
+                    None => fail!()
+                }
+            }
+        }
+    }
+
+    #[test]
+    fn stream_smoke_test_ip4() {
+        do run_in_mt_newsched_task {
+            let server_ip = next_test_ip4();
+            let client_ip = next_test_ip4();
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                match UdpSocket::bind(server_ip) {
+                    Some(server) => {
+                        let server = ~server;
+                        let mut stream = server.connect(client_ip);
+                        chan.take().send(());
+                        let mut buf = [0];
+                        match stream.read(buf) {
+                            Some(nread) => {
+                                assert_eq!(nread, 1);
+                                assert_eq!(buf[0], 99);
+                            }
+                            None => fail!()
+                        }
+                    }
+                    None => fail!()
+                }
+            }
+
+            do spawntask {
+                match UdpSocket::bind(client_ip) {
+                    Some(client) => {
+                        let client = ~client;
+                        let mut stream = client.connect(server_ip);
+                        port.take().recv();
+                        stream.write([99]);
+                    }
+                    None => fail!()
+                }
+            }
+        }
+    }
+
+    #[test]
+    fn stream_smoke_test_ip6() {
+        do run_in_mt_newsched_task {
+            let server_ip = next_test_ip6();
+            let client_ip = next_test_ip6();
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                match UdpSocket::bind(server_ip) {
+                    Some(server) => {
+                        let server = ~server;
+                        let mut stream = server.connect(client_ip);
+                        chan.take().send(());
+                        let mut buf = [0];
+                        match stream.read(buf) {
+                            Some(nread) => {
+                                assert_eq!(nread, 1);
+                                assert_eq!(buf[0], 99);
+                            }
+                            None => fail!()
+                        }
+                    }
+                    None => fail!()
+                }
+            }
+
+            do spawntask {
+                match UdpSocket::bind(client_ip) {
+                    Some(client) => {
+                        let client = ~client;
+                        let mut stream = client.connect(server_ip);
+                        port.take().recv();
+                        stream.write([99]);
+                    }
+                    None => fail!()
+                }
+            }
+        }
+    }
+
+    #[cfg(test)]
+    fn socket_name(addr: SocketAddr) {
+        do run_in_mt_newsched_task {
+            do spawntask {
+                let server = UdpSocket::bind(addr);
+
+                assert!(server.is_some());
+                let mut server = server.unwrap();
+
+                // Make sure socket_name gives
+                // us the socket we binded to.
+                let so_name = server.socket_name();
+                assert!(so_name.is_some());
+                assert_eq!(addr, so_name.unwrap());
+
+            }
+        }
+    }
+
+    #[test]
+    fn socket_name_ip4() {
+        socket_name(next_test_ip4());
+    }
+
+    #[test]
+    fn socket_name_ip6() {
+        socket_name(next_test_ip6());
+    }
+}
diff --git a/src/libstd/io/net/unix.rs b/src/libstd/io/net/unix.rs
new file mode 100644 (file)
index 0000000..c6b4a2f
--- /dev/null
@@ -0,0 +1,295 @@
+// 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.
+
+/*!
+
+Named pipes
+
+This module contains the ability to communicate over named pipes with
+synchronous I/O. On windows, this corresponds to talking over a Named Pipe,
+while on Unix it corresponds to UNIX domain sockets.
+
+These pipes are similar to TCP in the sense that you can have both a stream to a
+server and a server itself. The server provided accepts other `UnixStream`
+instances as clients.
+
+*/
+
+use prelude::*;
+
+use c_str::ToCStr;
+use rt::rtio::{IoFactory, RtioUnixListener, with_local_io};
+use rt::rtio::{RtioUnixAcceptor, RtioPipe};
+use io::pipe::PipeStream;
+use io::{io_error, Listener, Acceptor, Reader, Writer};
+
+/// A stream which communicates over a named pipe.
+pub struct UnixStream {
+    priv obj: PipeStream,
+}
+
+impl UnixStream {
+    fn new(obj: ~RtioPipe) -> UnixStream {
+        UnixStream { obj: PipeStream::new(obj) }
+    }
+
+    /// Connect to a pipe named by `path`. This will attempt to open a
+    /// connection to the underlying socket.
+    ///
+    /// The returned stream will be closed when the object falls out of scope.
+    ///
+    /// # Failure
+    ///
+    /// This function will raise on the `io_error` condition if the connection
+    /// could not be made.
+    ///
+    /// # Example
+    ///
+    ///     use std::io::net::unix::UnixStream;
+    ///
+    ///     let server = Path("path/to/my/socket");
+    ///     let mut stream = UnixStream::connect(&server);
+    ///     stream.write([1, 2, 3]);
+    ///
+    pub fn connect<P: ToCStr>(path: &P) -> Option<UnixStream> {
+        do with_local_io |io| {
+            match io.unix_connect(&path.to_c_str()) {
+                Ok(s) => Some(UnixStream::new(s)),
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
+            }
+        }
+    }
+}
+
+impl Reader for UnixStream {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.obj.read(buf) }
+    fn eof(&mut self) -> bool { self.obj.eof() }
+}
+
+impl Writer for UnixStream {
+    fn write(&mut self, buf: &[u8]) { self.obj.write(buf) }
+}
+
+pub struct UnixListener {
+    priv obj: ~RtioUnixListener,
+}
+
+impl UnixListener {
+
+    /// Creates a new listener, ready to receive incoming connections on the
+    /// specified socket. The server will be named by `path`.
+    ///
+    /// This listener will be closed when it falls out of scope.
+    ///
+    /// # Failure
+    ///
+    /// This function will raise on the `io_error` condition if the specified
+    /// path could not be bound.
+    ///
+    /// # Example
+    ///
+    ///     use std::io::net::unix::UnixListener;
+    ///
+    ///     let server = Path("path/to/my/socket");
+    ///     let mut stream = UnixListener::bind(&server);
+    ///     for client in stream.incoming() {
+    ///         let mut client = client;
+    ///         client.write([1, 2, 3, 4]);
+    ///     }
+    ///
+    pub fn bind<P: ToCStr>(path: &P) -> Option<UnixListener> {
+        do with_local_io |io| {
+            match io.unix_bind(&path.to_c_str()) {
+                Ok(s) => Some(UnixListener{ obj: s }),
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
+            }
+        }
+    }
+}
+
+impl Listener<UnixStream, UnixAcceptor> for UnixListener {
+    fn listen(self) -> Option<UnixAcceptor> {
+        match self.obj.listen() {
+            Ok(acceptor) => Some(UnixAcceptor { obj: acceptor }),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
+}
+
+pub struct UnixAcceptor {
+    priv obj: ~RtioUnixAcceptor,
+}
+
+impl Acceptor<UnixStream> for UnixAcceptor {
+    fn accept(&mut self) -> Option<UnixStream> {
+        match self.obj.accept() {
+            Ok(s) => Some(UnixStream::new(s)),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                None
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use prelude::*;
+    use super::*;
+    use cell::Cell;
+    use rt::test::*;
+    use io::*;
+    use rt::comm::oneshot;
+
+    fn smalltest(server: ~fn(UnixStream), client: ~fn(UnixStream)) {
+        let server = Cell::new(server);
+        let client = Cell::new(client);
+        do run_in_mt_newsched_task {
+            let server = Cell::new(server.take());
+            let client = Cell::new(client.take());
+            let path1 = next_test_unix();
+            let path2 = path1.clone();
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = UnixListener::bind(&path1).listen();
+                chan.take().send(());
+                server.take()(acceptor.accept().unwrap());
+            }
+
+            do spawntask {
+                port.take().recv();
+                client.take()(UnixStream::connect(&path2).unwrap());
+            }
+        }
+    }
+
+    #[test]
+    fn bind_error() {
+        do run_in_mt_newsched_task {
+            let mut called = false;
+            do io_error::cond.trap(|e| {
+                assert!(e.kind == PermissionDenied);
+                called = true;
+            }).inside {
+                let listener = UnixListener::bind(&("path/to/nowhere"));
+                assert!(listener.is_none());
+            }
+            assert!(called);
+        }
+    }
+
+    #[test]
+    fn connect_error() {
+        do run_in_mt_newsched_task {
+            let mut called = false;
+            do io_error::cond.trap(|e| {
+                assert_eq!(e.kind, OtherIoError);
+                called = true;
+            }).inside {
+                let stream = UnixStream::connect(&("path/to/nowhere"));
+                assert!(stream.is_none());
+            }
+            assert!(called);
+        }
+    }
+
+    #[test]
+    fn smoke() {
+        smalltest(|mut server| {
+            let mut buf = [0];
+            server.read(buf);
+            assert!(buf[0] == 99);
+        }, |mut client| {
+            client.write([99]);
+        })
+    }
+
+    #[test]
+    fn read_eof() {
+        smalltest(|mut server| {
+            let mut buf = [0];
+            assert!(server.read(buf).is_none());
+            assert!(server.read(buf).is_none());
+        }, |_client| {
+            // drop the client
+        })
+    }
+
+    #[test]
+    fn write_begone() {
+        smalltest(|mut server| {
+            let buf = [0];
+            let mut stop = false;
+            while !stop{
+                do io_error::cond.trap(|e| {
+                    assert!(e.kind == BrokenPipe || e.kind == NotConnected,
+                            "unknown error {:?}", e);
+                    stop = true;
+                }).inside {
+                    server.write(buf);
+                }
+            }
+        }, |_client| {
+            // drop the client
+        })
+    }
+
+    #[test]
+    fn accept_lots() {
+        do run_in_mt_newsched_task {
+            let times = 10;
+            let path1 = next_test_unix();
+            let path2 = path1.clone();
+            let (port, chan) = oneshot();
+            let port = Cell::new(port);
+            let chan = Cell::new(chan);
+
+            do spawntask {
+                let mut acceptor = UnixListener::bind(&path1).listen();
+                chan.take().send(());
+                do times.times {
+                    let mut client = acceptor.accept();
+                    let mut buf = [0];
+                    client.read(buf);
+                    assert_eq!(buf[0], 100);
+                }
+            }
+
+            do spawntask {
+                port.take().recv();
+                do times.times {
+                    let mut stream = UnixStream::connect(&path2);
+                    stream.write([100]);
+                }
+            }
+        }
+    }
+
+    #[test]
+    fn path_exists() {
+        do run_in_mt_newsched_task {
+            let path = next_test_unix();
+            let _acceptor = UnixListener::bind(&path).listen();
+            assert!(path.exists());
+        }
+    }
+}
diff --git a/src/libstd/io/option.rs b/src/libstd/io/option.rs
new file mode 100644 (file)
index 0000000..5938252
--- /dev/null
@@ -0,0 +1,181 @@
+// 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.
+
+//! Implementations of I/O traits for the Option type
+//!
+//! I/O constructors return option types to allow errors to be handled.
+//! These implementations allow e.g. `Option<File>` to be used
+//! as a `Reader` without unwrapping the option first.
+
+use option::*;
+use super::{Reader, Writer, Listener, Acceptor, Seek, SeekStyle};
+use super::{standard_error, PreviousIoError, io_error, IoError};
+
+fn prev_io_error() -> IoError {
+    standard_error(PreviousIoError)
+}
+
+impl<W: Writer> Writer for Option<W> {
+    fn write(&mut self, buf: &[u8]) {
+        match *self {
+            Some(ref mut writer) => writer.write(buf),
+            None => io_error::cond.raise(prev_io_error())
+        }
+    }
+
+    fn flush(&mut self) {
+        match *self {
+            Some(ref mut writer) => writer.flush(),
+            None => io_error::cond.raise(prev_io_error())
+        }
+    }
+}
+
+impl<R: Reader> Reader for Option<R> {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        match *self {
+            Some(ref mut reader) => reader.read(buf),
+            None => {
+                io_error::cond.raise(prev_io_error());
+                None
+            }
+        }
+    }
+
+    fn eof(&mut self) -> bool {
+        match *self {
+            Some(ref mut reader) => reader.eof(),
+            None => {
+                io_error::cond.raise(prev_io_error());
+                true
+            }
+        }
+    }
+}
+
+impl<S: Seek> Seek for Option<S> {
+    fn tell(&self) -> u64 {
+        match *self {
+            Some(ref seeker) => seeker.tell(),
+            None => {
+                io_error::cond.raise(prev_io_error());
+                0
+            }
+        }
+    }
+    fn seek(&mut self, pos: i64, style: SeekStyle) {
+        match *self {
+            Some(ref mut seeker) => seeker.seek(pos, style),
+            None => io_error::cond.raise(prev_io_error())
+        }
+    }
+}
+
+impl<T, A: Acceptor<T>, L: Listener<T, A>> Listener<T, A> for Option<L> {
+    fn listen(self) -> Option<A> {
+        match self {
+            Some(listener) => listener.listen(),
+            None => {
+                io_error::cond.raise(prev_io_error());
+                None
+            }
+        }
+    }
+}
+
+impl<T, A: Acceptor<T>> Acceptor<T> for Option<A> {
+    fn accept(&mut self) -> Option<T> {
+        match *self {
+            Some(ref mut acceptor) => acceptor.accept(),
+            None => {
+                io_error::cond.raise(prev_io_error());
+                None
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use option::*;
+    use super::super::mem::*;
+    use rt::test::*;
+    use super::super::{PreviousIoError, io_error};
+
+    #[test]
+    fn test_option_writer() {
+        do run_in_mt_newsched_task {
+            let mut writer: Option<MemWriter> = Some(MemWriter::new());
+            writer.write([0, 1, 2]);
+            writer.flush();
+            assert_eq!(writer.unwrap().inner(), ~[0, 1, 2]);
+        }
+    }
+
+    #[test]
+    fn test_option_writer_error() {
+        do run_in_mt_newsched_task {
+            let mut writer: Option<MemWriter> = None;
+
+            let mut called = false;
+            do io_error::cond.trap(|err| {
+                assert_eq!(err.kind, PreviousIoError);
+                called = true;
+            }).inside {
+                writer.write([0, 0, 0]);
+            }
+            assert!(called);
+
+            let mut called = false;
+            do io_error::cond.trap(|err| {
+                assert_eq!(err.kind, PreviousIoError);
+                called = true;
+            }).inside {
+                writer.flush();
+            }
+            assert!(called);
+        }
+    }
+
+    #[test]
+    fn test_option_reader() {
+        do run_in_mt_newsched_task {
+            let mut reader: Option<MemReader> = Some(MemReader::new(~[0, 1, 2, 3]));
+            let mut buf = [0, 0];
+            reader.read(buf);
+            assert_eq!(buf, [0, 1]);
+            assert!(!reader.eof());
+        }
+    }
+
+    #[test]
+    fn test_option_reader_error() {
+        let mut reader: Option<MemReader> = None;
+        let mut buf = [];
+
+        let mut called = false;
+        do io_error::cond.trap(|err| {
+            assert_eq!(err.kind, PreviousIoError);
+            called = true;
+        }).inside {
+            reader.read(buf);
+        }
+        assert!(called);
+
+        let mut called = false;
+        do io_error::cond.trap(|err| {
+            assert_eq!(err.kind, PreviousIoError);
+            called = true;
+        }).inside {
+            assert!(reader.eof());
+        }
+        assert!(called);
+    }
+}
diff --git a/src/libstd/io/pipe.rs b/src/libstd/io/pipe.rs
new file mode 100644 (file)
index 0000000..edbc6fa
--- /dev/null
@@ -0,0 +1,89 @@
+// 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.
+
+//! Synchronous, in-memory pipes.
+//!
+//! Currently these aren't particularly useful, there only exists bindings
+//! enough so that pipes can be created to child processes.
+
+use prelude::*;
+use super::{Reader, Writer};
+use io::{io_error, EndOfFile};
+use io::native::file;
+use rt::rtio::{RtioPipe, with_local_io};
+
+pub struct PipeStream {
+    priv obj: ~RtioPipe,
+}
+
+impl PipeStream {
+    /// Consumes a file descriptor to return a pipe stream that will have
+    /// synchronous, but non-blocking reads/writes. This is useful if the file
+    /// descriptor is acquired via means other than the standard methods.
+    ///
+    /// This operation consumes ownership of the file descriptor and it will be
+    /// closed once the object is deallocated.
+    ///
+    /// # Example
+    ///
+    ///     use std::libc;
+    ///     use std::io::pipe;
+    ///
+    ///     let mut pipe = PipeStream::open(libc::STDERR_FILENO);
+    ///     pipe.write(bytes!("Hello, stderr!"));
+    ///
+    /// # Failure
+    ///
+    /// If the pipe cannot be created, an error will be raised on the
+    /// `io_error` condition.
+    pub fn open(fd: file::fd_t) -> Option<PipeStream> {
+        do with_local_io |io| {
+            match io.pipe_open(fd) {
+                Ok(obj) => Some(PipeStream { obj: obj }),
+                Err(e) => {
+                    io_error::cond.raise(e);
+                    None
+                }
+            }
+        }
+    }
+
+    pub fn new(inner: ~RtioPipe) -> PipeStream {
+        PipeStream { obj: inner }
+    }
+}
+
+impl Reader for PipeStream {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        match self.obj.read(buf) {
+            Ok(read) => Some(read),
+            Err(ioerr) => {
+                // EOF is indicated by returning None
+                if ioerr.kind != EndOfFile {
+                    io_error::cond.raise(ioerr);
+                }
+                return None;
+            }
+        }
+    }
+
+    fn eof(&mut self) -> bool { false }
+}
+
+impl Writer for PipeStream {
+    fn write(&mut self, buf: &[u8]) {
+        match self.obj.write(buf) {
+            Ok(_) => (),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+            }
+        }
+    }
+}
diff --git a/src/libstd/io/process.rs b/src/libstd/io/process.rs
new file mode 100644 (file)
index 0000000..3941003
--- /dev/null
@@ -0,0 +1,177 @@
+// 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.
+
+//! Bindings for executing child processes
+
+use prelude::*;
+use cell::Cell;
+
+use libc;
+use io;
+use io::io_error;
+use rt::rtio::{RtioProcess, IoFactory, with_local_io};
+
+use fmt;
+
+// windows values don't matter as long as they're at least one of unix's
+// TERM/KILL/INT signals
+#[cfg(windows)] pub static PleaseExitSignal: int = 15;
+#[cfg(windows)] pub static MustDieSignal: int = 9;
+#[cfg(not(windows))] pub static PleaseExitSignal: int = libc::SIGTERM as int;
+#[cfg(not(windows))] pub static MustDieSignal: int = libc::SIGKILL as int;
+
+pub struct Process {
+    priv handle: ~RtioProcess,
+    io: ~[Option<io::PipeStream>],
+}
+
+/// This configuration describes how a new process should be spawned. This is
+/// translated to libuv's own configuration
+pub struct ProcessConfig<'self> {
+    /// Path to the program to run
+    program: &'self str,
+
+    /// Arguments to pass to the program (doesn't include the program itself)
+    args: &'self [~str],
+
+    /// Optional environment to specify for the program. If this is None, then
+    /// it will inherit the current process's environment.
+    env: Option<&'self [(~str, ~str)]>,
+
+    /// Optional working directory for the new process. If this is None, then
+    /// the current directory of the running process is inherited.
+    cwd: Option<&'self str>,
+
+    /// Any number of streams/file descriptors/pipes may be attached to this
+    /// process. This list enumerates the file descriptors and such for the
+    /// process to be spawned, and the file descriptors inherited will start at
+    /// 0 and go to the length of this array.
+    ///
+    /// Standard file descriptors are:
+    ///
+    ///     0 - stdin
+    ///     1 - stdout
+    ///     2 - stderr
+    io: &'self [StdioContainer]
+}
+
+/// Describes what to do with a standard io stream for a child process.
+pub enum StdioContainer {
+    /// This stream will be ignored. This is the equivalent of attaching the
+    /// stream to `/dev/null`
+    Ignored,
+
+    /// The specified file descriptor is inherited for the stream which it is
+    /// specified for.
+    InheritFd(libc::c_int),
+
+    /// Creates a pipe for the specified file descriptor which will be created
+    /// when the process is spawned.
+    ///
+    /// The first boolean argument is whether the pipe is readable, and the
+    /// second is whether it is writable. These properties are from the view of
+    /// the *child* process, not the parent process.
+    CreatePipe(bool /* readable */, bool /* writable */),
+}
+
+/// Describes the result of a process after it has terminated.
+#[deriving(Eq)]
+pub enum ProcessExit {
+    /// Normal termination with an exit status.
+    ExitStatus(int),
+
+    /// Termination by signal, with the signal number.
+    ExitSignal(int),
+}
+
+impl fmt::Default for ProcessExit {
+    /// Format a ProcessExit enum, to nicely present the information.
+    fn fmt(obj: &ProcessExit, f: &mut fmt::Formatter) {
+        match *obj {
+            ExitStatus(code) =>  write!(f.buf, "exit code: {}", code),
+            ExitSignal(code) =>  write!(f.buf, "signal: {}", code),
+        }
+    }
+}
+
+impl ProcessExit {
+    /// Was termination successful? Signal termination not considered a success,
+    /// and success is defined as a zero exit status.
+    pub fn success(&self) -> bool {
+        return self.matches_exit_status(0);
+    }
+
+    /// Checks whether this ProcessExit matches the given exit status.
+    /// Termination by signal will never match an exit code.
+    pub fn matches_exit_status(&self, wanted: int) -> bool {
+        *self == ExitStatus(wanted)
+    }
+}
+
+impl Process {
+    /// Creates a new pipe initialized, but not bound to any particular
+    /// source/destination
+    pub fn new(config: ProcessConfig) -> Option<Process> {
+        let config = Cell::new(config);
+        do with_local_io |io| {
+            match io.spawn(config.take()) {
+                Ok((p, io)) => Some(Process{
+                    handle: p,
+                    io: io.move_iter().map(|p|
+                        p.map(|p| io::PipeStream::new(p))
+                    ).collect()
+                }),
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
+            }
+        }
+    }
+
+    /// Returns the process id of this child process
+    pub fn id(&self) -> libc::pid_t { self.handle.id() }
+
+    /// Sends the specified signal to the child process, returning whether the
+    /// signal could be delivered or not.
+    ///
+    /// Note that this is purely a wrapper around libuv's `uv_process_kill`
+    /// function.
+    ///
+    /// If the signal delivery fails, then the `io_error` condition is raised on
+    pub fn signal(&mut self, signal: int) {
+        match self.handle.kill(signal) {
+            Ok(()) => {}
+            Err(err) => {
+                io_error::cond.raise(err)
+            }
+        }
+    }
+
+    /// Wait for the child to exit completely, returning the status that it
+    /// exited with. This function will continue to have the same return value
+    /// after it has been called at least once.
+    pub fn wait(&mut self) -> ProcessExit { self.handle.wait() }
+}
+
+impl Drop for Process {
+    fn drop(&mut self) {
+        // Close all I/O before exiting to ensure that the child doesn't wait
+        // forever to print some text or something similar.
+        for _ in range(0, self.io.len()) {
+            self.io.pop();
+        }
+
+        self.wait();
+    }
+}
+
+// Tests for this module can be found in the rtio-processes run-pass test, along
+// with the justification for why it's not located here.
diff --git a/src/libstd/io/signal.rs b/src/libstd/io/signal.rs
new file mode 100644 (file)
index 0000000..1310152
--- /dev/null
@@ -0,0 +1,224 @@
+// 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.
+
+/*!
+
+Signal handling
+
+This modules provides bindings to receive signals safely, built on top of the
+local I/O factory. There are a number of defined signals which can be caught,
+but not all signals will work across all platforms (windows doesn't have
+definitions for a number of signals.
+
+*/
+
+use clone::Clone;
+use comm::{Port, SharedChan, stream};
+use container::{Map, MutableMap};
+use hashmap;
+use io::io_error;
+use option::{Some, None};
+use result::{Err, Ok};
+use rt::rtio::{IoFactory, RtioSignal, with_local_io};
+
+#[repr(int)]
+#[deriving(Eq, IterBytes)]
+pub enum Signum {
+    /// Equivalent to SIGBREAK, delivered when the user presses Ctrl-Break.
+    Break = 21i,
+    /// Equivalent to SIGHUP, delivered when the user closes the terminal
+    /// window. On delivery of HangUp, the program is given approximately
+    /// 10 seconds to perfom any cleanup. After that, Windows will
+    /// unconditionally terminate it.
+    HangUp = 1i,
+    /// Equivalent to SIGINT, delivered when the user presses Ctrl-c.
+    Interrupt = 2i,
+    /// Equivalent to SIGQUIT, delivered when the user presses Ctrl-\.
+    Quit = 3i,
+    /// Equivalent to SIGTSTP, delivered when the user presses Ctrl-z.
+    StopTemporarily = 20i,
+    /// Equivalent to SIGUSR1.
+    User1 = 10i,
+    /// Equivalent to SIGUSR2.
+    User2 = 12i,
+    /// Equivalent to SIGWINCH, delivered when the console has been resized.
+    /// WindowSizeChange may not be delivered in a timely manner; size change
+    /// will only be detected when the cursor is being moved.
+    WindowSizeChange = 28i,
+}
+
+/// Listener provides a port to listen for registered signals.
+///
+/// Listener automatically unregisters its handles once it is out of scope.
+/// However, clients can still unregister signums manually.
+///
+/// # Example
+///
+/// ```rust
+/// use std::io::signal::{Listener, Interrupt};
+///
+/// let mut listener = Listener::new();
+/// listener.register(signal::Interrupt);
+///
+/// do spawn {
+///     loop {
+///         match listener.port.recv() {
+///             Interrupt => println("Got Interrupt'ed"),
+///             _ => (),
+///         }
+///     }
+/// }
+///
+/// ```
+pub struct Listener {
+    /// A map from signums to handles to keep the handles in memory
+    priv handles: hashmap::HashMap<Signum, ~RtioSignal>,
+    /// chan is where all the handles send signums, which are received by
+    /// the clients from port.
+    priv chan: SharedChan<Signum>,
+
+    /// Clients of Listener can `recv()` from this port. This is exposed to
+    /// allow selection over this port as well as manipulation of the port
+    /// directly.
+    port: Port<Signum>,
+}
+
+impl Listener {
+    /// Creates a new listener for signals. Once created, signals are bound via
+    /// the `register` method (otherwise nothing will ever be received)
+    pub fn new() -> Listener {
+        let (port, chan) = stream();
+        Listener {
+            chan: SharedChan::new(chan),
+            port: port,
+            handles: hashmap::HashMap::new(),
+        }
+    }
+
+    /// Listen for a signal, returning true when successfully registered for
+    /// signum. Signals can be received using `recv()`.
+    ///
+    /// Once a signal is registered, this listener will continue to receive
+    /// notifications of signals until it is unregistered. This occurs
+    /// regardless of the number of other listeners registered in other tasks
+    /// (or on this task).
+    ///
+    /// Signals are still received if there is no task actively waiting for
+    /// a signal, and a later call to `recv` will return the signal that was
+    /// received while no task was waiting on it.
+    ///
+    /// # Failure
+    ///
+    /// If this function fails to register a signal handler, then an error will
+    /// be raised on the `io_error` condition and the function will return
+    /// false.
+    pub fn register(&mut self, signum: Signum) -> bool {
+        if self.handles.contains_key(&signum) {
+            return true; // self is already listening to signum, so succeed
+        }
+        do with_local_io |io| {
+            match io.signal(signum, self.chan.clone()) {
+                Ok(w) => {
+                    self.handles.insert(signum, w);
+                    Some(())
+                },
+                Err(ioerr) => {
+                    io_error::cond.raise(ioerr);
+                    None
+                }
+            }
+        }.is_some()
+    }
+
+    /// Unregisters a signal. If this listener currently had a handler
+    /// registered for the signal, then it will stop receiving any more
+    /// notification about the signal. If the signal has already been received,
+    /// it may still be returned by `recv`.
+    pub fn unregister(&mut self, signum: Signum) {
+        self.handles.pop(&signum);
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use libc;
+    use io::timer;
+    use super::{Listener, Interrupt};
+    use comm::{GenericPort, Peekable};
+
+    // kill is only available on Unixes
+    #[cfg(unix)]
+    fn sigint() {
+        unsafe {
+            libc::funcs::posix88::signal::kill(libc::getpid(), libc::SIGINT);
+        }
+    }
+
+    #[test] #[cfg(unix, not(target_os="android"))] // FIXME(#10378)
+    fn test_io_signal_smoketest() {
+        let mut signal = Listener::new();
+        signal.register(Interrupt);
+        sigint();
+        timer::sleep(10);
+        match signal.port.recv() {
+            Interrupt => (),
+            s => fail!("Expected Interrupt, got {:?}", s),
+        }
+    }
+
+    #[test] #[cfg(unix, not(target_os="android"))] // FIXME(#10378)
+    fn test_io_signal_two_signal_one_signum() {
+        let mut s1 = Listener::new();
+        let mut s2 = Listener::new();
+        s1.register(Interrupt);
+        s2.register(Interrupt);
+        sigint();
+        timer::sleep(10);
+        match s1.port.recv() {
+            Interrupt => (),
+            s => fail!("Expected Interrupt, got {:?}", s),
+        }
+        match s2.port.recv() {
+            Interrupt => (),
+            s => fail!("Expected Interrupt, got {:?}", s),
+        }
+    }
+
+    #[test] #[cfg(unix, not(target_os="android"))] // FIXME(#10378)
+    fn test_io_signal_unregister() {
+        let mut s1 = Listener::new();
+        let mut s2 = Listener::new();
+        s1.register(Interrupt);
+        s2.register(Interrupt);
+        s2.unregister(Interrupt);
+        sigint();
+        timer::sleep(10);
+        if s2.port.peek() {
+            fail!("Unexpected {:?}", s2.port.recv());
+        }
+    }
+
+    #[cfg(windows)]
+    #[test]
+    fn test_io_signal_invalid_signum() {
+        use io;
+        use super::User1;
+        let mut s = Listener::new();
+        let mut called = false;
+        do io::io_error::cond.trap(|_| {
+            called = true;
+        }).inside {
+            if s.register(User1) {
+                fail!("Unexpected successful registry of signum {:?}", User1);
+            }
+        }
+        assert!(called);
+    }
+}
diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs
new file mode 100644 (file)
index 0000000..302d757
--- /dev/null
@@ -0,0 +1,321 @@
+// 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.
+
+/*!
+
+This modules provides bindings to the local event loop's TTY interface, using it
+to have synchronous, but non-blocking versions of stdio. These handles can be
+inspected for information about terminal dimensions or related information
+about the stream or terminal that it is attached to.
+
+# Example
+
+```rust
+use std::io;
+
+let mut out = io::stdout();
+out.write(bytes!("Hello, world!"));
+```
+
+*/
+
+use fmt;
+use libc;
+use option::{Option, Some, None};
+use result::{Ok, Err};
+use io::buffered::LineBufferedWriter;
+use rt::rtio::{IoFactory, RtioTTY, RtioFileStream, with_local_io,
+               CloseAsynchronously};
+use super::{Reader, Writer, io_error, IoError, OtherIoError,
+            standard_error, EndOfFile};
+
+// And so begins the tale of acquiring a uv handle to a stdio stream on all
+// platforms in all situations. Our story begins by splitting the world into two
+// categories, windows and unix. Then one day the creators of unix said let
+// there be redirection! And henceforth there was redirection away from the
+// console for standard I/O streams.
+//
+// After this day, the world split into four factions:
+//
+// 1. Unix with stdout on a terminal.
+// 2. Unix with stdout redirected.
+// 3. Windows with stdout on a terminal.
+// 4. Windows with stdout redirected.
+//
+// Many years passed, and then one day the nation of libuv decided to unify this
+// world. After months of toiling, uv created three ideas: TTY, Pipe, File.
+// These three ideas propagated throughout the lands and the four great factions
+// decided to settle among them.
+//
+// The groups of 1, 2, and 3 all worked very hard towards the idea of TTY. Upon
+// doing so, they even enhanced themselves further then their Pipe/File
+// brethren, becoming the dominant powers.
+//
+// The group of 4, however, decided to work independently. They abandoned the
+// common TTY belief throughout, and even abandoned the fledgling Pipe belief.
+// The members of the 4th faction decided to only align themselves with File.
+//
+// tl;dr; TTY works on everything but when windows stdout is redirected, in that
+//        case pipe also doesn't work, but magically file does!
+enum StdSource {
+    TTY(~RtioTTY),
+    File(~RtioFileStream),
+}
+
+fn src<T>(fd: libc::c_int, readable: bool, f: &fn(StdSource) -> T) -> T {
+    do with_local_io |io| {
+        let fd = unsafe { libc::dup(fd) };
+        match io.tty_open(fd, readable) {
+            Ok(tty) => Some(f(TTY(tty))),
+            Err(_) => {
+                // It's not really that desirable if these handles are closed
+                // synchronously, and because they're squirreled away in a task
+                // structure the destructors will be run when the task is
+                // attempted to get destroyed. This means that if we run a
+                // synchronous destructor we'll attempt to do some scheduling
+                // operations which will just result in sadness.
+                Some(f(File(io.fs_from_raw_fd(fd, CloseAsynchronously))))
+            }
+        }
+    }.unwrap()
+}
+
+/// Creates a new non-blocking handle to the stdin of the current process.
+///
+/// See `stdout()` for notes about this function.
+pub fn stdin() -> StdReader {
+    do src(libc::STDIN_FILENO, true) |src| { StdReader { inner: src } }
+}
+
+/// Creates a new non-blocking handle to the stdout of the current process.
+///
+/// Note that this is a fairly expensive operation in that at least one memory
+/// allocation is performed. Additionally, this must be called from a runtime
+/// task context because the stream returned will be a non-blocking object using
+/// the local scheduler to perform the I/O.
+pub fn stdout() -> StdWriter {
+    do src(libc::STDOUT_FILENO, false) |src| { StdWriter { inner: src } }
+}
+
+/// Creates a new non-blocking handle to the stderr of the current process.
+///
+/// See `stdout()` for notes about this function.
+pub fn stderr() -> StdWriter {
+    do src(libc::STDERR_FILENO, false) |src| { StdWriter { inner: src } }
+}
+
+// Helper to access the local task's stdout handle
+//
+// Note that this is not a safe function to expose because you can create an
+// aliased pointer very easily:
+//
+//  do with_task_stdout |io1| {
+//      do with_task_stdout |io2| {
+//          // io1 aliases io2
+//      }
+//  }
+fn with_task_stdout(f: &fn(&mut Writer)) {
+    use rt::local::Local;
+    use rt::task::Task;
+
+    unsafe {
+        // Logging may require scheduling operations, so we can't remove the
+        // task from TLS right now, hence the unsafe borrow. Sad.
+        let task: *mut Task = Local::unsafe_borrow();
+
+        match (*task).stdout_handle {
+            Some(ref mut handle) => f(*handle),
+            None => {
+                let handle = stdout();
+                let mut handle = ~LineBufferedWriter::new(handle) as ~Writer;
+                f(handle);
+                (*task).stdout_handle = Some(handle);
+            }
+        }
+    }
+}
+
+/// Flushes the local task's stdout handle.
+///
+/// By default, this stream is a line-buffering stream, so flushing may be
+/// necessary to ensure that all output is printed to the screen (if there are
+/// no newlines printed).
+///
+/// Note that logging macros do not use this stream. Using the logging macros
+/// will emit output to stderr, and while they are line buffered the log
+/// messages are always terminated in a newline (no need to flush).
+pub fn flush() {
+    do with_task_stdout |io| {
+        io.flush();
+    }
+}
+
+/// Prints a string to the stdout of the current process. No newline is emitted
+/// after the string is printed.
+pub fn print(s: &str) {
+    do with_task_stdout |io| {
+        io.write(s.as_bytes());
+    }
+}
+
+/// Prints a string as a line. to the stdout of the current process. A literal
+/// `\n` character is printed to the console after the string.
+pub fn println(s: &str) {
+    do with_task_stdout |io| {
+        io.write(s.as_bytes());
+        io.write(['\n' as u8]);
+    }
+}
+
+/// Similar to `print`, but takes a `fmt::Arguments` structure to be compatible
+/// with the `format_args!` macro.
+pub fn print_args(fmt: &fmt::Arguments) {
+    do with_task_stdout |io| {
+        fmt::write(io, fmt);
+    }
+}
+
+/// Similar to `println`, but takes a `fmt::Arguments` structure to be
+/// compatible with the `format_args!` macro.
+pub fn println_args(fmt: &fmt::Arguments) {
+    do with_task_stdout |io| {
+        fmt::writeln(io, fmt);
+    }
+}
+
+/// Representation of a reader of a standard input stream
+pub struct StdReader {
+    priv inner: StdSource
+}
+
+impl Reader for StdReader {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        let ret = match self.inner {
+            TTY(ref mut tty) => tty.read(buf),
+            File(ref mut file) => file.read(buf).map(|i| i as uint),
+        };
+        match ret {
+            // When reading a piped stdin, libuv will return 0-length reads when
+            // stdin reaches EOF. For pretty much all other streams it will
+            // return an actual EOF error, but apparently for stdin it's a
+            // little different. Hence, here we convert a 0 length read to an
+            // end-of-file indicator so the caller knows to stop reading.
+            Ok(0) => {
+                io_error::cond.raise(standard_error(EndOfFile));
+                None
+            }
+            Ok(amt) => Some(amt as uint),
+            Err(e) => {
+                io_error::cond.raise(e);
+                None
+            }
+        }
+    }
+
+    fn eof(&mut self) -> bool { false }
+}
+
+/// Representation of a writer to a standard output stream
+pub struct StdWriter {
+    priv inner: StdSource
+}
+
+impl StdWriter {
+    /// Gets the size of this output window, if possible. This is typically used
+    /// when the writer is attached to something like a terminal, this is used
+    /// to fetch the dimensions of the terminal.
+    ///
+    /// If successful, returns Some((width, height)).
+    ///
+    /// # Failure
+    ///
+    /// This function will raise on the `io_error` condition if an error
+    /// happens.
+    pub fn winsize(&mut self) -> Option<(int, int)> {
+        match self.inner {
+            TTY(ref mut tty) => {
+                match tty.get_winsize() {
+                    Ok(p) => Some(p),
+                    Err(e) => {
+                        io_error::cond.raise(e);
+                        None
+                    }
+                }
+            }
+            File(*) => {
+                io_error::cond.raise(IoError {
+                    kind: OtherIoError,
+                    desc: "stream is not a tty",
+                    detail: None,
+                });
+                None
+            }
+        }
+    }
+
+    /// Controls whether this output stream is a "raw stream" or simply a normal
+    /// stream.
+    ///
+    /// # Failure
+    ///
+    /// This function will raise on the `io_error` condition if an error
+    /// happens.
+    pub fn set_raw(&mut self, raw: bool) {
+        match self.inner {
+            TTY(ref mut tty) => {
+                match tty.set_raw(raw) {
+                    Ok(()) => {},
+                    Err(e) => io_error::cond.raise(e),
+                }
+            }
+            File(*) => {
+                io_error::cond.raise(IoError {
+                    kind: OtherIoError,
+                    desc: "stream is not a tty",
+                    detail: None,
+                });
+            }
+        }
+    }
+
+    /// Returns whether this stream is attached to a TTY instance or not.
+    pub fn isatty(&self) -> bool {
+        match self.inner {
+            TTY(*) => true,
+            File(*) => false,
+        }
+    }
+}
+
+impl Writer for StdWriter {
+    fn write(&mut self, buf: &[u8]) {
+        let ret = match self.inner {
+            TTY(ref mut tty) => tty.write(buf),
+            File(ref mut file) => file.write(buf),
+        };
+        match ret {
+            Ok(()) => {}
+            Err(e) => io_error::cond.raise(e)
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn smoke() {
+        // Just make sure we can acquire handles
+        stdin();
+        stdout();
+        stderr();
+    }
+}
diff --git a/src/libstd/io/timer.rs b/src/libstd/io/timer.rs
new file mode 100644 (file)
index 0000000..219f630
--- /dev/null
@@ -0,0 +1,186 @@
+// 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.
+
+/*!
+
+Synchronous Timers
+
+This module exposes the functionality to create timers, block the current task,
+and create ports which will receive notifications after a period of time.
+
+# Example
+
+```rust
+
+use std::io::Timer;
+
+let mut timer = Timer::new().unwrap();
+timer.sleep(10); // block the task for awhile
+
+let timeout = timer.oneshot(10);
+// do some work
+timeout.recv(); // wait for the timeout to expire
+
+let periodic = timer.periodic(10);
+loop {
+    periodic.recv();
+    // this loop is only executed once every 10ms
+}
+
+```
+
+*/
+
+use comm::{Port, PortOne};
+use option::{Option, Some, None};
+use result::{Ok, Err};
+use io::io_error;
+use rt::rtio::{IoFactory, RtioTimer, with_local_io};
+
+pub struct Timer {
+    priv obj: ~RtioTimer
+}
+
+/// Sleep the current task for `msecs` milliseconds.
+pub fn sleep(msecs: u64) {
+    let mut timer = Timer::new().expect("timer::sleep: could not create a Timer");
+
+    timer.sleep(msecs)
+}
+
+impl Timer {
+    /// Creates a new timer which can be used to put the current task to sleep
+    /// for a number of milliseconds, or to possibly create channels which will
+    /// get notified after an amount of time has passed.
+    pub fn new() -> Option<Timer> {
+        do with_local_io |io| {
+            match io.timer_init() {
+                Ok(t) => Some(Timer { obj: t }),
+                Err(ioerr) => {
+                    debug!("Timer::init: failed to init: {:?}", ioerr);
+                    io_error::cond.raise(ioerr);
+                    None
+                }
+            }
+
+        }
+    }
+
+    /// Blocks the current task for `msecs` milliseconds.
+    ///
+    /// Note that this function will cause any other ports for this timer to be
+    /// invalidated (the other end will be closed).
+    pub fn sleep(&mut self, msecs: u64) {
+        self.obj.sleep(msecs);
+    }
+
+    /// Creates a oneshot port which will have a notification sent when `msecs`
+    /// milliseconds has elapsed. This does *not* block the current task, but
+    /// instead returns immediately.
+    ///
+    /// Note that this invalidates any previous port which has been created by
+    /// this timer, and that the returned port will be invalidated once the
+    /// timer is destroyed (when it falls out of scope).
+    pub fn oneshot(&mut self, msecs: u64) -> PortOne<()> {
+        self.obj.oneshot(msecs)
+    }
+
+    /// Creates a port which will have a continuous stream of notifications
+    /// being sent every `msecs` milliseconds. This does *not* block the
+    /// current task, but instead returns immediately. The first notification
+    /// will not be received immediately, but rather after `msec` milliseconds
+    /// have passed.
+    ///
+    /// Note that this invalidates any previous port which has been created by
+    /// this timer, and that the returned port will be invalidated once the
+    /// timer is destroyed (when it falls out of scope).
+    pub fn periodic(&mut self, msecs: u64) -> Port<()> {
+        self.obj.period(msecs)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::*;
+    use super::*;
+    use rt::test::*;
+
+    #[test]
+    fn test_io_timer_sleep_simple() {
+        do run_in_mt_newsched_task {
+            let mut timer = Timer::new().unwrap();
+            timer.sleep(1);
+        }
+    }
+
+    #[test]
+    fn test_io_timer_sleep_oneshot() {
+        do run_in_mt_newsched_task {
+            let mut timer = Timer::new().unwrap();
+            timer.oneshot(1).recv();
+        }
+    }
+
+    #[test]
+    fn test_io_timer_sleep_oneshot_forget() {
+        do run_in_mt_newsched_task {
+            let mut timer = Timer::new().unwrap();
+            timer.oneshot(100000000000);
+        }
+    }
+
+    #[test]
+    fn oneshot_twice() {
+        do run_in_mt_newsched_task {
+            let mut timer = Timer::new().unwrap();
+            let port1 = timer.oneshot(10000);
+            let port = timer.oneshot(1);
+            port.recv();
+            assert_eq!(port1.try_recv(), None);
+        }
+    }
+
+    #[test]
+    fn test_io_timer_oneshot_then_sleep() {
+        do run_in_mt_newsched_task {
+            let mut timer = Timer::new().unwrap();
+            let port = timer.oneshot(100000000000);
+            timer.sleep(1); // this should invalidate the port
+
+            assert_eq!(port.try_recv(), None);
+        }
+    }
+
+    #[test]
+    fn test_io_timer_sleep_periodic() {
+        do run_in_mt_newsched_task {
+            let mut timer = Timer::new().unwrap();
+            let port = timer.periodic(1);
+            port.recv();
+            port.recv();
+            port.recv();
+        }
+    }
+
+    #[test]
+    fn test_io_timer_sleep_periodic_forget() {
+        do run_in_mt_newsched_task {
+            let mut timer = Timer::new().unwrap();
+            timer.periodic(100000000000);
+        }
+    }
+
+    #[test]
+    fn test_io_timer_sleep_standalone() {
+        do run_in_mt_newsched_task {
+            sleep(1)
+        }
+    }
+}
index 967aee9135d8ca12e22a56f48dbfdfaa8b09afe0..e0908dcb290b259857e6b6e604881367fa5dea2e 100644 (file)
@@ -21,7 +21,7 @@
 //! boxes (`owned`), and unsafe and borrowed pointers (`ptr`, `borrowed`).
 //! Additionally, `std` provides pervasive types (`option` and `result`),
 //! task creation and communication primitives (`task`, `comm`), platform
-//! abstractions (`os` and `path`), basic I/O abstractions (`rt::io`), common
+//! abstractions (`os` and `path`), basic I/O abstractions (`io`), common
 //! traits (`kinds`, `ops`, `cmp`, `num`, `to_str`), and complete bindings
 //! to the C standard library (`libc`).
 //!
@@ -68,7 +68,7 @@
 #[allow(cstack)]; // NOTE: remove after the next snapshot.
 
 // When testing libstd, bring in libuv as the I/O backend so tests can print
-// things and all of the std::rt::io tests have an I/O interface to run on top
+// things and all of the std::io tests have an I/O interface to run on top
 // of
 #[cfg(test)] extern mod rustuv(vers = "0.9-pre");
 
@@ -179,6 +179,7 @@ pub mod linkhack {
 pub mod libc;
 pub mod c_str;
 pub mod os;
+pub mod io;
 pub mod path;
 pub mod rand;
 pub mod run;
@@ -225,6 +226,7 @@ mod std {
     pub use logging;
     pub use option;
     pub use os;
+    pub use io;
     pub use rt;
     pub use str;
     pub use to_bytes;
index ff24c35d4e641123ba9792ce2bc66054b132175a..213cf5dc07cd54d682b10c4e6b3d5e4eb6cbff9e 100644 (file)
@@ -388,7 +388,7 @@ fn load_self() -> Option<~[u8]> {
     #[cfg(target_os = "linux")]
     #[cfg(target_os = "android")]
     fn load_self() -> Option<~[u8]> {
-        use std::rt::io;
+        use std::io;
 
         match io::result(|| io::fs::readlink(&Path::new("/proc/self/exe"))) {
             Ok(Some(path)) => Some(path.as_vec().to_owned()),
@@ -1447,8 +1447,8 @@ fn memory_map_file() {
         use result::{Ok, Err};
         use os::*;
         use libc::*;
-        use rt::io;
-        use rt::io::fs;
+        use io;
+        use io::fs;
 
         #[cfg(unix)]
         fn lseek_(fd: c_int, size: uint) {
index 0190b02fbc08f71e18e8b50df229a26cbf81a129..d3797cf8099bf0bbac3173906c2f7f0a5be090a9 100644 (file)
@@ -40,7 +40,7 @@
 // Reexported functions
 pub use from_str::from_str;
 pub use iter::range;
-pub use rt::io::stdio::{print, println};
+pub use io::stdio::{print, println};
 
 // Reexported types and traits
 
@@ -67,7 +67,7 @@
 pub use num::{Primitive, Int, Float, ToStrRadix, ToPrimitive, FromPrimitive};
 pub use path::{GenericPath, Path, PosixPath, WindowsPath};
 pub use ptr::RawPtr;
-pub use rt::io::{Writer, Reader, Seek};
+pub use io::{Writer, Reader, Seek};
 pub use send_str::{SendStr, SendStrOwned, SendStrStatic, IntoSendStr};
 pub use str::{Str, StrVector, StrSlice, OwnedStr};
 pub use to_bytes::IterBytes;
index 73d5c72a728863b2b38d10e4ad07a26ec0346c86..60fc1e0c6bc294384543b5a35e6dde169f7b8ab0 100644 (file)
@@ -17,7 +17,7 @@
 #[cfg(unix)]
 use rand::reader::ReaderRng;
 #[cfg(unix)]
-use rt::io::File;
+use io::File;
 
 #[cfg(windows)]
 use cast;
index b98dade4bf613e9f47cdc7da45170679904d1743..4beabb8bf6aa461c30b7323aff314e847a69256e 100644 (file)
@@ -11,7 +11,7 @@
 //! A wrapper around any Reader to treat it as an RNG.
 
 use option::{Some, None};
-use rt::io::Reader;
+use io::Reader;
 
 use rand::Rng;
 
@@ -24,7 +24,7 @@
 ///
 /// ```rust
 /// use std::rand::{reader, Rng};
-/// use std::rt::io::mem;
+/// use std::io::mem;
 ///
 /// fn main() {
 ///     let mut rng = reader::ReaderRng::new(mem::MemReader::new(~[1,2,3,4,5,6,7,8]));
@@ -77,7 +77,7 @@ fn fill_bytes(&mut self, v: &mut [u8]) {
 #[cfg(test)]
 mod test {
     use super::*;
-    use rt::io::mem::MemReader;
+    use io::mem::MemReader;
     use cast;
 
     #[test]
index e939be64d739a433a627b3863da947fe9de25f8c..3f8da64b3d6d347656cce3d8fa39ebcced56ad7d 100644 (file)
@@ -19,7 +19,7 @@
 use cast::transmute;
 use char;
 use container::Container;
-use rt::io;
+use io;
 use iter::Iterator;
 use libc::c_void;
 use option::{Some, None};
@@ -621,8 +621,8 @@ pub fn write_repr<T>(writer: &mut io::Writer, object: &T) {
 
 pub fn repr_to_str<T>(t: &T) -> ~str {
     use str;
-    use rt::io;
-    use rt::io::Decorator;
+    use io;
+    use io::Decorator;
 
     let mut result = io::mem::MemWriter::new();
     write_repr(&mut result as &mut io::Writer, t);
@@ -637,7 +637,7 @@ fn test_repr() {
     use prelude::*;
     use str;
     use str::Str;
-    use rt::io::Decorator;
+    use io::Decorator;
     use util::swap;
     use char::is_alphabetic;
 
diff --git a/src/libstd/rt/io/buffered.rs b/src/libstd/rt/io/buffered.rs
deleted file mode 100644 (file)
index 8afb718..0000000
+++ /dev/null
@@ -1,472 +0,0 @@
-// 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.
-
-//! Buffering wrappers for I/O traits
-//!
-//! It can be excessively inefficient to work directly with a `Reader` or
-//! `Writer`. Every call to `read` or `write` on `TcpStream` results in a
-//! system call, for example. This module provides structures that wrap
-//! `Readers`, `Writers`, and `Streams` and buffer input and output to them.
-//!
-//! # Examples
-//!
-//! ```
-//! let tcp_stream = TcpStream::connect(addr);
-//! let reader = BufferedReader::new(tcp_stream);
-//!
-//! let mut buf: ~[u8] = vec::from_elem(100, 0u8);
-//! match reader.read(buf.as_slice()) {
-//!     Some(nread) => println!("Read {} bytes", nread),
-//!     None => println!("At the end of the stream!")
-//! }
-//! ```
-//!
-//! ```
-//! let tcp_stream = TcpStream::connect(addr);
-//! let writer = BufferedWriter::new(tcp_stream);
-//!
-//! writer.write("hello, world".as_bytes());
-//! writer.flush();
-//! ```
-//!
-//! ```
-//! let tcp_stream = TcpStream::connect(addr);
-//! let stream = BufferedStream::new(tcp_stream);
-//!
-//! stream.write("hello, world".as_bytes());
-//! stream.flush();
-//!
-//! let mut buf = vec::from_elem(100, 0u8);
-//! match stream.read(buf.as_slice()) {
-//!     Some(nread) => println!("Read {} bytes", nread),
-//!     None => println!("At the end of the stream!")
-//! }
-//! ```
-//!
-
-use prelude::*;
-
-use num;
-use vec;
-use str;
-use super::{Reader, Writer, Stream, Decorator};
-
-// libuv recommends 64k buffers to maximize throughput
-// https://groups.google.com/forum/#!topic/libuv/oQO1HJAIDdA
-static DEFAULT_CAPACITY: uint = 64 * 1024;
-
-/// Wraps a Reader and buffers input from it
-pub struct BufferedReader<R> {
-    priv inner: R,
-    priv buf: ~[u8],
-    priv pos: uint,
-    priv cap: uint
-}
-
-impl<R: Reader> BufferedReader<R> {
-    /// Creates a new `BufferedReader` with with the specified buffer capacity
-    pub fn with_capacity(cap: uint, inner: R) -> BufferedReader<R> {
-        // It's *much* faster to create an uninitialized buffer than it is to
-        // fill everything in with 0. This buffer is entirely an implementation
-        // detail and is never exposed, so we're safe to not initialize
-        // everything up-front. This allows creation of BufferedReader instances
-        // to be very cheap (large mallocs are not nearly as expensive as large
-        // callocs).
-        let mut buf = vec::with_capacity(cap);
-        unsafe { vec::raw::set_len(&mut buf, cap); }
-        BufferedReader {
-            inner: inner,
-            buf: buf,
-            pos: 0,
-            cap: 0
-        }
-    }
-
-    /// Creates a new `BufferedReader` with a default buffer capacity
-    pub fn new(inner: R) -> BufferedReader<R> {
-        BufferedReader::with_capacity(DEFAULT_CAPACITY, inner)
-    }
-
-    /// Reads the next line of input, interpreted as a sequence of utf-8
-    /// encoded unicode codepoints. If a newline is encountered, then the
-    /// newline is contained in the returned string.
-    pub fn read_line(&mut self) -> Option<~str> {
-        self.read_until('\n' as u8).map(str::from_utf8_owned)
-    }
-
-    /// Reads a sequence of bytes leading up to a specified delimeter. Once the
-    /// specified byte is encountered, reading ceases and the bytes up to and
-    /// including the delimiter are returned.
-    pub fn read_until(&mut self, byte: u8) -> Option<~[u8]> {
-        let mut res = ~[];
-        let mut used;
-        loop {
-            {
-                let available = self.fill_buffer();
-                match available.iter().position(|&b| b == byte) {
-                    Some(i) => {
-                        res.push_all(available.slice_to(i + 1));
-                        used = i + 1;
-                        break
-                    }
-                    None => {
-                        res.push_all(available);
-                        used = available.len();
-                    }
-                }
-            }
-            if used == 0 {
-                break
-            }
-            self.pos += used;
-        }
-        self.pos += used;
-        return if res.len() == 0 {None} else {Some(res)};
-    }
-
-    fn fill_buffer<'a>(&'a mut self) -> &'a [u8] {
-        if self.pos == self.cap {
-            match self.inner.read(self.buf) {
-                Some(cap) => {
-                    self.pos = 0;
-                    self.cap = cap;
-                }
-                None => {}
-            }
-        }
-        return self.buf.slice(self.pos, self.cap);
-    }
-}
-
-impl<R: Reader> Reader for BufferedReader<R> {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        let nread = {
-            let available = self.fill_buffer();
-            if available.len() == 0 {
-                return None;
-            }
-            let nread = num::min(available.len(), buf.len());
-            vec::bytes::copy_memory(buf, available, nread);
-            nread
-        };
-        self.pos += nread;
-        Some(nread)
-    }
-
-    fn eof(&mut self) -> bool {
-        self.pos == self.cap && self.inner.eof()
-    }
-}
-
-impl<R: Reader> Decorator<R> for BufferedReader<R> {
-    fn inner(self) -> R {
-        self.inner
-    }
-
-    fn inner_ref<'a>(&'a self) -> &'a R {
-        &self.inner
-    }
-
-    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut R {
-        &mut self.inner
-    }
-}
-
-/// Wraps a Writer and buffers output to it
-///
-/// Note that `BufferedWriter` will NOT flush its buffer when dropped.
-pub struct BufferedWriter<W> {
-    priv inner: W,
-    priv buf: ~[u8],
-    priv pos: uint
-}
-
-impl<W: Writer> BufferedWriter<W> {
-    /// Creates a new `BufferedWriter` with with the specified buffer capacity
-    pub fn with_capacity(cap: uint, inner: W) -> BufferedWriter<W> {
-        // See comments in BufferedReader for why this uses unsafe code.
-        let mut buf = vec::with_capacity(cap);
-        unsafe { vec::raw::set_len(&mut buf, cap); }
-        BufferedWriter {
-            inner: inner,
-            buf: buf,
-            pos: 0
-        }
-    }
-
-    /// Creates a new `BufferedWriter` with a default buffer capacity
-    pub fn new(inner: W) -> BufferedWriter<W> {
-        BufferedWriter::with_capacity(DEFAULT_CAPACITY, inner)
-    }
-}
-
-impl<W: Writer> Writer for BufferedWriter<W> {
-    fn write(&mut self, buf: &[u8]) {
-        if self.pos + buf.len() > self.buf.len() {
-            self.flush();
-        }
-
-        if buf.len() > self.buf.len() {
-            self.inner.write(buf);
-        } else {
-            let dst = self.buf.mut_slice_from(self.pos);
-            vec::bytes::copy_memory(dst, buf, buf.len());
-            self.pos += buf.len();
-        }
-    }
-
-    fn flush(&mut self) {
-        if self.pos != 0 {
-            self.inner.write(self.buf.slice_to(self.pos));
-            self.pos = 0;
-        }
-        self.inner.flush();
-    }
-}
-
-impl<W: Writer> Decorator<W> for BufferedWriter<W> {
-    fn inner(self) -> W { self.inner }
-    fn inner_ref<'a>(&'a self) -> &'a W { &self.inner }
-    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut W { &mut self.inner }
-}
-
-/// Wraps a Writer and buffers output to it, flushing whenever a newline (0xa,
-/// '\n') is detected.
-///
-/// Note that this structure does NOT flush the output when dropped.
-pub struct LineBufferedWriter<W> {
-    priv inner: BufferedWriter<W>,
-}
-
-impl<W: Writer> LineBufferedWriter<W> {
-    /// Creates a new `LineBufferedWriter`
-    pub fn new(inner: W) -> LineBufferedWriter<W> {
-        // Lines typically aren't that long, don't use a giant buffer
-        LineBufferedWriter {
-            inner: BufferedWriter::with_capacity(1024, inner)
-        }
-    }
-}
-
-impl<W: Writer> Writer for LineBufferedWriter<W> {
-    fn write(&mut self, buf: &[u8]) {
-        match buf.iter().position(|&b| b == '\n' as u8) {
-            Some(i) => {
-                self.inner.write(buf.slice_to(i + 1));
-                self.inner.flush();
-                self.inner.write(buf.slice_from(i + 1));
-            }
-            None => self.inner.write(buf),
-        }
-    }
-
-    fn flush(&mut self) { self.inner.flush() }
-}
-
-impl<W: Writer> Decorator<W> for LineBufferedWriter<W> {
-    fn inner(self) -> W { self.inner.inner() }
-    fn inner_ref<'a>(&'a self) -> &'a W { self.inner.inner_ref() }
-    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut W { self.inner.inner_mut_ref() }
-}
-
-struct InternalBufferedWriter<W>(BufferedWriter<W>);
-
-impl<W: Reader> Reader for InternalBufferedWriter<W> {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        self.inner.read(buf)
-    }
-
-    fn eof(&mut self) -> bool {
-        self.inner.eof()
-    }
-}
-
-/// Wraps a Stream and buffers input and output to and from it
-///
-/// Note that `BufferedStream` will NOT flush its output buffer when dropped.
-pub struct BufferedStream<S> {
-    priv inner: BufferedReader<InternalBufferedWriter<S>>
-}
-
-impl<S: Stream> BufferedStream<S> {
-    pub fn with_capacities(reader_cap: uint, writer_cap: uint, inner: S)
-                           -> BufferedStream<S> {
-        let writer = BufferedWriter::with_capacity(writer_cap, inner);
-        let internal_writer = InternalBufferedWriter(writer);
-        let reader = BufferedReader::with_capacity(reader_cap,
-                                                   internal_writer);
-        BufferedStream { inner: reader }
-    }
-
-    pub fn new(inner: S) -> BufferedStream<S> {
-        BufferedStream::with_capacities(DEFAULT_CAPACITY, DEFAULT_CAPACITY,
-                                        inner)
-    }
-}
-
-impl<S: Stream> Reader for BufferedStream<S> {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        self.inner.read(buf)
-    }
-
-    fn eof(&mut self) -> bool {
-        self.inner.eof()
-    }
-}
-
-impl<S: Stream> Writer for BufferedStream<S> {
-    fn write(&mut self, buf: &[u8]) {
-        self.inner.inner.write(buf)
-    }
-
-    fn flush(&mut self) {
-        self.inner.inner.flush()
-    }
-}
-
-impl<S: Stream> Decorator<S> for BufferedStream<S> {
-    fn inner(self) -> S {
-        self.inner.inner.inner()
-    }
-
-    fn inner_ref<'a>(&'a self) -> &'a S {
-        self.inner.inner.inner_ref()
-    }
-
-    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut S {
-        self.inner.inner.inner_mut_ref()
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use prelude::*;
-    use super::*;
-    use super::super::mem::{MemReader, MemWriter};
-
-    #[test]
-    fn test_buffered_reader() {
-        let inner = MemReader::new(~[0, 1, 2, 3, 4]);
-        let mut reader = BufferedReader::with_capacity(2, inner);
-
-        let mut buf = [0, 0, 0];
-        let nread = reader.read(buf);
-        assert_eq!(Some(2), nread);
-        assert_eq!([0, 1, 0], buf);
-        assert!(!reader.eof());
-
-        let mut buf = [0];
-        let nread = reader.read(buf);
-        assert_eq!(Some(1), nread);
-        assert_eq!([2], buf);
-        assert!(!reader.eof());
-
-        let mut buf = [0, 0, 0];
-        let nread = reader.read(buf);
-        assert_eq!(Some(1), nread);
-        assert_eq!([3, 0, 0], buf);
-        assert!(!reader.eof());
-
-        let nread = reader.read(buf);
-        assert_eq!(Some(1), nread);
-        assert_eq!([4, 0, 0], buf);
-        assert!(reader.eof());
-
-        assert_eq!(None, reader.read(buf));
-    }
-
-    #[test]
-    fn test_buffered_writer() {
-        let inner = MemWriter::new();
-        let mut writer = BufferedWriter::with_capacity(2, inner);
-
-        writer.write([0, 1]);
-        assert_eq!([], writer.inner_ref().inner_ref().as_slice());
-
-        writer.write([2]);
-        assert_eq!([0, 1], writer.inner_ref().inner_ref().as_slice());
-
-        writer.write([3]);
-        assert_eq!([0, 1], writer.inner_ref().inner_ref().as_slice());
-
-        writer.flush();
-        assert_eq!([0, 1, 2, 3], writer.inner_ref().inner_ref().as_slice());
-
-        writer.write([4]);
-        writer.write([5]);
-        assert_eq!([0, 1, 2, 3], writer.inner_ref().inner_ref().as_slice());
-
-        writer.write([6]);
-        assert_eq!([0, 1, 2, 3, 4, 5],
-                   writer.inner_ref().inner_ref().as_slice());
-
-        writer.write([7, 8]);
-        assert_eq!([0, 1, 2, 3, 4, 5, 6],
-                   writer.inner_ref().inner_ref().as_slice());
-
-        writer.write([9, 10, 11]);
-        assert_eq!([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
-                   writer.inner_ref().inner_ref().as_slice());
-
-        writer.flush();
-        assert_eq!([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
-                   writer.inner_ref().inner_ref().as_slice());
-    }
-
-    // This is just here to make sure that we don't infinite loop in the
-    // newtype struct autoderef weirdness
-    #[test]
-    fn test_buffered_stream() {
-        use rt;
-        struct S;
-
-        impl rt::io::Writer for S {
-            fn write(&mut self, _: &[u8]) {}
-        }
-
-        impl rt::io::Reader for S {
-            fn read(&mut self, _: &mut [u8]) -> Option<uint> { None }
-            fn eof(&mut self) -> bool { true }
-        }
-
-        let mut stream = BufferedStream::new(S);
-        let mut buf = [];
-        stream.read(buf);
-        stream.eof();
-        stream.write(buf);
-        stream.flush();
-    }
-
-    #[test]
-    fn test_read_until() {
-        let inner = MemReader::new(~[0, 1, 2, 1, 0]);
-        let mut reader = BufferedReader::with_capacity(2, inner);
-        assert_eq!(reader.read_until(0), Some(~[0]));
-        assert_eq!(reader.read_until(2), Some(~[1, 2]));
-        assert_eq!(reader.read_until(1), Some(~[1]));
-        assert_eq!(reader.read_until(8), Some(~[0]));
-        assert_eq!(reader.read_until(9), None);
-    }
-
-    #[test]
-    fn test_line_buffer() {
-        let mut writer = LineBufferedWriter::new(MemWriter::new());
-        writer.write([0]);
-        assert_eq!(*writer.inner_ref().inner_ref(), ~[]);
-        writer.write([1]);
-        assert_eq!(*writer.inner_ref().inner_ref(), ~[]);
-        writer.flush();
-        assert_eq!(*writer.inner_ref().inner_ref(), ~[0, 1]);
-        writer.write([0, '\n' as u8, 1]);
-        assert_eq!(*writer.inner_ref().inner_ref(), ~[0, 1, 0, '\n' as u8]);
-        writer.flush();
-        assert_eq!(*writer.inner_ref().inner_ref(), ~[0, 1, 0, '\n' as u8, 1]);
-    }
-}
diff --git a/src/libstd/rt/io/comm_adapters.rs b/src/libstd/rt/io/comm_adapters.rs
deleted file mode 100644 (file)
index 98dbec2..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-// 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.
-
-use option::Option;
-use comm::{GenericPort, GenericChan};
-use super::{Reader, Writer};
-
-struct PortReader<P>;
-
-impl<P: GenericPort<~[u8]>> PortReader<P> {
-    pub fn new(_port: P) -> PortReader<P> { fail!() }
-}
-
-impl<P: GenericPort<~[u8]>> Reader for PortReader<P> {
-    fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail!() }
-
-    fn eof(&mut self) -> bool { fail!() }
-}
-
-struct ChanWriter<C>;
-
-impl<C: GenericChan<~[u8]>> ChanWriter<C> {
-    pub fn new(_chan: C) -> ChanWriter<C> { fail!() }
-}
-
-impl<C: GenericChan<~[u8]>> Writer for ChanWriter<C> {
-    fn write(&mut self, _buf: &[u8]) { fail!() }
-}
-
-struct ReaderPort<R>;
-
-impl<R: Reader> ReaderPort<R> {
-    pub fn new(_reader: R) -> ReaderPort<R> { fail!() }
-}
-
-impl<R: Reader> GenericPort<~[u8]> for ReaderPort<R> {
-    fn recv(&self) -> ~[u8] { fail!() }
-
-    fn try_recv(&self) -> Option<~[u8]> { fail!() }
-}
-
-struct WriterChan<W>;
-
-impl<W: Writer> WriterChan<W> {
-    pub fn new(_writer: W) -> WriterChan<W> { fail!() }
-}
-
-impl<W: Writer> GenericChan<~[u8]> for WriterChan<W> {
-    fn send(&self, _x: ~[u8]) { fail!() }
-}
diff --git a/src/libstd/rt/io/extensions.rs b/src/libstd/rt/io/extensions.rs
deleted file mode 100644 (file)
index 2617929..0000000
+++ /dev/null
@@ -1,490 +0,0 @@
-// 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.
-
-//! Utility mixins that apply to all Readers and Writers
-
-// XXX: Not sure how this should be structured
-// XXX: Iteration should probably be considered separately
-
-use iter::Iterator;
-use option::Option;
-use rt::io::{Reader, Decorator};
-
-/// An iterator that reads a single byte on each iteration,
-/// until `.read_byte()` returns `None`.
-///
-/// # Notes about the Iteration Protocol
-///
-/// The `ByteIterator` may yield `None` and thus terminate
-/// an iteration, but continue to yield elements if iteration
-/// is attempted again.
-///
-/// # Failure
-///
-/// Raises the same conditions as the `read` method, for
-/// each call to its `.next()` method.
-/// Yields `None` if the condition is handled.
-pub struct ByteIterator<T> {
-    priv reader: T,
-}
-
-impl<R: Reader> ByteIterator<R> {
-    pub fn new(r: R) -> ByteIterator<R> {
-        ByteIterator { reader: r }
-    }
-}
-
-impl<R> Decorator<R> for ByteIterator<R> {
-    fn inner(self) -> R { self.reader }
-    fn inner_ref<'a>(&'a self) -> &'a R { &self.reader }
-    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut R { &mut self.reader }
-}
-
-impl<'self, R: Reader> Iterator<u8> for ByteIterator<R> {
-    #[inline]
-    fn next(&mut self) -> Option<u8> {
-        self.reader.read_byte()
-    }
-}
-
-pub fn u64_to_le_bytes<T>(n: u64, size: uint,
-                          f: &fn(v: &[u8]) -> T) -> T {
-    assert!(size <= 8u);
-    match size {
-      1u => f(&[n as u8]),
-      2u => f(&[n as u8,
-              (n >> 8) as u8]),
-      4u => f(&[n as u8,
-              (n >> 8) as u8,
-              (n >> 16) as u8,
-              (n >> 24) as u8]),
-      8u => f(&[n as u8,
-              (n >> 8) as u8,
-              (n >> 16) as u8,
-              (n >> 24) as u8,
-              (n >> 32) as u8,
-              (n >> 40) as u8,
-              (n >> 48) as u8,
-              (n >> 56) as u8]),
-      _ => {
-
-        let mut bytes: ~[u8] = ~[];
-        let mut i = size;
-        let mut n = n;
-        while i > 0u {
-            bytes.push((n & 255_u64) as u8);
-            n >>= 8_u64;
-            i -= 1u;
-        }
-        f(bytes)
-      }
-    }
-}
-
-pub fn u64_to_be_bytes<T>(n: u64, size: uint,
-                           f: &fn(v: &[u8]) -> T) -> T {
-    assert!(size <= 8u);
-    match size {
-      1u => f(&[n as u8]),
-      2u => f(&[(n >> 8) as u8,
-              n as u8]),
-      4u => f(&[(n >> 24) as u8,
-              (n >> 16) as u8,
-              (n >> 8) as u8,
-              n as u8]),
-      8u => f(&[(n >> 56) as u8,
-              (n >> 48) as u8,
-              (n >> 40) as u8,
-              (n >> 32) as u8,
-              (n >> 24) as u8,
-              (n >> 16) as u8,
-              (n >> 8) as u8,
-              n as u8]),
-      _ => {
-        let mut bytes: ~[u8] = ~[];
-        let mut i = size;
-        while i > 0u {
-            let shift = ((i - 1u) * 8u) as u64;
-            bytes.push((n >> shift) as u8);
-            i -= 1u;
-        }
-        f(bytes)
-      }
-    }
-}
-
-pub fn u64_from_be_bytes(data: &[u8],
-                         start: uint,
-                         size: uint)
-                      -> u64 {
-    let mut sz = size;
-    assert!((sz <= 8u));
-    let mut val = 0_u64;
-    let mut pos = start;
-    while sz > 0u {
-        sz -= 1u;
-        val += (data[pos] as u64) << ((sz * 8u) as u64);
-        pos += 1u;
-    }
-    return val;
-}
-
-#[cfg(test)]
-mod test {
-    use option::{None, Option, Some};
-    use rt::io::mem::{MemReader, MemWriter};
-    use rt::io::{Reader, io_error, placeholder_error};
-
-    struct InitialZeroByteReader {
-        count: int,
-    }
-
-    impl Reader for InitialZeroByteReader {
-        fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-            if self.count == 0 {
-                self.count = 1;
-                Some(0)
-            } else {
-                buf[0] = 10;
-                Some(1)
-            }
-        }
-        fn eof(&mut self) -> bool {
-            false
-        }
-    }
-
-    struct EofReader;
-
-    impl Reader for EofReader {
-        fn read(&mut self, _: &mut [u8]) -> Option<uint> {
-            None
-        }
-        fn eof(&mut self) -> bool {
-            false
-        }
-    }
-
-    struct ErroringReader;
-
-    impl Reader for ErroringReader {
-        fn read(&mut self, _: &mut [u8]) -> Option<uint> {
-            io_error::cond.raise(placeholder_error());
-            None
-        }
-        fn eof(&mut self) -> bool {
-            false
-        }
-    }
-
-    struct PartialReader {
-        count: int,
-    }
-
-    impl Reader for PartialReader {
-        fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-            if self.count == 0 {
-                self.count = 1;
-                buf[0] = 10;
-                buf[1] = 11;
-                Some(2)
-            } else {
-                buf[0] = 12;
-                buf[1] = 13;
-                Some(2)
-            }
-        }
-        fn eof(&mut self) -> bool {
-            false
-        }
-    }
-
-    struct ErroringLaterReader {
-        count: int,
-    }
-
-    impl Reader for ErroringLaterReader {
-        fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-            if self.count == 0 {
-                self.count = 1;
-                buf[0] = 10;
-                Some(1)
-            } else {
-                io_error::cond.raise(placeholder_error());
-                None
-            }
-        }
-        fn eof(&mut self) -> bool {
-            false
-        }
-    }
-
-    struct ThreeChunkReader {
-        count: int,
-    }
-
-    impl Reader for ThreeChunkReader {
-        fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-            if self.count == 0 {
-                self.count = 1;
-                buf[0] = 10;
-                buf[1] = 11;
-                Some(2)
-            } else if self.count == 1 {
-                self.count = 2;
-                buf[0] = 12;
-                buf[1] = 13;
-                Some(2)
-            } else {
-                None
-            }
-        }
-        fn eof(&mut self) -> bool {
-            false
-        }
-    }
-
-    #[test]
-    fn read_byte() {
-        let mut reader = MemReader::new(~[10]);
-        let byte = reader.read_byte();
-        assert!(byte == Some(10));
-    }
-
-    #[test]
-    fn read_byte_0_bytes() {
-        let mut reader = InitialZeroByteReader {
-            count: 0,
-        };
-        let byte = reader.read_byte();
-        assert!(byte == Some(10));
-    }
-
-    #[test]
-    fn read_byte_eof() {
-        let mut reader = EofReader;
-        let byte = reader.read_byte();
-        assert!(byte == None);
-    }
-
-    #[test]
-    fn read_byte_error() {
-        let mut reader = ErroringReader;
-        do io_error::cond.trap(|_| {
-        }).inside {
-            let byte = reader.read_byte();
-            assert!(byte == None);
-        }
-    }
-
-    #[test]
-    fn bytes_0_bytes() {
-        let reader = InitialZeroByteReader {
-            count: 0,
-        };
-        let byte = reader.bytes().next();
-        assert!(byte == Some(10));
-    }
-
-    #[test]
-    fn bytes_eof() {
-        let reader = EofReader;
-        let byte = reader.bytes().next();
-        assert!(byte == None);
-    }
-
-    #[test]
-    fn bytes_error() {
-        let reader = ErroringReader;
-        let mut it = reader.bytes();
-        do io_error::cond.trap(|_| ()).inside {
-            let byte = it.next();
-            assert!(byte == None);
-        }
-    }
-
-    #[test]
-    fn read_bytes() {
-        let mut reader = MemReader::new(~[10, 11, 12, 13]);
-        let bytes = reader.read_bytes(4);
-        assert!(bytes == ~[10, 11, 12, 13]);
-    }
-
-    #[test]
-    fn read_bytes_partial() {
-        let mut reader = PartialReader {
-            count: 0,
-        };
-        let bytes = reader.read_bytes(4);
-        assert!(bytes == ~[10, 11, 12, 13]);
-    }
-
-    #[test]
-    fn read_bytes_eof() {
-        let mut reader = MemReader::new(~[10, 11]);
-        do io_error::cond.trap(|_| {
-        }).inside {
-            assert!(reader.read_bytes(4) == ~[10, 11]);
-        }
-    }
-
-    #[test]
-    fn push_bytes() {
-        let mut reader = MemReader::new(~[10, 11, 12, 13]);
-        let mut buf = ~[8, 9];
-        reader.push_bytes(&mut buf, 4);
-        assert!(buf == ~[8, 9, 10, 11, 12, 13]);
-    }
-
-    #[test]
-    fn push_bytes_partial() {
-        let mut reader = PartialReader {
-            count: 0,
-        };
-        let mut buf = ~[8, 9];
-        reader.push_bytes(&mut buf, 4);
-        assert!(buf == ~[8, 9, 10, 11, 12, 13]);
-    }
-
-    #[test]
-    fn push_bytes_eof() {
-        let mut reader = MemReader::new(~[10, 11]);
-        let mut buf = ~[8, 9];
-        do io_error::cond.trap(|_| {
-        }).inside {
-            reader.push_bytes(&mut buf, 4);
-            assert!(buf == ~[8, 9, 10, 11]);
-        }
-    }
-
-    #[test]
-    fn push_bytes_error() {
-        let mut reader = ErroringLaterReader {
-            count: 0,
-        };
-        let mut buf = ~[8, 9];
-        do io_error::cond.trap(|_| { } ).inside {
-            reader.push_bytes(&mut buf, 4);
-        }
-        assert!(buf == ~[8, 9, 10]);
-    }
-
-    #[test]
-    #[should_fail]
-    fn push_bytes_fail_reset_len() {
-        // push_bytes unsafely sets the vector length. This is testing that
-        // upon failure the length is reset correctly.
-        let mut reader = ErroringLaterReader {
-            count: 0,
-        };
-        let buf = @mut ~[8, 9];
-        do (|| {
-            reader.push_bytes(&mut *buf, 4);
-        }).finally {
-            // NB: Using rtassert here to trigger abort on failure since this is a should_fail test
-            // FIXME: #7049 This fails because buf is still borrowed
-            //rtassert!(*buf == ~[8, 9, 10]);
-        }
-    }
-
-    #[test]
-    fn read_to_end() {
-        let mut reader = ThreeChunkReader {
-            count: 0,
-        };
-        let buf = reader.read_to_end();
-        assert!(buf == ~[10, 11, 12, 13]);
-    }
-
-    #[test]
-    #[should_fail]
-    fn read_to_end_error() {
-        let mut reader = ThreeChunkReader {
-            count: 0,
-        };
-        let buf = reader.read_to_end();
-        assert!(buf == ~[10, 11]);
-    }
-
-    #[test]
-    fn test_read_write_le_mem() {
-        let uints = [0, 1, 2, 42, 10_123, 100_123_456, ::u64::max_value];
-
-        let mut writer = MemWriter::new();
-        for i in uints.iter() {
-            writer.write_le_u64(*i);
-        }
-
-        let mut reader = MemReader::new(writer.inner());
-        for i in uints.iter() {
-            assert!(reader.read_le_u64() == *i);
-        }
-    }
-
-
-    #[test]
-    fn test_read_write_be() {
-        let uints = [0, 1, 2, 42, 10_123, 100_123_456, ::u64::max_value];
-
-        let mut writer = MemWriter::new();
-        for i in uints.iter() {
-            writer.write_be_u64(*i);
-        }
-
-        let mut reader = MemReader::new(writer.inner());
-        for i in uints.iter() {
-            assert!(reader.read_be_u64() == *i);
-        }
-    }
-
-    #[test]
-    fn test_read_be_int_n() {
-        let ints = [::i32::min_value, -123456, -42, -5, 0, 1, ::i32::max_value];
-
-        let mut writer = MemWriter::new();
-        for i in ints.iter() {
-            writer.write_be_i32(*i);
-        }
-
-        let mut reader = MemReader::new(writer.inner());
-        for i in ints.iter() {
-            // this tests that the sign extension is working
-            // (comparing the values as i32 would not test this)
-            assert!(reader.read_be_int_n(4) == *i as i64);
-        }
-    }
-
-    #[test]
-    fn test_read_f32() {
-        //big-endian floating-point 8.1250
-        let buf = ~[0x41, 0x02, 0x00, 0x00];
-
-        let mut writer = MemWriter::new();
-        writer.write(buf);
-
-        let mut reader = MemReader::new(writer.inner());
-        let f = reader.read_be_f32();
-        assert!(f == 8.1250);
-    }
-
-    #[test]
-    fn test_read_write_f32() {
-        let f:f32 = 8.1250;
-
-        let mut writer = MemWriter::new();
-        writer.write_be_f32(f);
-        writer.write_le_f32(f);
-
-        let mut reader = MemReader::new(writer.inner());
-        assert!(reader.read_be_f32() == 8.1250);
-        assert!(reader.read_le_f32() == 8.1250);
-    }
-
-}
diff --git a/src/libstd/rt/io/flate.rs b/src/libstd/rt/io/flate.rs
deleted file mode 100644 (file)
index 8a5aa17..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-// 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.
-
-//! Some various other I/O types
-
-// FIXME(#3660): should move to libextra
-
-use prelude::*;
-use super::*;
-
-/// A Writer decorator that compresses using the 'deflate' scheme
-pub struct DeflateWriter<W> {
-    priv inner_writer: W
-}
-
-impl<W: Writer> DeflateWriter<W> {
-    pub fn new(inner_writer: W) -> DeflateWriter<W> {
-        DeflateWriter {
-            inner_writer: inner_writer
-        }
-    }
-}
-
-impl<W: Writer> Writer for DeflateWriter<W> {
-    fn write(&mut self, _buf: &[u8]) { fail!() }
-
-    fn flush(&mut self) { fail!() }
-}
-
-impl<W: Writer> Decorator<W> for DeflateWriter<W> {
-    fn inner(self) -> W {
-        match self {
-            DeflateWriter { inner_writer: w } => w
-        }
-    }
-
-    fn inner_ref<'a>(&'a self) -> &'a W {
-        match *self {
-            DeflateWriter { inner_writer: ref w } => w
-        }
-    }
-
-    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut W {
-        match *self {
-            DeflateWriter { inner_writer: ref mut w } => w
-        }
-    }
-}
-
-/// A Reader decorator that decompresses using the 'deflate' scheme
-pub struct InflateReader<R> {
-    priv inner_reader: R
-}
-
-impl<R: Reader> InflateReader<R> {
-    pub fn new(inner_reader: R) -> InflateReader<R> {
-        InflateReader {
-            inner_reader: inner_reader
-        }
-    }
-}
-
-impl<R: Reader> Reader for InflateReader<R> {
-    fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail!() }
-
-    fn eof(&mut self) -> bool { fail!() }
-}
-
-impl<R: Reader> Decorator<R> for InflateReader<R> {
-    fn inner(self) -> R {
-        match self {
-            InflateReader { inner_reader: r } => r
-        }
-    }
-
-    fn inner_ref<'a>(&'a self) -> &'a R {
-        match *self {
-            InflateReader { inner_reader: ref r } => r
-        }
-    }
-
-    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut R {
-        match *self {
-            InflateReader { inner_reader: ref mut r } => r
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use prelude::*;
-    use super::*;
-    use super::super::mem::*;
-    use super::super::Decorator;
-
-    use str;
-
-    #[test]
-    #[ignore]
-    fn smoke_test() {
-        let mem_writer = MemWriter::new();
-        let mut deflate_writer = DeflateWriter::new(mem_writer);
-        let in_msg = "test";
-        let in_bytes = in_msg.as_bytes();
-        deflate_writer.write(in_bytes);
-        deflate_writer.flush();
-        let buf = deflate_writer.inner().inner();
-        let mem_reader = MemReader::new(buf);
-        let mut inflate_reader = InflateReader::new(mem_reader);
-        let mut out_bytes = [0, .. 100];
-        let bytes_read = inflate_reader.read(out_bytes).unwrap();
-        assert_eq!(bytes_read, in_bytes.len());
-        let out_msg = str::from_utf8(out_bytes);
-        assert!(in_msg == out_msg);
-    }
-}
diff --git a/src/libstd/rt/io/fs.rs b/src/libstd/rt/io/fs.rs
deleted file mode 100644 (file)
index 06c0730..0000000
+++ /dev/null
@@ -1,1288 +0,0 @@
-// 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.
-
-/*! Synchronous File I/O
-
-This module provides a set of functions and traits for working
-with regular files & directories on a filesystem.
-
-At the top-level of the module are a set of freestanding functions, associated
-with various filesystem operations. They all operate on a `Path` object.
-
-All operations in this module, including those as part of `File` et al
-block the task during execution. Most will raise `std::rt::io::io_error`
-conditions in the event of failure.
-
-Also included in this module is an implementation block on the `Path` object
-defined in `std::path::Path`. The impl adds useful methods about inspecting the
-metadata of a file. This includes getting the `stat` information, reading off
-particular bits of it, etc.
-
-# Example
-
-    use std::rt::io::{File, fs};
-
-    let path = Path::new("foo.txt");
-
-    // create the file, whether it exists or not
-    let mut file = File::create(&path);
-    file.write(bytes!("foobar"));
-
-    // open the file in read-only mode
-    let mut file = File::open(&path);
-    file.read_to_end();
-
-    println!("{}", path.stat().size);
-    fs::symlink(&path, &Path::new("bar.txt"));
-    fs::unlink(&path);
-
-*/
-
-use c_str::ToCStr;
-use iter::Iterator;
-use super::{Reader, Writer, Seek};
-use super::{SeekStyle, Read, Write, Open, IoError, Truncate,
-            FileMode, FileAccess, FileStat, io_error, FilePermission};
-use rt::rtio::{RtioFileStream, IoFactory, with_local_io};
-use rt::io;
-use option::{Some, None, Option};
-use result::{Ok, Err, Result};
-use path;
-use path::{Path, GenericPath};
-use vec::OwnedVector;
-
-/// Unconstrained file access type that exposes read and write operations
-///
-/// Can be constructed via `File::open()`, `File::create()`, and
-/// `File::open_mode()`.
-///
-/// # Errors
-///
-/// This type will raise an io_error condition if operations are attempted against
-/// it for which its underlying file descriptor was not configured at creation
-/// time, via the `FileAccess` parameter to `File::open_mode()`.
-pub struct File {
-    priv fd: ~RtioFileStream,
-    priv path: Path,
-    priv last_nread: int,
-}
-
-fn io_raise<T>(f: &fn(io: &mut IoFactory) -> Result<T, IoError>) -> Option<T> {
-    do with_local_io |io| {
-        match f(io) {
-            Ok(t) => Some(t),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
-    }
-}
-
-impl File {
-    /// Open a file at `path` in the mode specified by the `mode` and `access`
-    /// arguments
-    ///
-    /// # Example
-    ///
-    ///     use std::rt::io::{File, io_error, Open, ReadWrite};
-    ///
-    ///     let p = Path::new("/some/file/path.txt");
-    ///
-    ///     do io_error::cond.trap(|_| {
-    ///         // hoo-boy...
-    ///     }).inside {
-    ///         let file = match File::open_mode(&p, Open, ReadWrite) {
-    ///             Some(s) => s,
-    ///             None => fail!("whoops! I'm sure this raised, anyways..")
-    ///         };
-    ///         // do some stuff with that file
-    ///
-    ///         // the file will be closed at the end of this block
-    ///     }
-    ///     // ..
-    ///
-    /// `FileMode` and `FileAccess` provide information about the permissions
-    /// context in which a given stream is created. More information about them
-    /// can be found in `std::rt::io`'s docs. If a file is opened with `Write`
-    /// or `ReadWrite` access, then it will be created it it does not already
-    /// exist.
-    ///
-    /// Note that, with this function, a `File` is returned regardless of the
-    /// access-limitations indicated by `FileAccess` (e.g. calling `write` on a
-    /// `File` opened as `Read` will raise an `io_error` condition at runtime).
-    ///
-    /// # Errors
-    ///
-    /// This function will raise an `io_error` condition under a number of
-    /// different circumstances, to include but not limited to:
-    ///
-    /// * Opening a file that does not exist with `Read` access.
-    /// * Attempting to open a file with a `FileAccess` that the user lacks
-    ///   permissions for
-    /// * Filesystem-level errors (full disk, etc)
-    pub fn open_mode(path: &Path,
-                     mode: FileMode,
-                     access: FileAccess) -> Option<File> {
-        do with_local_io |io| {
-            match io.fs_open(&path.to_c_str(), mode, access) {
-                Ok(fd) => Some(File {
-                    path: path.clone(),
-                    fd: fd,
-                    last_nread: -1
-                }),
-                Err(ioerr) => {
-                    io_error::cond.raise(ioerr);
-                    None
-                }
-            }
-        }
-    }
-
-    /// Attempts to open a file in read-only mode. This function is equivalent to
-    /// `File::open_mode(path, Open, Read)`, and will raise all of the same
-    /// errors that `File::open_mode` does.
-    ///
-    /// For more information, see the `File::open_mode` function.
-    ///
-    /// # Example
-    ///
-    ///     use std::rt::io::File;
-    ///
-    ///     let contents = File::open(&Path::new("foo.txt")).read_to_end();
-    pub fn open(path: &Path) -> Option<File> {
-        File::open_mode(path, Open, Read)
-    }
-
-    /// Attempts to create a file in write-only mode. This function is
-    /// equivalent to `File::open_mode(path, Truncate, Write)`, and will
-    /// raise all of the same errors that `File::open_mode` does.
-    ///
-    /// For more information, see the `File::open_mode` function.
-    ///
-    /// # Example
-    ///
-    ///     use std::rt::io::File;
-    ///
-    ///     let mut f = File::create(&Path::new("foo.txt"));
-    ///     f.write(bytes!("This is a sample file"));
-    pub fn create(path: &Path) -> Option<File> {
-        File::open_mode(path, Truncate, Write)
-    }
-
-    /// Returns the original path which was used to open this file.
-    pub fn path<'a>(&'a self) -> &'a Path {
-        &self.path
-    }
-
-    /// Synchronizes all modifications to this file to its permanent storage
-    /// device. This will flush any internal buffers necessary to perform this
-    /// operation.
-    ///
-    /// # Errors
-    ///
-    /// This function will raise on the `io_error` condition on failure.
-    pub fn fsync(&mut self) {
-        self.fd.fsync();
-    }
-
-    /// This function is similar to `fsync`, except that it may not synchronize
-    /// file metadata to the filesystem. This is intended for use case which
-    /// must synchronize content, but don't need the metadata on disk. The goal
-    /// of this method is to reduce disk operations.
-    ///
-    /// # Errors
-    ///
-    /// This function will raise on the `io_error` condition on failure.
-    pub fn datasync(&mut self) {
-        self.fd.datasync();
-    }
-
-    /// Either truncates or extends the underlying file, as extended from the
-    /// file's current position. This is equivalent to the unix `truncate`
-    /// function.
-    ///
-    /// The offset given is added to the file's current position and the result
-    /// is the new size of the file. If the new size is less than the current
-    /// size, then the file is truncated. If the new size is greater than the
-    /// current size, then the file is expanded to be filled with 0s.
-    ///
-    /// # Errors
-    ///
-    /// On error, this function will raise on the `io_error` condition.
-    pub fn truncate(&mut self, offset: i64) {
-        self.fd.truncate(offset);
-    }
-}
-
-/// Unlink a file from the underlying filesystem.
-///
-/// # Example
-///
-///     use std::rt::io::fs;
-///
-///     let p = Path::new("/some/file/path.txt");
-///     fs::unlink(&p);
-///     // if we made it here without failing, then the
-///     // unlink operation was successful
-///
-/// Note that, just because an unlink call was successful, it is not
-/// guaranteed that a file is immediately deleted (e.g. depending on
-/// platform, other open file descriptors may prevent immediate removal)
-///
-/// # Errors
-///
-/// This function will raise an `io_error` condition if the path points to a
-/// directory, the user lacks permissions to remove the file, or if some
-/// other filesystem-level error occurs.
-pub fn unlink(path: &Path) {
-    do io_raise |io| { io.fs_unlink(&path.to_c_str()) };
-}
-
-/// Given a path, query the file system to get information about a file,
-/// directory, etc. This function will traverse symlinks to query
-/// information about the destination file.
-///
-/// Returns a fully-filled out stat structure on succes, and on failure it
-/// will return a dummy stat structure (it is expected that the condition
-/// raised is handled as well).
-///
-/// # Example
-///
-///     use std::rt::io;
-///     use std::rt::io::fs;
-///
-///     let p = Path::new("/some/file/path.txt");
-///     match io::result(|| fs::stat(&p)) {
-///         Ok(stat) => { /* ... */ }
-///         Err(e) => { /* handle error */ }
-///     }
-///
-/// # Errors
-///
-/// This call will raise an `io_error` condition if the user lacks the
-/// requisite permissions to perform a `stat` call on the given path or if
-/// there is no entry in the filesystem at the provided path.
-pub fn stat(path: &Path) -> FileStat {
-    do io_raise |io| {
-        io.fs_stat(&path.to_c_str())
-    }.unwrap_or_else(dummystat)
-}
-
-fn dummystat() -> FileStat {
-    FileStat {
-        path: Path::new(""),
-        size: 0,
-        kind: io::TypeFile,
-        perm: 0,
-        created: 0,
-        modified: 0,
-        accessed: 0,
-        unstable: io::UnstableFileStat {
-            device: 0,
-            inode: 0,
-            rdev: 0,
-            nlink: 0,
-            uid: 0,
-            gid: 0,
-            blksize: 0,
-            blocks: 0,
-            flags: 0,
-            gen: 0,
-        }
-    }
-}
-
-/// Perform the same operation as the `stat` function, except that this
-/// function does not traverse through symlinks. This will return
-/// information about the symlink file instead of the file that it points
-/// to.
-///
-/// # Errors
-///
-/// See `stat`
-pub fn lstat(path: &Path) -> FileStat {
-    do io_raise |io| {
-        io.fs_lstat(&path.to_c_str())
-    }.unwrap_or_else(dummystat)
-}
-
-/// Rename a file or directory to a new name.
-///
-/// # Example
-///
-///     use std::rt::io::fs;
-///
-///     fs::rename(&Path::new("foo"), &Path::new("bar"));
-///     // Oh boy, nothing was raised!
-///
-/// # Errors
-///
-/// Will raise an `io_error` condition if the provided `path` doesn't exist,
-/// the process lacks permissions to view the contents, or if some other
-/// intermittent I/O error occurs.
-pub fn rename(from: &Path, to: &Path) {
-    do io_raise |io| {
-        io.fs_rename(&from.to_c_str(), &to.to_c_str())
-    };
-}
-
-/// Copies the contents of one file to another. This function will also
-/// copy the permission bits of the original file to the destination file.
-///
-/// Note that if `from` and `to` both point to the same file, then the file
-/// will likely get truncated by this operation.
-///
-/// # Example
-///
-///     use std::rt::io::fs;
-///
-///     fs::copy(&Path::new("foo.txt"), &Path::new("bar.txt"));
-///     // Oh boy, nothing was raised!
-///
-/// # Errors
-///
-/// Will raise an `io_error` condition is the following situtations, but is
-/// not limited to just these cases:
-///
-/// * The `from` path is not a file
-/// * The `from` file does not exist
-/// * The current process does not have the permission rights to access
-///   `from` or write `to`
-///
-/// Note that this copy is not atomic in that once the destination is
-/// ensured to not exist, there is nothing preventing the destination from
-/// being created and then destroyed by this operation.
-pub fn copy(from: &Path, to: &Path) {
-    if !from.is_file() {
-        return io_error::cond.raise(IoError {
-            kind: io::MismatchedFileTypeForOperation,
-            desc: "the source path is not an existing file",
-            detail: None,
-        });
-    }
-
-    let mut reader = match File::open(from) { Some(f) => f, None => return };
-    let mut writer = match File::create(to) { Some(f) => f, None => return };
-    let mut buf = [0, ..io::DEFAULT_BUF_SIZE];
-
-    loop {
-        match reader.read(buf) {
-            Some(amt) => writer.write(buf.slice_to(amt)),
-            None => break
-        }
-    }
-
-    chmod(to, from.stat().perm)
-}
-
-/// Changes the permission mode bits found on a file or a directory. This
-/// function takes a mask from the `io` module
-///
-/// # Example
-///
-///     use std::rt::io;
-///     use std::rt::io::fs;
-///
-///     fs::chmod(&Path::new("file.txt"), io::UserFile);
-///     fs::chmod(&Path::new("file.txt"), io::UserRead | io::UserWrite);
-///     fs::chmod(&Path::new("dir"),      io::UserDir);
-///     fs::chmod(&Path::new("file.exe"), io::UserExec);
-///
-/// # Errors
-///
-/// If this funciton encounters an I/O error, it will raise on the `io_error`
-/// condition. Some possible error situations are not having the permission to
-/// change the attributes of a file or the file not existing.
-pub fn chmod(path: &Path, mode: io::FilePermission) {
-    do io_raise |io| {
-        io.fs_chmod(&path.to_c_str(), mode)
-    };
-}
-
-/// Change the user and group owners of a file at the specified path.
-///
-/// # Errors
-///
-/// This funtion will raise on the `io_error` condition on failure.
-pub fn chown(path: &Path, uid: int, gid: int) {
-    do io_raise |io| { io.fs_chown(&path.to_c_str(), uid, gid) };
-}
-
-/// Creates a new hard link on the filesystem. The `dst` path will be a
-/// link pointing to the `src` path. Note that systems often require these
-/// two paths to both be located on the same filesystem.
-///
-/// # Errors
-///
-/// This function will raise on the `io_error` condition on failure.
-pub fn link(src: &Path, dst: &Path) {
-    do io_raise |io| { io.fs_link(&src.to_c_str(), &dst.to_c_str()) };
-}
-
-/// Creates a new symbolic link on the filesystem. The `dst` path will be a
-/// symlink pointing to the `src` path.
-///
-/// # Errors
-///
-/// This function will raise on the `io_error` condition on failure.
-pub fn symlink(src: &Path, dst: &Path) {
-    do io_raise |io| { io.fs_symlink(&src.to_c_str(), &dst.to_c_str()) };
-}
-
-/// Reads a symlink, returning the file that the symlink points to.
-///
-/// # Errors
-///
-/// This function will raise on the `io_error` condition on failure. Failure
-/// conditions include reading a file that does not exist or reading a file
-/// which is not a symlink.
-pub fn readlink(path: &Path) -> Option<Path> {
-    do io_raise |io| { io.fs_readlink(&path.to_c_str()) }
-}
-
-/// Create a new, empty directory at the provided path
-///
-/// # Example
-///
-///     use std::libc::S_IRWXU;
-///     use std::rt::io::fs;
-///
-///     let p = Path::new("/some/dir");
-///     fs::mkdir(&p, S_IRWXU as int);
-///     // If we got here, our directory exists! Horray!
-///
-/// # Errors
-///
-/// This call will raise an `io_error` condition if the user lacks permissions
-/// to make a new directory at the provided path, or if the directory already
-/// exists.
-pub fn mkdir(path: &Path, mode: FilePermission) {
-    do io_raise |io| {
-        io.fs_mkdir(&path.to_c_str(), mode)
-    };
-}
-
-/// Remove an existing, empty directory
-///
-/// # Example
-///
-///     use std::rt::io::fs;
-///
-///     let p = Path::new("/some/dir");
-///     fs::rmdir(&p);
-///     // good riddance, you mean ol' directory
-///
-/// # Errors
-///
-/// This call will raise an `io_error` condition if the user lacks permissions
-/// to remove the directory at the provided path, or if the directory isn't
-/// empty.
-pub fn rmdir(path: &Path) {
-    do io_raise |io| {
-        io.fs_rmdir(&path.to_c_str())
-    };
-}
-
-/// Retrieve a vector containing all entries within a provided directory
-///
-/// # Example
-///
-///     use std::rt::io::fs;
-///
-///     // one possible implementation of fs::walk_dir only visiting files
-///     fn visit_dirs(dir: &Path, cb: &fn(&Path)) {
-///         if dir.is_dir() {
-///             let contents = fs::readdir(dir).unwrap();
-///             for entry in contents.iter() {
-///                 if entry.is_dir() { visit_dirs(entry, cb); }
-///                 else { cb(entry); }
-///             }
-///         }
-///         else { fail!("nope"); }
-///     }
-///
-/// # Errors
-///
-/// Will raise an `io_error` condition if the provided `from` doesn't exist,
-/// the process lacks permissions to view the contents or if the `path` points
-/// at a non-directory file
-pub fn readdir(path: &Path) -> ~[Path] {
-    do io_raise |io| {
-        io.fs_readdir(&path.to_c_str(), 0)
-    }.unwrap_or_else(|| ~[])
-}
-
-/// Returns an iterator which will recursively walk the directory structure
-/// rooted at `path`. The path given will not be iterated over, and this will
-/// perform iteration in a top-down order.
-pub fn walk_dir(path: &Path) -> WalkIterator {
-    WalkIterator { stack: readdir(path) }
-}
-
-/// An iterator which walks over a directory
-pub struct WalkIterator {
-    priv stack: ~[Path],
-}
-
-impl Iterator<Path> for WalkIterator {
-    fn next(&mut self) -> Option<Path> {
-        match self.stack.shift_opt() {
-            Some(path) => {
-                if path.is_dir() {
-                    self.stack.push_all_move(readdir(&path));
-                }
-                Some(path)
-            }
-            None => None
-        }
-    }
-}
-
-/// Recursively create a directory and all of its parent components if they
-/// are missing.
-///
-/// # Errors
-///
-/// This function will raise on the `io_error` condition if an error
-/// happens, see `fs::mkdir` for more information about error conditions
-/// and performance.
-pub fn mkdir_recursive(path: &Path, mode: FilePermission) {
-    // tjc: if directory exists but with different permissions,
-    // should we return false?
-    if path.is_dir() {
-        return
-    }
-    if path.filename().is_some() {
-        mkdir_recursive(&path.dir_path(), mode);
-    }
-    mkdir(path, mode)
-}
-
-/// Removes a directory at this path, after removing all its contents. Use
-/// carefully!
-///
-/// # Errors
-///
-/// This function will raise on the `io_error` condition if an error
-/// happens. See `file::unlink` and `fs::readdir` for possible error
-/// conditions.
-pub fn rmdir_recursive(path: &Path) {
-    let children = readdir(path);
-    for child in children.iter() {
-        if child.is_dir() {
-            rmdir_recursive(child);
-        } else {
-            unlink(child);
-        }
-    }
-    // Directory should now be empty
-    rmdir(path);
-}
-
-/// Changes the timestamps for a file's last modification and access time.
-/// The file at the path specified will have its last access time set to
-/// `atime` and its modification time set to `mtime`. The times specified should
-/// be in milliseconds.
-///
-/// # Errors
-///
-/// This function will raise on the `io_error` condition if an error
-/// happens.
-// FIXME(#10301) these arguments should not be u64
-pub fn change_file_times(path: &Path, atime: u64, mtime: u64) {
-    do io_raise |io| {
-        io.fs_utime(&path.to_c_str(), atime, mtime)
-    };
-}
-
-impl Reader for File {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        match self.fd.read(buf) {
-            Ok(read) => {
-                self.last_nread = read;
-                match read {
-                    0 => None,
-                    _ => Some(read as uint)
-                }
-            },
-            Err(ioerr) => {
-                // EOF is indicated by returning None
-                if ioerr.kind != io::EndOfFile {
-                    io_error::cond.raise(ioerr);
-                }
-                return None;
-            }
-        }
-    }
-
-    fn eof(&mut self) -> bool { self.last_nread == 0 }
-}
-
-impl Writer for File {
-    fn write(&mut self, buf: &[u8]) {
-        match self.fd.write(buf) {
-            Ok(()) => (),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-            }
-        }
-    }
-}
-
-impl Seek for File {
-    fn tell(&self) -> u64 {
-        let res = self.fd.tell();
-        match res {
-            Ok(cursor) => cursor,
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                return -1;
-            }
-        }
-    }
-
-    fn seek(&mut self, pos: i64, style: SeekStyle) {
-        match self.fd.seek(pos, style) {
-            Ok(_) => {
-                // successful seek resets EOF indicator
-                self.last_nread = -1;
-                ()
-            },
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-            }
-        }
-    }
-}
-
-impl path::Path {
-    /// Get information on the file, directory, etc at this path.
-    ///
-    /// Consult the `file::stat` documentation for more info.
-    ///
-    /// This call preserves identical runtime/error semantics with `file::stat`.
-    pub fn stat(&self) -> FileStat { stat(self) }
-
-    /// Boolean value indicator whether the underlying file exists on the local
-    /// filesystem. This will return true if the path points to either a
-    /// directory or a file.
-    ///
-    /// # Errors
-    ///
-    /// Will not raise a condition
-    pub fn exists(&self) -> bool {
-        io::result(|| self.stat()).is_ok()
-    }
-
-    /// Whether the underlying implemention (be it a file path, or something
-    /// else) points at a "regular file" on the FS. Will return false for paths
-    /// to non-existent locations or directories or other non-regular files
-    /// (named pipes, etc).
-    ///
-    /// # Errors
-    ///
-    /// Will not raise a condition
-    pub fn is_file(&self) -> bool {
-        match io::result(|| self.stat()) {
-            Ok(s) => s.kind == io::TypeFile,
-            Err(*) => false
-        }
-    }
-
-    /// Whether the underlying implemention (be it a file path,
-    /// or something else) is pointing at a directory in the underlying FS.
-    /// Will return false for paths to non-existent locations or if the item is
-    /// not a directory (eg files, named pipes, links, etc)
-    ///
-    /// # Errors
-    ///
-    /// Will not raise a condition
-    pub fn is_dir(&self) -> bool {
-        match io::result(|| self.stat()) {
-            Ok(s) => s.kind == io::TypeDirectory,
-            Err(*) => false
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use prelude::*;
-    use rt::io::{SeekSet, SeekCur, SeekEnd, io_error, Read, Open, ReadWrite};
-    use rt::io;
-    use str;
-    use super::{File, rmdir, mkdir, readdir, rmdir_recursive, mkdir_recursive,
-                copy, unlink, stat, symlink, link, readlink, chmod,
-                lstat, change_file_times};
-
-    fn tmpdir() -> Path {
-        use os;
-        use rand;
-        let ret = os::tmpdir().join(format!("rust-{}", rand::random::<u32>()));
-        mkdir(&ret, io::UserRWX);
-        ret
-    }
-
-    fn free<T>(_: T) {}
-
-    #[test]
-    fn file_test_io_smoke_test() {
-        let message = "it's alright. have a good time";
-        let filename = &Path::new("./tmp/file_rt_io_file_test.txt");
-        {
-            let mut write_stream = File::open_mode(filename, Open, ReadWrite);
-            write_stream.write(message.as_bytes());
-        }
-        {
-            let mut read_stream = File::open_mode(filename, Open, Read);
-            let mut read_buf = [0, .. 1028];
-            let read_str = match read_stream.read(read_buf).unwrap() {
-                -1|0 => fail!("shouldn't happen"),
-                n => str::from_utf8(read_buf.slice_to(n))
-            };
-            assert!(read_str == message.to_owned());
-        }
-        unlink(filename);
-    }
-
-    #[test]
-    fn file_test_io_invalid_path_opened_without_create_should_raise_condition() {
-        let filename = &Path::new("./tmp/file_that_does_not_exist.txt");
-        let mut called = false;
-        do io_error::cond.trap(|_| {
-            called = true;
-        }).inside {
-            let result = File::open_mode(filename, Open, Read);
-            assert!(result.is_none());
-        }
-        assert!(called);
-    }
-
-    #[test]
-    fn file_test_iounlinking_invalid_path_should_raise_condition() {
-        let filename = &Path::new("./tmp/file_another_file_that_does_not_exist.txt");
-        let mut called = false;
-        do io_error::cond.trap(|_| {
-            called = true;
-        }).inside {
-            unlink(filename);
-        }
-        assert!(called);
-    }
-
-    #[test]
-    fn file_test_io_non_positional_read() {
-        let message = "ten-four";
-        let mut read_mem = [0, .. 8];
-        let filename = &Path::new("./tmp/file_rt_io_file_test_positional.txt");
-        {
-            let mut rw_stream = File::open_mode(filename, Open, ReadWrite);
-            rw_stream.write(message.as_bytes());
-        }
-        {
-            let mut read_stream = File::open_mode(filename, Open, Read);
-            {
-                let read_buf = read_mem.mut_slice(0, 4);
-                read_stream.read(read_buf);
-            }
-            {
-                let read_buf = read_mem.mut_slice(4, 8);
-                read_stream.read(read_buf);
-            }
-        }
-        unlink(filename);
-        let read_str = str::from_utf8(read_mem);
-        assert!(read_str == message.to_owned());
-    }
-
-    #[test]
-    fn file_test_io_seek_and_tell_smoke_test() {
-        let message = "ten-four";
-        let mut read_mem = [0, .. 4];
-        let set_cursor = 4 as u64;
-        let mut tell_pos_pre_read;
-        let mut tell_pos_post_read;
-        let filename = &Path::new("./tmp/file_rt_io_file_test_seeking.txt");
-        {
-            let mut rw_stream = File::open_mode(filename, Open, ReadWrite);
-            rw_stream.write(message.as_bytes());
-        }
-        {
-            let mut read_stream = File::open_mode(filename, Open, Read);
-            read_stream.seek(set_cursor as i64, SeekSet);
-            tell_pos_pre_read = read_stream.tell();
-            read_stream.read(read_mem);
-            tell_pos_post_read = read_stream.tell();
-        }
-        unlink(filename);
-        let read_str = str::from_utf8(read_mem);
-        assert!(read_str == message.slice(4, 8).to_owned());
-        assert!(tell_pos_pre_read == set_cursor);
-        assert!(tell_pos_post_read == message.len() as u64);
-    }
-
-    #[test]
-    fn file_test_io_seek_and_write() {
-        let initial_msg =   "food-is-yummy";
-        let overwrite_msg =    "-the-bar!!";
-        let final_msg =     "foo-the-bar!!";
-        let seek_idx = 3;
-        let mut read_mem = [0, .. 13];
-        let filename = &Path::new("./tmp/file_rt_io_file_test_seek_and_write.txt");
-        {
-            let mut rw_stream = File::open_mode(filename, Open, ReadWrite);
-            rw_stream.write(initial_msg.as_bytes());
-            rw_stream.seek(seek_idx as i64, SeekSet);
-            rw_stream.write(overwrite_msg.as_bytes());
-        }
-        {
-            let mut read_stream = File::open_mode(filename, Open, Read);
-            read_stream.read(read_mem);
-        }
-        unlink(filename);
-        let read_str = str::from_utf8(read_mem);
-        assert!(read_str == final_msg.to_owned());
-    }
-
-    #[test]
-    fn file_test_io_seek_shakedown() {
-        use std::str;          // 01234567890123
-        let initial_msg =   "qwer-asdf-zxcv";
-        let chunk_one = "qwer";
-        let chunk_two = "asdf";
-        let chunk_three = "zxcv";
-        let mut read_mem = [0, .. 4];
-        let filename = &Path::new("./tmp/file_rt_io_file_test_seek_shakedown.txt");
-        {
-            let mut rw_stream = File::open_mode(filename, Open, ReadWrite);
-            rw_stream.write(initial_msg.as_bytes());
-        }
-        {
-            let mut read_stream = File::open_mode(filename, Open, Read);
-
-            read_stream.seek(-4, SeekEnd);
-            read_stream.read(read_mem);
-            let read_str = str::from_utf8(read_mem);
-            assert!(read_str == chunk_three.to_owned());
-
-            read_stream.seek(-9, SeekCur);
-            read_stream.read(read_mem);
-            let read_str = str::from_utf8(read_mem);
-            assert!(read_str == chunk_two.to_owned());
-
-            read_stream.seek(0, SeekSet);
-            read_stream.read(read_mem);
-            let read_str = str::from_utf8(read_mem);
-            assert!(read_str == chunk_one.to_owned());
-        }
-        unlink(filename);
-    }
-
-    #[test]
-    fn file_test_stat_is_correct_on_is_file() {
-        let filename = &Path::new("./tmp/file_stat_correct_on_is_file.txt");
-        {
-            let mut fs = File::open_mode(filename, Open, ReadWrite);
-            let msg = "hw";
-            fs.write(msg.as_bytes());
-        }
-        let stat_res = stat(filename);
-        assert_eq!(stat_res.kind, io::TypeFile);
-        unlink(filename);
-    }
-
-    #[test]
-    fn file_test_stat_is_correct_on_is_dir() {
-        let filename = &Path::new("./tmp/file_stat_correct_on_is_dir");
-        mkdir(filename, io::UserRWX);
-        let stat_res = filename.stat();
-        assert!(stat_res.kind == io::TypeDirectory);
-        rmdir(filename);
-    }
-
-    #[test]
-    fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() {
-        let dir = &Path::new("./tmp/fileinfo_false_on_dir");
-        mkdir(dir, io::UserRWX);
-        assert!(dir.is_file() == false);
-        rmdir(dir);
-    }
-
-    #[test]
-    fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
-        let file = &Path::new("./tmp/fileinfo_check_exists_b_and_a.txt");
-        File::create(file).write(bytes!("foo"));
-        assert!(file.exists());
-        unlink(file);
-        assert!(!file.exists());
-    }
-
-    #[test]
-    fn file_test_directoryinfo_check_exists_before_and_after_mkdir() {
-        let dir = &Path::new("./tmp/before_and_after_dir");
-        assert!(!dir.exists());
-        mkdir(dir, io::UserRWX);
-        assert!(dir.exists());
-        assert!(dir.is_dir());
-        rmdir(dir);
-        assert!(!dir.exists());
-    }
-
-    #[test]
-    fn file_test_directoryinfo_readdir() {
-        use std::str;
-        let dir = &Path::new("./tmp/di_readdir");
-        mkdir(dir, io::UserRWX);
-        let prefix = "foo";
-        for n in range(0,3) {
-            let f = dir.join(format!("{}.txt", n));
-            let mut w = File::create(&f);
-            let msg_str = (prefix + n.to_str().to_owned()).to_owned();
-            let msg = msg_str.as_bytes();
-            w.write(msg);
-        }
-        let files = readdir(dir);
-        let mut mem = [0u8, .. 4];
-        for f in files.iter() {
-            {
-                let n = f.filestem_str();
-                File::open(f).read(mem);
-                let read_str = str::from_utf8(mem);
-                let expected = match n {
-                    None|Some("") => fail!("really shouldn't happen.."),
-                    Some(n) => prefix+n
-                };
-                assert!(expected == read_str);
-            }
-            unlink(f);
-        }
-        rmdir(dir);
-    }
-
-    #[test]
-    fn recursive_mkdir_slash() {
-        mkdir_recursive(&Path::new("/"), io::UserRWX);
-    }
-
-    #[test]
-    fn unicode_path_is_dir() {
-        assert!(Path::new(".").is_dir());
-        assert!(!Path::new("test/stdtest/fs.rs").is_dir());
-
-        let tmpdir = tmpdir();
-
-        let mut dirpath = tmpdir.clone();
-        dirpath.push(format!("test-가一ー你好"));
-        mkdir(&dirpath, io::UserRWX);
-        assert!(dirpath.is_dir());
-
-        let mut filepath = dirpath;
-        filepath.push("unicode-file-\uac00\u4e00\u30fc\u4f60\u597d.rs");
-        File::create(&filepath); // ignore return; touch only
-        assert!(!filepath.is_dir());
-        assert!(filepath.exists());
-
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    fn unicode_path_exists() {
-        assert!(Path::new(".").exists());
-        assert!(!Path::new("test/nonexistent-bogus-path").exists());
-
-        let tmpdir = tmpdir();
-        let unicode = tmpdir.clone();
-        let unicode = unicode.join(format!("test-각丁ー再见"));
-        mkdir(&unicode, io::UserRWX);
-        assert!(unicode.exists());
-        assert!(!Path::new("test/unicode-bogus-path-각丁ー再见").exists());
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    fn copy_file_does_not_exist() {
-        let from = Path::new("test/nonexistent-bogus-path");
-        let to = Path::new("test/other-bogus-path");
-        match io::result(|| copy(&from, &to)) {
-            Ok(*) => fail!(),
-            Err(*) => {
-                assert!(!from.exists());
-                assert!(!to.exists());
-            }
-        }
-    }
-
-    #[test]
-    fn copy_file_ok() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in.txt");
-        let out = tmpdir.join("out.txt");
-
-        File::create(&input).write(bytes!("hello"));
-        copy(&input, &out);
-        let contents = File::open(&out).read_to_end();
-        assert_eq!(contents.as_slice(), bytes!("hello"));
-
-        assert_eq!(input.stat().perm, out.stat().perm);
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    fn copy_file_dst_dir() {
-        let tmpdir = tmpdir();
-        let out = tmpdir.join("out");
-
-        File::create(&out);
-        match io::result(|| copy(&out, &tmpdir)) {
-            Ok(*) => fail!(), Err(*) => {}
-        }
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    fn copy_file_dst_exists() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in");
-        let output = tmpdir.join("out");
-
-        File::create(&input).write("foo".as_bytes());
-        File::create(&output).write("bar".as_bytes());
-        copy(&input, &output);
-
-        assert_eq!(File::open(&output).read_to_end(),
-                   (bytes!("foo")).to_owned());
-
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    fn copy_file_src_dir() {
-        let tmpdir = tmpdir();
-        let out = tmpdir.join("out");
-
-        match io::result(|| copy(&tmpdir, &out)) {
-            Ok(*) => fail!(), Err(*) => {}
-        }
-        assert!(!out.exists());
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    fn copy_file_preserves_perm_bits() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in.txt");
-        let out = tmpdir.join("out.txt");
-
-        File::create(&input);
-        chmod(&input, io::UserRead);
-        copy(&input, &out);
-        assert!(out.stat().perm & io::UserWrite == 0);
-
-        chmod(&input, io::UserFile);
-        chmod(&out, io::UserFile);
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    #[ignore(cfg(windows))] // FIXME(#10264) operation not permitted?
-    fn symlinks_work() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in.txt");
-        let out = tmpdir.join("out.txt");
-
-        File::create(&input).write("foobar".as_bytes());
-        symlink(&input, &out);
-        assert_eq!(lstat(&out).kind, io::TypeSymlink);
-        assert_eq!(stat(&out).size, stat(&input).size);
-        assert_eq!(File::open(&out).read_to_end(), (bytes!("foobar")).to_owned());
-
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    #[ignore(cfg(windows))] // apparently windows doesn't like symlinks
-    fn symlink_noexist() {
-        let tmpdir = tmpdir();
-        // symlinks can point to things that don't exist
-        symlink(&tmpdir.join("foo"), &tmpdir.join("bar"));
-        assert!(readlink(&tmpdir.join("bar")).unwrap() == tmpdir.join("foo"));
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    fn readlink_not_symlink() {
-        let tmpdir = tmpdir();
-        match io::result(|| readlink(&tmpdir)) {
-            Ok(*) => fail!("wanted a failure"),
-            Err(*) => {}
-        }
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    fn links_work() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in.txt");
-        let out = tmpdir.join("out.txt");
-
-        File::create(&input).write("foobar".as_bytes());
-        link(&input, &out);
-        assert_eq!(lstat(&out).kind, io::TypeFile);
-        assert_eq!(stat(&out).size, stat(&input).size);
-        assert_eq!(stat(&out).unstable.nlink, 2);
-        assert_eq!(File::open(&out).read_to_end(), (bytes!("foobar")).to_owned());
-
-        // can't link to yourself
-        match io::result(|| link(&input, &input)) {
-            Ok(*) => fail!("wanted a failure"),
-            Err(*) => {}
-        }
-        // can't link to something that doesn't exist
-        match io::result(|| link(&tmpdir.join("foo"), &tmpdir.join("bar"))) {
-            Ok(*) => fail!("wanted a failure"),
-            Err(*) => {}
-        }
-
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    fn chmod_works() {
-        let tmpdir = tmpdir();
-        let file = tmpdir.join("in.txt");
-
-        File::create(&file);
-        assert!(stat(&file).perm & io::UserWrite == io::UserWrite);
-        chmod(&file, io::UserRead);
-        assert!(stat(&file).perm & io::UserWrite == 0);
-
-        match io::result(|| chmod(&tmpdir.join("foo"), io::UserRWX)) {
-            Ok(*) => fail!("wanted a failure"),
-            Err(*) => {}
-        }
-
-        chmod(&file, io::UserFile);
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    fn sync_doesnt_kill_anything() {
-        let tmpdir = tmpdir();
-        let path = tmpdir.join("in.txt");
-
-        let mut file = File::open_mode(&path, io::Open, io::ReadWrite).unwrap();
-        file.fsync();
-        file.datasync();
-        file.write(bytes!("foo"));
-        file.fsync();
-        file.datasync();
-        free(file);
-
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    fn truncate_works() {
-        let tmpdir = tmpdir();
-        let path = tmpdir.join("in.txt");
-
-        let mut file = File::open_mode(&path, io::Open, io::ReadWrite).unwrap();
-        file.write(bytes!("foo"));
-
-        // Do some simple things with truncation
-        assert_eq!(stat(&path).size, 3);
-        file.truncate(10);
-        assert_eq!(stat(&path).size, 10);
-        file.write(bytes!("bar"));
-        assert_eq!(stat(&path).size, 10);
-        assert_eq!(File::open(&path).read_to_end(),
-                   (bytes!("foobar", 0, 0, 0, 0)).to_owned());
-
-        // Truncate to a smaller length, don't seek, and then write something.
-        // Ensure that the intermediate zeroes are all filled in (we're seeked
-        // past the end of the file).
-        file.truncate(2);
-        assert_eq!(stat(&path).size, 2);
-        file.write(bytes!("wut"));
-        assert_eq!(stat(&path).size, 9);
-        assert_eq!(File::open(&path).read_to_end(),
-                   (bytes!("fo", 0, 0, 0, 0, "wut")).to_owned());
-        free(file);
-
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    fn open_flavors() {
-        let tmpdir = tmpdir();
-
-        match io::result(|| File::open_mode(&tmpdir.join("a"), io::Open,
-                                            io::Read)) {
-            Ok(*) => fail!(), Err(*) => {}
-        }
-        File::open_mode(&tmpdir.join("b"), io::Open, io::Write).unwrap();
-        File::open_mode(&tmpdir.join("c"), io::Open, io::ReadWrite).unwrap();
-        File::open_mode(&tmpdir.join("d"), io::Append, io::Write).unwrap();
-        File::open_mode(&tmpdir.join("e"), io::Append, io::ReadWrite).unwrap();
-        File::open_mode(&tmpdir.join("f"), io::Truncate, io::Write).unwrap();
-        File::open_mode(&tmpdir.join("g"), io::Truncate, io::ReadWrite).unwrap();
-
-        File::create(&tmpdir.join("h")).write("foo".as_bytes());
-        File::open_mode(&tmpdir.join("h"), io::Open, io::Read).unwrap();
-        {
-            let mut f = File::open_mode(&tmpdir.join("h"), io::Open,
-                                        io::Read).unwrap();
-            match io::result(|| f.write("wut".as_bytes())) {
-                Ok(*) => fail!(), Err(*) => {}
-            }
-        }
-        assert_eq!(stat(&tmpdir.join("h")).size, 3);
-        {
-            let mut f = File::open_mode(&tmpdir.join("h"), io::Append,
-                                        io::Write).unwrap();
-            f.write("bar".as_bytes());
-        }
-        assert_eq!(stat(&tmpdir.join("h")).size, 6);
-        {
-            let mut f = File::open_mode(&tmpdir.join("h"), io::Truncate,
-                                        io::Write).unwrap();
-            f.write("bar".as_bytes());
-        }
-        assert_eq!(stat(&tmpdir.join("h")).size, 3);
-
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    fn utime() {
-        let tmpdir = tmpdir();
-        let path = tmpdir.join("a");
-        File::create(&path);
-
-        change_file_times(&path, 1000, 2000);
-        assert_eq!(path.stat().accessed, 1000);
-        assert_eq!(path.stat().modified, 2000);
-
-        rmdir_recursive(&tmpdir);
-    }
-
-    #[test]
-    fn utime_noexist() {
-        let tmpdir = tmpdir();
-
-        match io::result(|| change_file_times(&tmpdir.join("a"), 100, 200)) {
-            Ok(*) => fail!(),
-            Err(*) => {}
-        }
-
-        rmdir_recursive(&tmpdir);
-    }
-}
diff --git a/src/libstd/rt/io/mem.rs b/src/libstd/rt/io/mem.rs
deleted file mode 100644 (file)
index 6803637..0000000
+++ /dev/null
@@ -1,308 +0,0 @@
-// 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.
-
-//! Readers and Writers for in-memory buffers
-//!
-//! # XXX
-//!
-//! * Should probably have something like this for strings.
-//! * Should they implement Closable? Would take extra state.
-
-use cmp::min;
-use prelude::*;
-use super::*;
-use vec;
-
-/// Writes to an owned, growable byte vector
-pub struct MemWriter {
-    priv buf: ~[u8],
-    priv pos: uint,
-}
-
-impl MemWriter {
-    pub fn new() -> MemWriter {
-        MemWriter { buf: vec::with_capacity(128), pos: 0 }
-    }
-}
-
-impl Writer for MemWriter {
-    fn write(&mut self, buf: &[u8]) {
-        // Make sure the internal buffer is as least as big as where we
-        // currently are
-        let difference = self.pos as i64 - self.buf.len() as i64;
-        if difference > 0 {
-            self.buf.grow(difference as uint, &0);
-        }
-
-        // Figure out what bytes will be used to overwrite what's currently
-        // there (left), and what will be appended on the end (right)
-        let cap = self.buf.len() - self.pos;
-        let (left, right) = if cap <= buf.len() {
-            (buf.slice_to(cap), buf.slice_from(cap))
-        } else {
-            (buf, &[])
-        };
-
-        // Do the necessary writes
-        if left.len() > 0 {
-            vec::bytes::copy_memory(self.buf.mut_slice_from(self.pos),
-                                    left, left.len());
-        }
-        if right.len() > 0 {
-            self.buf.push_all(right);
-        }
-
-        // Bump us forward
-        self.pos += buf.len();
-    }
-}
-
-impl Seek for MemWriter {
-    fn tell(&self) -> u64 { self.pos as u64 }
-
-    fn seek(&mut self, pos: i64, style: SeekStyle) {
-        match style {
-            SeekSet => { self.pos = pos as uint; }
-            SeekEnd => { self.pos = self.buf.len() + pos as uint; }
-            SeekCur => { self.pos += pos as uint; }
-        }
-    }
-}
-
-impl Decorator<~[u8]> for MemWriter {
-    fn inner(self) -> ~[u8] { self.buf }
-    fn inner_ref<'a>(&'a self) -> &'a ~[u8] { &self.buf }
-    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] { &mut self.buf }
-}
-
-/// Reads from an owned byte vector
-pub struct MemReader {
-    priv buf: ~[u8],
-    priv pos: uint
-}
-
-impl MemReader {
-    pub fn new(buf: ~[u8]) -> MemReader {
-        MemReader {
-            buf: buf,
-            pos: 0
-        }
-    }
-}
-
-impl Reader for MemReader {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        { if self.eof() { return None; } }
-
-        let write_len = min(buf.len(), self.buf.len() - self.pos);
-        {
-            let input = self.buf.slice(self.pos, self.pos + write_len);
-            let output = buf.mut_slice(0, write_len);
-            assert_eq!(input.len(), output.len());
-            vec::bytes::copy_memory(output, input, write_len);
-        }
-        self.pos += write_len;
-        assert!(self.pos <= self.buf.len());
-
-        return Some(write_len);
-    }
-
-    fn eof(&mut self) -> bool { self.pos == self.buf.len() }
-}
-
-impl Seek for MemReader {
-    fn tell(&self) -> u64 { self.pos as u64 }
-
-    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
-}
-
-impl Decorator<~[u8]> for MemReader {
-
-    fn inner(self) -> ~[u8] {
-        match self {
-            MemReader { buf: buf, _ } => buf
-        }
-    }
-
-    fn inner_ref<'a>(&'a self) -> &'a ~[u8] {
-        match *self {
-            MemReader { buf: ref buf, _ } => buf
-        }
-    }
-
-    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] {
-        match *self {
-            MemReader { buf: ref mut buf, _ } => buf
-        }
-    }
-}
-
-
-/// Writes to a fixed-size byte slice
-pub struct BufWriter<'self> {
-    priv buf: &'self mut [u8],
-    priv pos: uint
-}
-
-impl<'self> BufWriter<'self> {
-    pub fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> {
-        BufWriter {
-            buf: buf,
-            pos: 0
-        }
-    }
-}
-
-impl<'self> Writer for BufWriter<'self> {
-    fn write(&mut self, _buf: &[u8]) { fail!() }
-
-    fn flush(&mut self) { fail!() }
-}
-
-impl<'self> Seek for BufWriter<'self> {
-    fn tell(&self) -> u64 { fail!() }
-
-    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
-}
-
-
-/// Reads from a fixed-size byte slice
-pub struct BufReader<'self> {
-    priv buf: &'self [u8],
-    priv pos: uint
-}
-
-impl<'self> BufReader<'self> {
-    pub fn new<'a>(buf: &'a [u8]) -> BufReader<'a> {
-        BufReader {
-            buf: buf,
-            pos: 0
-        }
-    }
-}
-
-impl<'self> Reader for BufReader<'self> {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        { if self.eof() { return None; } }
-
-        let write_len = min(buf.len(), self.buf.len() - self.pos);
-        {
-            let input = self.buf.slice(self.pos, self.pos + write_len);
-            let output = buf.mut_slice(0, write_len);
-            assert_eq!(input.len(), output.len());
-            vec::bytes::copy_memory(output, input, write_len);
-        }
-        self.pos += write_len;
-        assert!(self.pos <= self.buf.len());
-
-        return Some(write_len);
-     }
-
-    fn eof(&mut self) -> bool { self.pos == self.buf.len() }
-}
-
-impl<'self> Seek for BufReader<'self> {
-    fn tell(&self) -> u64 { self.pos as u64 }
-
-    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
-}
-
-///Calls a function with a MemWriter and returns
-///the writer's stored vector.
-pub fn with_mem_writer(writeFn:&fn(&mut MemWriter)) -> ~[u8] {
-    let mut writer = MemWriter::new();
-    writeFn(&mut writer);
-    writer.inner()
-}
-
-#[cfg(test)]
-mod test {
-    use prelude::*;
-    use super::*;
-    use rt::io::*;
-
-    #[test]
-    fn test_mem_writer() {
-        let mut writer = MemWriter::new();
-        assert_eq!(writer.tell(), 0);
-        writer.write([0]);
-        assert_eq!(writer.tell(), 1);
-        writer.write([1, 2, 3]);
-        writer.write([4, 5, 6, 7]);
-        assert_eq!(writer.tell(), 8);
-        assert_eq!(*writer.inner_ref(), ~[0, 1, 2, 3, 4, 5, 6, 7]);
-
-        writer.seek(0, SeekSet);
-        assert_eq!(writer.tell(), 0);
-        writer.write([3, 4]);
-        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 3, 4, 5, 6, 7]);
-
-        writer.seek(1, SeekCur);
-        writer.write([0, 1]);
-        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 7]);
-
-        writer.seek(-1, SeekEnd);
-        writer.write([1, 2]);
-        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 1, 2]);
-
-        writer.seek(1, SeekEnd);
-        writer.write([1]);
-        assert_eq!(*writer.inner_ref(), ~[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]);
-    }
-
-    #[test]
-    fn test_mem_reader() {
-        let mut reader = MemReader::new(~[0, 1, 2, 3, 4, 5, 6, 7]);
-        let mut buf = [];
-        assert_eq!(reader.read(buf), Some(0));
-        assert_eq!(reader.tell(), 0);
-        let mut buf = [0];
-        assert_eq!(reader.read(buf), Some(1));
-        assert_eq!(reader.tell(), 1);
-        assert_eq!(buf, [0]);
-        let mut buf = [0, ..4];
-        assert_eq!(reader.read(buf), Some(4));
-        assert_eq!(reader.tell(), 5);
-        assert_eq!(buf, [1, 2, 3, 4]);
-        assert_eq!(reader.read(buf), Some(3));
-        assert_eq!(buf.slice(0, 3), [5, 6, 7]);
-        assert!(reader.eof());
-        assert_eq!(reader.read(buf), None);
-        assert!(reader.eof());
-    }
-
-    #[test]
-    fn test_buf_reader() {
-        let in_buf = ~[0, 1, 2, 3, 4, 5, 6, 7];
-        let mut reader = BufReader::new(in_buf);
-        let mut buf = [];
-        assert_eq!(reader.read(buf), Some(0));
-        assert_eq!(reader.tell(), 0);
-        let mut buf = [0];
-        assert_eq!(reader.read(buf), Some(1));
-        assert_eq!(reader.tell(), 1);
-        assert_eq!(buf, [0]);
-        let mut buf = [0, ..4];
-        assert_eq!(reader.read(buf), Some(4));
-        assert_eq!(reader.tell(), 5);
-        assert_eq!(buf, [1, 2, 3, 4]);
-        assert_eq!(reader.read(buf), Some(3));
-        assert_eq!(buf.slice(0, 3), [5, 6, 7]);
-        assert!(reader.eof());
-        assert_eq!(reader.read(buf), None);
-        assert!(reader.eof());
-    }
-
-    #[test]
-    fn test_with_mem_writer() {
-        let buf = with_mem_writer(|wr| wr.write([1,2,3,4,5,6,7]));
-        assert_eq!(buf, ~[1,2,3,4,5,6,7]);
-    }
-}
diff --git a/src/libstd/rt/io/mod.rs b/src/libstd/rt/io/mod.rs
deleted file mode 100644 (file)
index ce9504a..0000000
+++ /dev/null
@@ -1,1224 +0,0 @@
-// 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.
-
-/*! Synchronous I/O
-
-This module defines the Rust interface for synchronous I/O.
-It models byte-oriented input and output with the Reader and Writer traits.
-Types that implement both `Reader` and `Writer` are called 'streams',
-and automatically implement the `Stream` trait.
-Implementations are provided for common I/O streams like
-file, TCP, UDP, Unix domain sockets.
-Readers and Writers may be composed to add capabilities like string
-parsing, encoding, and compression.
-
-This will likely live in std::io, not std::rt::io.
-
-# Examples
-
-Some examples of obvious things you might want to do
-
-* Read lines from stdin
-
-    for stdin().each_line |line| {
-        println(line)
-    }
-
-* Read a complete file to a string, (converting newlines?)
-
-    let contents = File::open("message.txt").read_to_str(); // read_to_str??
-
-* Write a line to a file
-
-    let file = File::open("message.txt", Create, Write);
-    file.write_line("hello, file!");
-
-* Iterate over the lines of a file
-
-    do File::open("message.txt").each_line |line| {
-        println(line)
-    }
-
-* Pull the lines of a file into a vector of strings
-
-    let lines = File::open("message.txt").line_iter().to_vec();
-
-* Make an simple HTTP request
-
-    let socket = TcpStream::open("localhost:8080");
-    socket.write_line("GET / HTTP/1.0");
-    socket.write_line("");
-    let response = socket.read_to_end();
-
-* Connect based on URL? Requires thinking about where the URL type lives
-  and how to make protocol handlers extensible, e.g. the "tcp" protocol
-  yields a `TcpStream`.
-
-    connect("tcp://localhost:8080");
-
-# Terms
-
-* Reader - An I/O source, reads bytes into a buffer
-* Writer - An I/O sink, writes bytes from a buffer
-* Stream - Typical I/O sources like files and sockets are both Readers and Writers,
-  and are collectively referred to a `streams`.
-* Decorator - A Reader or Writer that composes with others to add additional capabilities
-  such as encoding or decoding
-
-# Blocking and synchrony
-
-When discussing I/O you often hear the terms 'synchronous' and
-'asynchronous', along with 'blocking' and 'non-blocking' compared and
-contrasted. A synchronous I/O interface performs each I/O operation to
-completion before proceeding to the next. Synchronous interfaces are
-usually used in imperative style as a sequence of commands. An
-asynchronous interface allows multiple I/O requests to be issued
-simultaneously, without waiting for each to complete before proceeding
-to the next.
-
-Asynchronous interfaces are used to achieve 'non-blocking' I/O. In
-traditional single-threaded systems, performing a synchronous I/O
-operation means that the program stops all activity (it 'blocks')
-until the I/O is complete. Blocking is bad for performance when
-there are other computations that could be done.
-
-Asynchronous interfaces are most often associated with the callback
-(continuation-passing) style popularised by node.js. Such systems rely
-on all computations being run inside an event loop which maintains a
-list of all pending I/O events; when one completes the registered
-callback is run and the code that made the I/O request continues.
-Such interfaces achieve non-blocking at the expense of being more
-difficult to reason about.
-
-Rust's I/O interface is synchronous - easy to read - and non-blocking by default.
-
-Remember that Rust tasks are 'green threads', lightweight threads that
-are multiplexed onto a single operating system thread. If that system
-thread blocks then no other task may proceed. Rust tasks are
-relatively cheap to create, so as long as other tasks are free to
-execute then non-blocking code may be written by simply creating a new
-task.
-
-When discussing blocking in regards to Rust's I/O model, we are
-concerned with whether performing I/O blocks other Rust tasks from
-proceeding. In other words, when a task calls `read`, it must then
-wait (or 'sleep', or 'block') until the call to `read` is complete.
-During this time, other tasks may or may not be executed, depending on
-how `read` is implemented.
-
-
-Rust's default I/O implementation is non-blocking; by cooperating
-directly with the task scheduler it arranges to never block progress
-of *other* tasks. Under the hood, Rust uses asynchronous I/O via a
-per-scheduler (and hence per-thread) event loop. Synchronous I/O
-requests are implemented by descheduling the running task and
-performing an asynchronous request; the task is only resumed once the
-asynchronous request completes.
-
-For blocking (but possibly more efficient) implementations, look
-in the `io::native` module.
-
-# Error Handling
-
-I/O is an area where nearly every operation can result in unexpected
-errors. It should allow errors to be handled efficiently.
-It needs to be convenient to use I/O when you don't care
-about dealing with specific errors.
-
-Rust's I/O employs a combination of techniques to reduce boilerplate
-while still providing feedback about errors. The basic strategy:
-
-* Errors are fatal by default, resulting in task failure
-* Errors raise the `io_error` condition which provides an opportunity to inspect
-  an IoError object containing details.
-* Return values must have a sensible null or zero value which is returned
-  if a condition is handled successfully. This may be an `Option`, an empty
-  vector, or other designated error value.
-* Common traits are implemented for `Option`, e.g. `impl<R: Reader> Reader for Option<R>`,
-  so that nullable values do not have to be 'unwrapped' before use.
-
-These features combine in the API to allow for expressions like
-`File::new("diary.txt").write_line("met a girl")` without having to
-worry about whether "diary.txt" exists or whether the write
-succeeds. As written, if either `new` or `write_line` encounters
-an error the task will fail.
-
-If you wanted to handle the error though you might write
-
-    let mut error = None;
-    do io_error::cond(|e: IoError| {
-        error = Some(e);
-    }).in {
-        File::new("diary.txt").write_line("met a girl");
-    }
-
-    if error.is_some() {
-        println("failed to write my diary");
-    }
-
-XXX: Need better condition handling syntax
-
-In this case the condition handler will have the opportunity to
-inspect the IoError raised by either the call to `new` or the call to
-`write_line`, but then execution will continue.
-
-So what actually happens if `new` encounters an error? To understand
-that it's important to know that what `new` returns is not a `File`
-but an `Option<File>`.  If the file does not open, and the condition
-is handled, then `new` will simply return `None`. Because there is an
-implementation of `Writer` (the trait required ultimately required for
-types to implement `write_line`) there is no need to inspect or unwrap
-the `Option<File>` and we simply call `write_line` on it.  If `new`
-returned a `None` then the followup call to `write_line` will also
-raise an error.
-
-## Concerns about this strategy
-
-This structure will encourage a programming style that is prone
-to errors similar to null pointer dereferences.
-In particular code written to ignore errors and expect conditions to be unhandled
-will start passing around null or zero objects when wrapped in a condition handler.
-
-* XXX: How should we use condition handlers that return values?
-* XXX: Should EOF raise default conditions when EOF is not an error?
-
-# Issues with i/o scheduler affinity, work stealing, task pinning
-
-# Resource management
-
-* `close` vs. RAII
-
-# Paths, URLs and overloaded constructors
-
-
-
-# Scope
-
-In scope for core
-
-* Url?
-
-Some I/O things don't belong in core
-
-  - url
-  - net - `fn connect`
-    - http
-  - flate
-
-Out of scope
-
-* Async I/O. We'll probably want it eventually
-
-
-# XXX Questions and issues
-
-* Should default constructors take `Path` or `&str`? `Path` makes simple cases verbose.
-  Overloading would be nice.
-* Add overloading for Path and &str and Url &str
-* stdin/err/out
-* print, println, etc.
-* fsync
-* relationship with filesystem querying, Directory, File types etc.
-* Rename Reader/Writer to ByteReader/Writer, make Reader/Writer generic?
-* Can Port and Chan be implementations of a generic Reader<T>/Writer<T>?
-* Trait for things that are both readers and writers, Stream?
-* How to handle newline conversion
-* String conversion
-* open vs. connect for generic stream opening
-* Do we need `close` at all? dtors might be good enough
-* How does I/O relate to the Iterator trait?
-* std::base64 filters
-* Using conditions is a big unknown since we don't have much experience with them
-* Too many uses of OtherIoError
-
-*/
-
-use cast;
-use int;
-use path::Path;
-use str::{StrSlice, OwnedStr};
-use option::{Option, Some, None};
-use result::{Ok, Err, Result};
-use iter::Iterator;
-use to_str::ToStr;
-use uint;
-use unstable::finally::Finally;
-use vec;
-
-// Reexports
-pub use self::stdio::stdin;
-pub use self::stdio::stdout;
-pub use self::stdio::stderr;
-pub use self::stdio::print;
-pub use self::stdio::println;
-
-pub use self::fs::File;
-pub use self::timer::Timer;
-pub use self::net::ip::IpAddr;
-pub use self::net::tcp::TcpListener;
-pub use self::net::tcp::TcpStream;
-pub use self::net::udp::UdpStream;
-pub use self::pipe::PipeStream;
-pub use self::process::Process;
-
-/// Synchronous, non-blocking filesystem operations.
-pub mod fs;
-
-/// Synchronous, in-memory I/O.
-pub mod pipe;
-
-/// Child process management.
-pub mod process;
-
-/// Synchronous, non-blocking network I/O.
-pub mod net;
-
-/// Readers and Writers for memory buffers and strings.
-pub mod mem;
-
-/// Non-blocking access to stdin, stdout, stderr
-pub mod stdio;
-
-/// Implementations for Option
-mod option;
-
-/// Basic stream compression. XXX: Belongs with other flate code
-pub mod flate;
-
-/// Interop between byte streams and pipes. Not sure where it belongs
-pub mod comm_adapters;
-
-/// Extension traits
-pub mod extensions;
-
-/// Basic Timer
-pub mod timer;
-
-/// Buffered I/O wrappers
-pub mod buffered;
-
-/// Thread-blocking implementations
-pub mod native {
-    /// Posix file I/O
-    pub mod file;
-    /// Process spawning and child management
-    pub mod process;
-    /// Posix stdio
-    pub mod stdio;
-
-    /// Sockets
-    /// # XXX - implement this
-    pub mod net {
-        pub mod tcp { }
-        pub mod udp { }
-        #[cfg(unix)]
-        pub mod unix { }
-    }
-}
-
-/// Signal handling
-pub mod signal;
-
-/// The default buffer size for various I/O operations
-static DEFAULT_BUF_SIZE: uint = 1024 * 64;
-
-/// The type passed to I/O condition handlers to indicate error
-///
-/// # XXX
-///
-/// Is something like this sufficient? It's kind of archaic
-pub struct IoError {
-    kind: IoErrorKind,
-    desc: &'static str,
-    detail: Option<~str>
-}
-
-// FIXME: #8242 implementing manually because deriving doesn't work for some reason
-impl ToStr for IoError {
-    fn to_str(&self) -> ~str {
-        let mut s = ~"IoError { kind: ";
-        s.push_str(self.kind.to_str());
-        s.push_str(", desc: ");
-        s.push_str(self.desc);
-        s.push_str(", detail: ");
-        s.push_str(self.detail.to_str());
-        s.push_str(" }");
-        s
-    }
-}
-
-#[deriving(Eq)]
-pub enum IoErrorKind {
-    PreviousIoError,
-    OtherIoError,
-    EndOfFile,
-    FileNotFound,
-    PermissionDenied,
-    ConnectionFailed,
-    Closed,
-    ConnectionRefused,
-    ConnectionReset,
-    ConnectionAborted,
-    NotConnected,
-    BrokenPipe,
-    PathAlreadyExists,
-    PathDoesntExist,
-    MismatchedFileTypeForOperation,
-    ResourceUnavailable,
-    IoUnavailable,
-}
-
-// FIXME: #8242 implementing manually because deriving doesn't work for some reason
-impl ToStr for IoErrorKind {
-    fn to_str(&self) -> ~str {
-        match *self {
-            PreviousIoError => ~"PreviousIoError",
-            OtherIoError => ~"OtherIoError",
-            EndOfFile => ~"EndOfFile",
-            FileNotFound => ~"FileNotFound",
-            PermissionDenied => ~"PermissionDenied",
-            ConnectionFailed => ~"ConnectionFailed",
-            Closed => ~"Closed",
-            ConnectionRefused => ~"ConnectionRefused",
-            ConnectionReset => ~"ConnectionReset",
-            NotConnected => ~"NotConnected",
-            BrokenPipe => ~"BrokenPipe",
-            PathAlreadyExists => ~"PathAlreadyExists",
-            PathDoesntExist => ~"PathDoesntExist",
-            MismatchedFileTypeForOperation => ~"MismatchedFileTypeForOperation",
-            IoUnavailable => ~"IoUnavailable",
-            ResourceUnavailable => ~"ResourceUnavailable",
-            ConnectionAborted => ~"ConnectionAborted",
-        }
-    }
-}
-
-// XXX: Can't put doc comments on macros
-// Raised by `I/O` operations on error.
-condition! {
-    pub io_error: IoError -> ();
-}
-
-/// Helper for wrapper calls where you want to
-/// ignore any io_errors that might be raised
-pub fn ignore_io_error<T>(cb: &fn() -> T) -> T {
-    do io_error::cond.trap(|_| {
-        // just swallow the error.. downstream users
-        // who can make a decision based on a None result
-        // won't care
-    }).inside {
-        cb()
-    }
-}
-
-/// Helper for catching an I/O error and wrapping it in a Result object. The
-/// return result will be the last I/O error that happened or the result of the
-/// closure if no error occurred.
-pub fn result<T>(cb: &fn() -> T) -> Result<T, IoError> {
-    let mut err = None;
-    let ret = io_error::cond.trap(|e| {
-        if err.is_none() {
-            err = Some(e);
-        }
-    }).inside(cb);
-    match err {
-        Some(e) => Err(e),
-        None => Ok(ret),
-    }
-}
-
-pub trait Reader {
-
-    // Only two methods which need to get implemented for this trait
-
-    /// Read bytes, up to the length of `buf` and place them in `buf`.
-    /// Returns the number of bytes read. The number of bytes read my
-    /// be less than the number requested, even 0. Returns `None` on EOF.
-    ///
-    /// # Failure
-    ///
-    /// Raises the `io_error` condition on error. If the condition
-    /// is handled then no guarantee is made about the number of bytes
-    /// read and the contents of `buf`. If the condition is handled
-    /// returns `None` (XXX see below).
-    ///
-    /// # XXX
-    ///
-    /// * Should raise_default error on eof?
-    /// * If the condition is handled it should still return the bytes read,
-    ///   in which case there's no need to return Option - but then you *have*
-    ///   to install a handler to detect eof.
-    ///
-    /// This doesn't take a `len` argument like the old `read`.
-    /// Will people often need to slice their vectors to call this
-    /// and will that be annoying?
-    /// Is it actually possible for 0 bytes to be read successfully?
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint>;
-
-    /// Return whether the Reader has reached the end of the stream.
-    ///
-    /// # Example
-    ///
-    ///     let reader = File::open(&Path::new("foo.txt"))
-    ///     while !reader.eof() {
-    ///         println(reader.read_line());
-    ///     }
-    ///
-    /// # Failure
-    ///
-    /// Returns `true` on failure.
-    fn eof(&mut self) -> bool;
-
-    // Convenient helper methods based on the above methods
-
-    /// Reads a single byte. Returns `None` on EOF.
-    ///
-    /// # Failure
-    ///
-    /// Raises the same conditions as the `read` method. Returns
-    /// `None` if the condition is handled.
-    fn read_byte(&mut self) -> Option<u8> {
-        let mut buf = [0];
-        match self.read(buf) {
-            Some(0) => {
-                debug!("read 0 bytes. trying again");
-                self.read_byte()
-            }
-            Some(1) => Some(buf[0]),
-            Some(_) => unreachable!(),
-            None => None
-        }
-    }
-
-    /// Reads `len` bytes and appends them to a vector.
-    ///
-    /// May push fewer than the requested number of bytes on error
-    /// or EOF. Returns true on success, false on EOF or error.
-    ///
-    /// # Failure
-    ///
-    /// Raises the same conditions as `read`. Additionally raises `io_error`
-    /// on EOF. If `io_error` is handled then `push_bytes` may push less
-    /// than the requested number of bytes.
-    fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) {
-        unsafe {
-            let start_len = buf.len();
-            let mut total_read = 0;
-
-            buf.reserve_additional(len);
-            vec::raw::set_len(buf, start_len + len);
-
-            do (|| {
-                while total_read < len {
-                    let len = buf.len();
-                    let slice = buf.mut_slice(start_len + total_read, len);
-                    match self.read(slice) {
-                        Some(nread) => {
-                            total_read += nread;
-                        }
-                        None => {
-                            io_error::cond.raise(standard_error(EndOfFile));
-                            break;
-                        }
-                    }
-                }
-            }).finally {
-                vec::raw::set_len(buf, start_len + total_read);
-            }
-        }
-    }
-
-    /// Reads `len` bytes and gives you back a new vector of length `len`
-    ///
-    /// # Failure
-    ///
-    /// Raises the same conditions as `read`. Additionally raises `io_error`
-    /// on EOF. If `io_error` is handled then the returned vector may
-    /// contain less than the requested number of bytes.
-    fn read_bytes(&mut self, len: uint) -> ~[u8] {
-        let mut buf = vec::with_capacity(len);
-        self.push_bytes(&mut buf, len);
-        return buf;
-    }
-
-    /// Reads all remaining bytes from the stream.
-    ///
-    /// # Failure
-    ///
-    /// Raises the same conditions as the `read` method.
-    fn read_to_end(&mut self) -> ~[u8] {
-        let mut buf = vec::with_capacity(DEFAULT_BUF_SIZE);
-        let mut keep_reading = true;
-        do io_error::cond.trap(|e| {
-            if e.kind == EndOfFile {
-                keep_reading = false;
-            } else {
-                io_error::cond.raise(e)
-            }
-        }).inside {
-            while keep_reading {
-                self.push_bytes(&mut buf, DEFAULT_BUF_SIZE)
-            }
-        }
-        return buf;
-    }
-
-    /// Create an iterator that reads a single byte on
-    /// each iteration, until EOF.
-    ///
-    /// # Failure
-    ///
-    /// Raises the same conditions as the `read` method, for
-    /// each call to its `.next()` method.
-    /// Ends the iteration if the condition is handled.
-    fn bytes(self) -> extensions::ByteIterator<Self> {
-        extensions::ByteIterator::new(self)
-    }
-
-    // Byte conversion helpers
-
-    /// Reads `n` little-endian unsigned integer bytes.
-    ///
-    /// `n` must be between 1 and 8, inclusive.
-    fn read_le_uint_n(&mut self, nbytes: uint) -> u64 {
-        assert!(nbytes > 0 && nbytes <= 8);
-
-        let mut val = 0u64;
-        let mut pos = 0;
-        let mut i = nbytes;
-        while i > 0 {
-            val += (self.read_u8() as u64) << pos;
-            pos += 8;
-            i -= 1;
-        }
-        val
-    }
-
-    /// Reads `n` little-endian signed integer bytes.
-    ///
-    /// `n` must be between 1 and 8, inclusive.
-    fn read_le_int_n(&mut self, nbytes: uint) -> i64 {
-        extend_sign(self.read_le_uint_n(nbytes), nbytes)
-    }
-
-    /// Reads `n` big-endian unsigned integer bytes.
-    ///
-    /// `n` must be between 1 and 8, inclusive.
-    fn read_be_uint_n(&mut self, nbytes: uint) -> u64 {
-        assert!(nbytes > 0 && nbytes <= 8);
-
-        let mut val = 0u64;
-        let mut i = nbytes;
-        while i > 0 {
-            i -= 1;
-            val += (self.read_u8() as u64) << i * 8;
-        }
-        val
-    }
-
-    /// Reads `n` big-endian signed integer bytes.
-    ///
-    /// `n` must be between 1 and 8, inclusive.
-    fn read_be_int_n(&mut self, nbytes: uint) -> i64 {
-        extend_sign(self.read_be_uint_n(nbytes), nbytes)
-    }
-
-    /// Reads a little-endian unsigned integer.
-    ///
-    /// The number of bytes returned is system-dependant.
-    fn read_le_uint(&mut self) -> uint {
-        self.read_le_uint_n(uint::bytes) as uint
-    }
-
-    /// Reads a little-endian integer.
-    ///
-    /// The number of bytes returned is system-dependant.
-    fn read_le_int(&mut self) -> int {
-        self.read_le_int_n(int::bytes) as int
-    }
-
-    /// Reads a big-endian unsigned integer.
-    ///
-    /// The number of bytes returned is system-dependant.
-    fn read_be_uint(&mut self) -> uint {
-        self.read_be_uint_n(uint::bytes) as uint
-    }
-
-    /// Reads a big-endian integer.
-    ///
-    /// The number of bytes returned is system-dependant.
-    fn read_be_int(&mut self) -> int {
-        self.read_be_int_n(int::bytes) as int
-    }
-
-    /// Reads a big-endian `u64`.
-    ///
-    /// `u64`s are 8 bytes long.
-    fn read_be_u64(&mut self) -> u64 {
-        self.read_be_uint_n(8) as u64
-    }
-
-    /// Reads a big-endian `u32`.
-    ///
-    /// `u32`s are 4 bytes long.
-    fn read_be_u32(&mut self) -> u32 {
-        self.read_be_uint_n(4) as u32
-    }
-
-    /// Reads a big-endian `u16`.
-    ///
-    /// `u16`s are 2 bytes long.
-    fn read_be_u16(&mut self) -> u16 {
-        self.read_be_uint_n(2) as u16
-    }
-
-    /// Reads a big-endian `i64`.
-    ///
-    /// `i64`s are 8 bytes long.
-    fn read_be_i64(&mut self) -> i64 {
-        self.read_be_int_n(8) as i64
-    }
-
-    /// Reads a big-endian `i32`.
-    ///
-    /// `i32`s are 4 bytes long.
-    fn read_be_i32(&mut self) -> i32 {
-        self.read_be_int_n(4) as i32
-    }
-
-    /// Reads a big-endian `i16`.
-    ///
-    /// `i16`s are 2 bytes long.
-    fn read_be_i16(&mut self) -> i16 {
-        self.read_be_int_n(2) as i16
-    }
-
-    /// Reads a big-endian `f64`.
-    ///
-    /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
-    fn read_be_f64(&mut self) -> f64 {
-        unsafe {
-            cast::transmute::<u64, f64>(self.read_be_u64())
-        }
-    }
-
-    /// Reads a big-endian `f32`.
-    ///
-    /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
-    fn read_be_f32(&mut self) -> f32 {
-        unsafe {
-            cast::transmute::<u32, f32>(self.read_be_u32())
-        }
-    }
-
-    /// Reads a little-endian `u64`.
-    ///
-    /// `u64`s are 8 bytes long.
-    fn read_le_u64(&mut self) -> u64 {
-        self.read_le_uint_n(8) as u64
-    }
-
-    /// Reads a little-endian `u32`.
-    ///
-    /// `u32`s are 4 bytes long.
-    fn read_le_u32(&mut self) -> u32 {
-        self.read_le_uint_n(4) as u32
-    }
-
-    /// Reads a little-endian `u16`.
-    ///
-    /// `u16`s are 2 bytes long.
-    fn read_le_u16(&mut self) -> u16 {
-        self.read_le_uint_n(2) as u16
-    }
-
-    /// Reads a little-endian `i64`.
-    ///
-    /// `i64`s are 8 bytes long.
-    fn read_le_i64(&mut self) -> i64 {
-        self.read_le_int_n(8) as i64
-    }
-
-    /// Reads a little-endian `i32`.
-    ///
-    /// `i32`s are 4 bytes long.
-    fn read_le_i32(&mut self) -> i32 {
-        self.read_le_int_n(4) as i32
-    }
-
-    /// Reads a little-endian `i16`.
-    ///
-    /// `i16`s are 2 bytes long.
-    fn read_le_i16(&mut self) -> i16 {
-        self.read_le_int_n(2) as i16
-    }
-
-    /// Reads a little-endian `f64`.
-    ///
-    /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
-    fn read_le_f64(&mut self) -> f64 {
-        unsafe {
-            cast::transmute::<u64, f64>(self.read_le_u64())
-        }
-    }
-
-    /// Reads a little-endian `f32`.
-    ///
-    /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
-    fn read_le_f32(&mut self) -> f32 {
-        unsafe {
-            cast::transmute::<u32, f32>(self.read_le_u32())
-        }
-    }
-
-    /// Read a u8.
-    ///
-    /// `u8`s are 1 byte.
-    fn read_u8(&mut self) -> u8 {
-        match self.read_byte() {
-            Some(b) => b as u8,
-            None => 0
-        }
-    }
-
-    /// Read an i8.
-    ///
-    /// `i8`s are 1 byte.
-    fn read_i8(&mut self) -> i8 {
-        match self.read_byte() {
-            Some(b) => b as i8,
-            None => 0
-        }
-    }
-
-}
-
-impl Reader for ~Reader {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.read(buf) }
-    fn eof(&mut self) -> bool { self.eof() }
-}
-
-impl<'self> Reader for &'self mut Reader {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.read(buf) }
-    fn eof(&mut self) -> bool { self.eof() }
-}
-
-fn extend_sign(val: u64, nbytes: uint) -> i64 {
-    let shift = (8 - nbytes) * 8;
-    (val << shift) as i64 >> shift
-}
-
-pub trait Writer {
-    /// Write the given buffer
-    ///
-    /// # Failure
-    ///
-    /// Raises the `io_error` condition on error
-    fn write(&mut self, buf: &[u8]);
-
-    /// Flush this output stream, ensuring that all intermediately buffered
-    /// contents reach their destination.
-    ///
-    /// This is by default a no-op and implementors of the `Writer` trait should
-    /// decide whether their stream needs to be buffered or not.
-    fn flush(&mut self) {}
-
-    /// Write the result of passing n through `int::to_str_bytes`.
-    fn write_int(&mut self, n: int) {
-        int::to_str_bytes(n, 10u, |bytes| self.write(bytes))
-    }
-
-    /// Write the result of passing n through `uint::to_str_bytes`.
-    fn write_uint(&mut self, n: uint) {
-        uint::to_str_bytes(n, 10u, |bytes| self.write(bytes))
-    }
-
-    /// Write a little-endian uint (number of bytes depends on system).
-    fn write_le_uint(&mut self, n: uint) {
-        extensions::u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v))
-    }
-
-    /// Write a little-endian int (number of bytes depends on system).
-    fn write_le_int(&mut self, n: int) {
-        extensions::u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v))
-    }
-
-    /// Write a big-endian uint (number of bytes depends on system).
-    fn write_be_uint(&mut self, n: uint) {
-        extensions::u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v))
-    }
-
-    /// Write a big-endian int (number of bytes depends on system).
-    fn write_be_int(&mut self, n: int) {
-        extensions::u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v))
-    }
-
-    /// Write a big-endian u64 (8 bytes).
-    fn write_be_u64(&mut self, n: u64) {
-        extensions::u64_to_be_bytes(n, 8u, |v| self.write(v))
-    }
-
-    /// Write a big-endian u32 (4 bytes).
-    fn write_be_u32(&mut self, n: u32) {
-        extensions::u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
-    }
-
-    /// Write a big-endian u16 (2 bytes).
-    fn write_be_u16(&mut self, n: u16) {
-        extensions::u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
-    }
-
-    /// Write a big-endian i64 (8 bytes).
-    fn write_be_i64(&mut self, n: i64) {
-        extensions::u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
-    }
-
-    /// Write a big-endian i32 (4 bytes).
-    fn write_be_i32(&mut self, n: i32) {
-        extensions::u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
-    }
-
-    /// Write a big-endian i16 (2 bytes).
-    fn write_be_i16(&mut self, n: i16) {
-        extensions::u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
-    }
-
-    /// Write a big-endian IEEE754 double-precision floating-point (8 bytes).
-    fn write_be_f64(&mut self, f: f64) {
-        unsafe {
-            self.write_be_u64(cast::transmute(f))
-        }
-    }
-
-    /// Write a big-endian IEEE754 single-precision floating-point (4 bytes).
-    fn write_be_f32(&mut self, f: f32) {
-        unsafe {
-            self.write_be_u32(cast::transmute(f))
-        }
-    }
-
-    /// Write a little-endian u64 (8 bytes).
-    fn write_le_u64(&mut self, n: u64) {
-        extensions::u64_to_le_bytes(n, 8u, |v| self.write(v))
-    }
-
-    /// Write a little-endian u32 (4 bytes).
-    fn write_le_u32(&mut self, n: u32) {
-        extensions::u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
-    }
-
-    /// Write a little-endian u16 (2 bytes).
-    fn write_le_u16(&mut self, n: u16) {
-        extensions::u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
-    }
-
-    /// Write a little-endian i64 (8 bytes).
-    fn write_le_i64(&mut self, n: i64) {
-        extensions::u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
-    }
-
-    /// Write a little-endian i32 (4 bytes).
-    fn write_le_i32(&mut self, n: i32) {
-        extensions::u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
-    }
-
-    /// Write a little-endian i16 (2 bytes).
-    fn write_le_i16(&mut self, n: i16) {
-        extensions::u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
-    }
-
-    /// Write a little-endian IEEE754 double-precision floating-point
-    /// (8 bytes).
-    fn write_le_f64(&mut self, f: f64) {
-        unsafe {
-            self.write_le_u64(cast::transmute(f))
-        }
-    }
-
-    /// Write a little-endian IEEE754 single-precision floating-point
-    /// (4 bytes).
-    fn write_le_f32(&mut self, f: f32) {
-        unsafe {
-            self.write_le_u32(cast::transmute(f))
-        }
-    }
-
-    /// Write a u8 (1 byte).
-    fn write_u8(&mut self, n: u8) {
-        self.write([n])
-    }
-
-    /// Write a i8 (1 byte).
-    fn write_i8(&mut self, n: i8) {
-        self.write([n as u8])
-    }
-}
-
-impl Writer for ~Writer {
-    fn write(&mut self, buf: &[u8]) { self.write(buf) }
-    fn flush(&mut self) { self.flush() }
-}
-
-impl<'self> Writer for &'self mut Writer {
-    fn write(&mut self, buf: &[u8]) { self.write(buf) }
-    fn flush(&mut self) { self.flush() }
-}
-
-pub trait Stream: Reader + Writer { }
-
-impl<T: Reader + Writer> Stream for T {}
-
-pub enum SeekStyle {
-    /// Seek from the beginning of the stream
-    SeekSet,
-    /// Seek from the end of the stream
-    SeekEnd,
-    /// Seek from the current position
-    SeekCur,
-}
-
-/// # XXX
-/// * Are `u64` and `i64` the right choices?
-pub trait Seek {
-    /// Return position of file cursor in the stream
-    fn tell(&self) -> u64;
-
-    /// Seek to an offset in a stream
-    ///
-    /// A successful seek clears the EOF indicator.
-    ///
-    /// # XXX
-    ///
-    /// * What is the behavior when seeking past the end of a stream?
-    fn seek(&mut self, pos: i64, style: SeekStyle);
-}
-
-/// A listener is a value that can consume itself to start listening for connections.
-/// Doing so produces some sort of Acceptor.
-pub trait Listener<T, A: Acceptor<T>> {
-    /// Spin up the listener and start queueing incoming connections
-    ///
-    /// # Failure
-    ///
-    /// Raises `io_error` condition. If the condition is handled,
-    /// then `listen` returns `None`.
-    fn listen(self) -> Option<A>;
-}
-
-/// An acceptor is a value that presents incoming connections
-pub trait Acceptor<T> {
-    /// Wait for and accept an incoming connection
-    ///
-    /// # Failure
-    /// Raise `io_error` condition. If the condition is handled,
-    /// then `accept` returns `None`.
-    fn accept(&mut self) -> Option<T>;
-
-    /// Create an iterator over incoming connection attempts
-    fn incoming<'r>(&'r mut self) -> IncomingIterator<'r, Self> {
-        IncomingIterator { inc: self }
-    }
-}
-
-/// An infinite iterator over incoming connection attempts.
-/// Calling `next` will block the task until a connection is attempted.
-///
-/// Since connection attempts can continue forever, this iterator always returns Some.
-/// The Some contains another Option representing whether the connection attempt was succesful.
-/// A successful connection will be wrapped in Some.
-/// A failed connection is represented as a None and raises a condition.
-struct IncomingIterator<'self, A> {
-    priv inc: &'self mut A,
-}
-
-impl<'self, T, A: Acceptor<T>> Iterator<Option<T>> for IncomingIterator<'self, A> {
-    fn next(&mut self) -> Option<Option<T>> {
-        Some(self.inc.accept())
-    }
-}
-
-/// Common trait for decorator types.
-///
-/// Provides accessors to get the inner, 'decorated' values. The I/O library
-/// uses decorators to add functionality like compression and encryption to I/O
-/// streams.
-///
-/// # XXX
-///
-/// Is this worth having a trait for? May be overkill
-pub trait Decorator<T> {
-    /// Destroy the decorator and extract the decorated value
-    ///
-    /// # XXX
-    ///
-    /// Because this takes `self' one could never 'undecorate' a Reader/Writer
-    /// that has been boxed. Is that ok? This feature is mostly useful for
-    /// extracting the buffer from MemWriter
-    fn inner(self) -> T;
-
-    /// Take an immutable reference to the decorated value
-    fn inner_ref<'a>(&'a self) -> &'a T;
-
-    /// Take a mutable reference to the decorated value
-    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut T;
-}
-
-pub fn standard_error(kind: IoErrorKind) -> IoError {
-    match kind {
-        PreviousIoError => {
-            IoError {
-                kind: PreviousIoError,
-                desc: "Failing due to a previous I/O error",
-                detail: None
-            }
-        }
-        EndOfFile => {
-            IoError {
-                kind: EndOfFile,
-                desc: "End of file",
-                detail: None
-            }
-        }
-        IoUnavailable => {
-            IoError {
-                kind: IoUnavailable,
-                desc: "I/O is unavailable",
-                detail: None
-            }
-        }
-        _ => fail!()
-    }
-}
-
-pub fn placeholder_error() -> IoError {
-    IoError {
-        kind: OtherIoError,
-        desc: "Placeholder error. You shouldn't be seeing this",
-        detail: None
-    }
-}
-
-/// A mode specifies how a file should be opened or created. These modes are
-/// passed to `File::open_mode` and are used to control where the file is
-/// positioned when it is initially opened.
-pub enum FileMode {
-    /// Opens a file positioned at the beginning.
-    Open,
-    /// Opens a file positioned at EOF.
-    Append,
-    /// Opens a file, truncating it if it already exists.
-    Truncate,
-}
-
-/// Access permissions with which the file should be opened. `File`s
-/// opened with `Read` will raise an `io_error` condition if written to.
-pub enum FileAccess {
-    Read,
-    Write,
-    ReadWrite,
-}
-
-/// Different kinds of files which can be identified by a call to stat
-#[deriving(Eq)]
-pub enum FileType {
-    TypeFile,
-    TypeDirectory,
-    TypeNamedPipe,
-    TypeBlockSpecial,
-    TypeSymlink,
-    TypeUnknown,
-}
-
-pub struct FileStat {
-    /// The path that this stat structure is describing
-    path: Path,
-    /// The size of the file, in bytes
-    size: u64,
-    /// The kind of file this path points to (directory, file, pipe, etc.)
-    kind: FileType,
-    /// The file permissions currently on the file
-    perm: FilePermission,
-
-    // FIXME(#10301): These time fields are pretty useless without an actual
-    //                time representation, what are the milliseconds relative
-    //                to?
-
-    /// The time that the file was created at, in platform-dependent
-    /// milliseconds
-    created: u64,
-    /// The time that this file was last modified, in platform-dependent
-    /// milliseconds
-    modified: u64,
-    /// The time that this file was last accessed, in platform-dependent
-    /// milliseconds
-    accessed: u64,
-
-    /// Information returned by stat() which is not guaranteed to be
-    /// platform-independent. This information may be useful on some platforms,
-    /// but it may have different meanings or no meaning at all on other
-    /// platforms.
-    ///
-    /// Usage of this field is discouraged, but if access is desired then the
-    /// fields are located here.
-    #[unstable]
-    unstable: UnstableFileStat,
-}
-
-/// This structure represents all of the possible information which can be
-/// returned from a `stat` syscall which is not contained in the `FileStat`
-/// structure. This information is not necessarily platform independent, and may
-/// have different meanings or no meaning at all on some platforms.
-#[unstable]
-pub struct UnstableFileStat {
-    device: u64,
-    inode: u64,
-    rdev: u64,
-    nlink: u64,
-    uid: u64,
-    gid: u64,
-    blksize: u64,
-    blocks: u64,
-    flags: u64,
-    gen: u64,
-}
-
-/// A set of permissions for a file or directory is represented by a set of
-/// flags which are or'd together.
-pub type FilePermission = u32;
-
-// Each permission bit
-pub static UserRead: FilePermission     = 0x100;
-pub static UserWrite: FilePermission    = 0x080;
-pub static UserExecute: FilePermission  = 0x040;
-pub static GroupRead: FilePermission    = 0x020;
-pub static GroupWrite: FilePermission   = 0x010;
-pub static GroupExecute: FilePermission = 0x008;
-pub static OtherRead: FilePermission    = 0x004;
-pub static OtherWrite: FilePermission   = 0x002;
-pub static OtherExecute: FilePermission = 0x001;
-
-// Common combinations of these bits
-pub static UserRWX: FilePermission  = UserRead | UserWrite | UserExecute;
-pub static GroupRWX: FilePermission = GroupRead | GroupWrite | GroupExecute;
-pub static OtherRWX: FilePermission = OtherRead | OtherWrite | OtherExecute;
-
-/// A set of permissions for user owned files, this is equivalent to 0644 on
-/// unix-like systems.
-pub static UserFile: FilePermission = UserRead | UserWrite | GroupRead | OtherRead;
-/// A set of permissions for user owned directories, this is equivalent to 0755
-/// on unix-like systems.
-pub static UserDir: FilePermission = UserRWX | GroupRead | GroupExecute |
-                                     OtherRead | OtherExecute;
-/// A set of permissions for user owned executables, this is equivalent to 0755
-/// on unix-like systems.
-pub static UserExec: FilePermission = UserDir;
-
-/// A mask for all possible permission bits
-pub static AllPermissions: FilePermission = 0x1ff;
diff --git a/src/libstd/rt/io/native/file.rs b/src/libstd/rt/io/native/file.rs
deleted file mode 100644 (file)
index 69d1159..0000000
+++ /dev/null
@@ -1,761 +0,0 @@
-// 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.
-
-//! Blocking posix-based file I/O
-
-#[allow(non_camel_case_types)];
-
-use libc;
-use os;
-use prelude::*;
-use super::super::*;
-
-#[cfg(windows)]
-fn get_err(errno: i32) -> (IoErrorKind, &'static str) {
-    match errno {
-        libc::EOF => (EndOfFile, "end of file"),
-        _ => (OtherIoError, "unknown error"),
-    }
-}
-
-#[cfg(not(windows))]
-fn get_err(errno: i32) -> (IoErrorKind, &'static str) {
-    // XXX: this should probably be a bit more descriptive...
-    match errno {
-        libc::EOF => (EndOfFile, "end of file"),
-
-        // These two constants can have the same value on some systems, but
-        // different values on others, so we can't use a match clause
-        x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
-            (ResourceUnavailable, "resource temporarily unavailable"),
-
-        _ => (OtherIoError, "unknown error"),
-    }
-}
-
-fn raise_error() {
-    let (kind, desc) = get_err(os::errno() as i32);
-    io_error::cond.raise(IoError {
-        kind: kind,
-        desc: desc,
-        detail: Some(os::last_os_error())
-    });
-}
-
-fn keep_going(data: &[u8], f: &fn(*u8, uint) -> i64) -> i64 {
-    #[cfg(windows)] static eintr: int = 0; // doesn't matter
-    #[cfg(not(windows))] static eintr: int = libc::EINTR as int;
-
-    let (data, origamt) = do data.as_imm_buf |data, amt| { (data, amt) };
-    let mut data = data;
-    let mut amt = origamt;
-    while amt > 0 {
-        let mut ret;
-        loop {
-            ret = f(data, amt);
-            if cfg!(not(windows)) { break } // windows has no eintr
-            // if we get an eintr, then try again
-            if ret != -1 || os::errno() as int != eintr { break }
-        }
-        if ret == 0 {
-            break
-        } else if ret != -1 {
-            amt -= ret as uint;
-            data = unsafe { data.offset(ret as int) };
-        } else {
-            return ret;
-        }
-    }
-    return (origamt - amt) as i64;
-}
-
-pub type fd_t = libc::c_int;
-
-pub struct FileDesc {
-    priv fd: fd_t,
-    priv close_on_drop: bool,
-}
-
-impl FileDesc {
-    /// Create a `FileDesc` from an open C file descriptor.
-    ///
-    /// The `FileDesc` will take ownership of the specified file descriptor and
-    /// close it upon destruction if the `close_on_drop` flag is true, otherwise
-    /// it will not close the file descriptor when this `FileDesc` is dropped.
-    ///
-    /// Note that all I/O operations done on this object will be *blocking*, but
-    /// they do not require the runtime to be active.
-    pub fn new(fd: fd_t, close_on_drop: bool) -> FileDesc {
-        FileDesc { fd: fd, close_on_drop: close_on_drop }
-    }
-}
-
-impl Reader for FileDesc {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        #[cfg(windows)] type rlen = libc::c_uint;
-        #[cfg(not(windows))] type rlen = libc::size_t;
-        let ret = do keep_going(buf) |buf, len| {
-            unsafe {
-                libc::read(self.fd, buf as *mut libc::c_void, len as rlen) as i64
-            }
-        };
-        if ret == 0 {
-            None
-        } else if ret < 0 {
-            raise_error();
-            None
-        } else {
-            Some(ret as uint)
-        }
-    }
-
-    fn eof(&mut self) -> bool { false }
-}
-
-impl Writer for FileDesc {
-    fn write(&mut self, buf: &[u8]) {
-        #[cfg(windows)] type wlen = libc::c_uint;
-        #[cfg(not(windows))] type wlen = libc::size_t;
-        let ret = do keep_going(buf) |buf, len| {
-            unsafe {
-                libc::write(self.fd, buf as *libc::c_void, len as wlen) as i64
-            }
-        };
-        if ret < 0 {
-            raise_error();
-        }
-    }
-}
-
-impl Drop for FileDesc {
-    fn drop(&mut self) {
-        if self.close_on_drop {
-            unsafe { libc::close(self.fd); }
-        }
-    }
-}
-
-pub struct CFile {
-    priv file: *libc::FILE
-}
-
-impl CFile {
-    /// Create a `CFile` from an open `FILE` pointer.
-    ///
-    /// The `CFile` takes ownership of the `FILE` pointer and will close it upon
-    /// destruction.
-    pub fn new(file: *libc::FILE) -> CFile { CFile { file: file } }
-}
-
-impl Reader for CFile {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        let ret = do keep_going(buf) |buf, len| {
-            unsafe {
-                libc::fread(buf as *mut libc::c_void, 1, len as libc::size_t,
-                            self.file) as i64
-            }
-        };
-        if ret == 0 {
-            None
-        } else if ret < 0 {
-            raise_error();
-            None
-        } else {
-            Some(ret as uint)
-        }
-    }
-
-    fn eof(&mut self) -> bool {
-        unsafe { libc::feof(self.file) != 0 }
-    }
-}
-
-impl Writer for CFile {
-    fn write(&mut self, buf: &[u8]) {
-        let ret = do keep_going(buf) |buf, len| {
-            unsafe {
-                libc::fwrite(buf as *libc::c_void, 1, len as libc::size_t,
-                            self.file) as i64
-            }
-        };
-        if ret < 0 {
-            raise_error();
-        }
-    }
-
-    fn flush(&mut self) {
-        if unsafe { libc::fflush(self.file) } < 0 {
-            raise_error();
-        }
-    }
-}
-
-impl Seek for CFile {
-    fn tell(&self) -> u64 {
-        let ret = unsafe { libc::ftell(self.file) };
-        if ret < 0 {
-            raise_error();
-        }
-        return ret as u64;
-    }
-
-    fn seek(&mut self, pos: i64, style: SeekStyle) {
-        let whence = match style {
-            SeekSet => libc::SEEK_SET,
-            SeekEnd => libc::SEEK_END,
-            SeekCur => libc::SEEK_CUR,
-        };
-        if unsafe { libc::fseek(self.file, pos as libc::c_long, whence) } < 0 {
-            raise_error();
-        }
-    }
-}
-
-impl Drop for CFile {
-    fn drop(&mut self) {
-        unsafe { libc::fclose(self.file); }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use libc;
-    use os;
-    use prelude::*;
-    use rt::io::{io_error, SeekSet};
-    use super::*;
-
-    #[ignore(cfg(target_os = "freebsd"))] // hmm, maybe pipes have a tiny buffer
-    fn test_file_desc() {
-        // Run this test with some pipes so we don't have to mess around with
-        // opening or closing files.
-        unsafe {
-            let os::Pipe { input, out } = os::pipe();
-            let mut reader = FileDesc::new(input, true);
-            let mut writer = FileDesc::new(out, true);
-
-            writer.write(bytes!("test"));
-            let mut buf = [0u8, ..4];
-            match reader.read(buf) {
-                Some(4) => {
-                    assert_eq!(buf[0], 't' as u8);
-                    assert_eq!(buf[1], 'e' as u8);
-                    assert_eq!(buf[2], 's' as u8);
-                    assert_eq!(buf[3], 't' as u8);
-                }
-                r => fail!("invalid read: {:?}", r)
-            }
-
-            let mut raised = false;
-            do io_error::cond.trap(|_| { raised = true; }).inside {
-                writer.read(buf);
-            }
-            assert!(raised);
-
-            raised = false;
-            do io_error::cond.trap(|_| { raised = true; }).inside {
-                reader.write(buf);
-            }
-            assert!(raised);
-        }
-    }
-
-    #[ignore(cfg(windows))] // apparently windows doesn't like tmpfile
-    fn test_cfile() {
-        unsafe {
-            let f = libc::tmpfile();
-            assert!(!f.is_null());
-            let mut file = CFile::new(f);
-
-            file.write(bytes!("test"));
-            let mut buf = [0u8, ..4];
-            file.seek(0, SeekSet);
-            match file.read(buf) {
-                Some(4) => {
-                    assert_eq!(buf[0], 't' as u8);
-                    assert_eq!(buf[1], 'e' as u8);
-                    assert_eq!(buf[2], 's' as u8);
-                    assert_eq!(buf[3], 't' as u8);
-                }
-                r => fail!("invalid read: {:?}", r)
-            }
-        }
-    }
-}
-
-// n.b. these functions were all part of the old `std::os` module. There's lots
-//      of fun little nuances that were taken care of by these functions, but
-//      they are all thread-blocking versions that are no longer desired (we now
-//      use a non-blocking event loop implementation backed by libuv).
-//
-//      In theory we will have a thread-blocking version of the event loop (if
-//      desired), so these functions may just need to get adapted to work in
-//      those situtations. For now, I'm leaving the code around so it doesn't
-//      get bitrotted instantaneously.
-mod old_os {
-    use prelude::*;
-    use libc::{size_t, c_void, c_int};
-    use libc;
-    use vec;
-
-    #[cfg(not(windows))] use c_str::CString;
-    #[cfg(not(windows))] use libc::fclose;
-    #[cfg(test)] #[cfg(windows)] use os;
-    #[cfg(test)] use rand;
-    #[cfg(windows)] use str;
-    #[cfg(windows)] use ptr;
-
-    // On Windows, wide character version of function must be used to support
-    // unicode, so functions should be split into at least two versions,
-    // which are for Windows and for non-Windows, if necessary.
-    // See https://github.com/mozilla/rust/issues/9822 for more information.
-
-    mod rustrt {
-        use libc::{c_char, c_int};
-        use libc;
-
-        extern {
-            pub fn rust_path_is_dir(path: *libc::c_char) -> c_int;
-            pub fn rust_path_exists(path: *libc::c_char) -> c_int;
-        }
-
-        // Uses _wstat instead of stat.
-        #[cfg(windows)]
-        extern {
-            pub fn rust_path_is_dir_u16(path: *u16) -> c_int;
-            pub fn rust_path_exists_u16(path: *u16) -> c_int;
-        }
-    }
-
-    /// Recursively walk a directory structure
-    pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool {
-        let r = list_dir(p);
-        r.iter().advance(|q| {
-            let path = &p.join(q);
-            f(path) && (!path_is_dir(path) || walk_dir(path, |p| f(p)))
-        })
-    }
-
-    #[cfg(unix)]
-    /// Indicates whether a path represents a directory
-    pub fn path_is_dir(p: &Path) -> bool {
-        unsafe {
-            do p.with_c_str |buf| {
-                rustrt::rust_path_is_dir(buf) != 0 as c_int
-            }
-        }
-    }
-
-
-    #[cfg(windows)]
-    pub fn path_is_dir(p: &Path) -> bool {
-        unsafe {
-            do os::win32::as_utf16_p(p.as_str().unwrap()) |buf| {
-                rustrt::rust_path_is_dir_u16(buf) != 0 as c_int
-            }
-        }
-    }
-
-    #[cfg(unix)]
-    /// Indicates whether a path exists
-    pub fn path_exists(p: &Path) -> bool {
-        unsafe {
-            do p.with_c_str |buf| {
-                rustrt::rust_path_exists(buf) != 0 as c_int
-            }
-        }
-    }
-
-    #[cfg(windows)]
-    pub fn path_exists(p: &Path) -> bool {
-        unsafe {
-            do os::win32::as_utf16_p(p.as_str().unwrap()) |buf| {
-                rustrt::rust_path_exists_u16(buf) != 0 as c_int
-            }
-        }
-    }
-
-    /// Creates a directory at the specified path
-    pub fn make_dir(p: &Path, mode: c_int) -> bool {
-        return mkdir(p, mode);
-
-        #[cfg(windows)]
-        fn mkdir(p: &Path, _mode: c_int) -> bool {
-            unsafe {
-                use os::win32::as_utf16_p;
-                // FIXME: turn mode into something useful? #2623
-                do as_utf16_p(p.as_str().unwrap()) |buf| {
-                    libc::CreateDirectoryW(buf, ptr::mut_null())
-                        != (0 as libc::BOOL)
-                }
-            }
-        }
-
-        #[cfg(unix)]
-        fn mkdir(p: &Path, mode: c_int) -> bool {
-            do p.with_c_str |buf| {
-                unsafe {
-                    libc::mkdir(buf, mode as libc::mode_t) == (0 as c_int)
-                }
-            }
-        }
-    }
-
-    /// Creates a directory with a given mode.
-    /// Returns true iff creation
-    /// succeeded. Also creates all intermediate subdirectories
-    /// if they don't already exist, giving all of them the same mode.
-
-    // tjc: if directory exists but with different permissions,
-    // should we return false?
-    pub fn mkdir_recursive(p: &Path, mode: c_int) -> bool {
-        if path_is_dir(p) {
-            return true;
-        }
-        if p.filename().is_some() {
-            let mut p_ = p.clone();
-            p_.pop();
-            if !mkdir_recursive(&p_, mode) {
-                return false;
-            }
-        }
-        return make_dir(p, mode);
-    }
-
-    /// Lists the contents of a directory
-    ///
-    /// Each resulting Path is a relative path with no directory component.
-    pub fn list_dir(p: &Path) -> ~[Path] {
-        unsafe {
-            #[cfg(target_os = "linux")]
-            #[cfg(target_os = "android")]
-            #[cfg(target_os = "freebsd")]
-            #[cfg(target_os = "macos")]
-            unsafe fn get_list(p: &Path) -> ~[Path] {
-                use libc::{dirent_t};
-                use libc::{opendir, readdir, closedir};
-                extern {
-                    fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char;
-                }
-                let mut paths = ~[];
-                debug!("os::list_dir -- BEFORE OPENDIR");
-
-                let dir_ptr = do p.with_c_str |buf| {
-                    opendir(buf)
-                };
-
-                if (dir_ptr as uint != 0) {
-                    debug!("os::list_dir -- opendir() SUCCESS");
-                    let mut entry_ptr = readdir(dir_ptr);
-                    while (entry_ptr as uint != 0) {
-                        let cstr = CString::new(rust_list_dir_val(entry_ptr), false);
-                        paths.push(Path::new(cstr));
-                        entry_ptr = readdir(dir_ptr);
-                    }
-                    closedir(dir_ptr);
-                }
-                else {
-                    debug!("os::list_dir -- opendir() FAILURE");
-                }
-                debug!("os::list_dir -- AFTER -- \\#: {}", paths.len());
-                paths
-            }
-            #[cfg(windows)]
-            unsafe fn get_list(p: &Path) -> ~[Path] {
-                use libc::consts::os::extra::INVALID_HANDLE_VALUE;
-                use libc::{wcslen, free};
-                use libc::funcs::extra::kernel32::{
-                    FindFirstFileW,
-                    FindNextFileW,
-                    FindClose,
-                };
-                use libc::types::os::arch::extra::HANDLE;
-                use os::win32::{
-                    as_utf16_p
-                };
-                use rt::global_heap::malloc_raw;
-
-                #[nolink]
-                extern {
-                    fn rust_list_dir_wfd_size() -> libc::size_t;
-                    fn rust_list_dir_wfd_fp_buf(wfd: *libc::c_void) -> *u16;
-                }
-                let star = p.join("*");
-                do as_utf16_p(star.as_str().unwrap()) |path_ptr| {
-                    let mut paths = ~[];
-                    let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
-                    let find_handle = FindFirstFileW(path_ptr, wfd_ptr as HANDLE);
-                    if find_handle as libc::c_int != INVALID_HANDLE_VALUE {
-                        let mut more_files = 1 as libc::c_int;
-                        while more_files != 0 {
-                            let fp_buf = rust_list_dir_wfd_fp_buf(wfd_ptr);
-                            if fp_buf as uint == 0 {
-                                fail!("os::list_dir() failure: got null ptr from wfd");
-                            }
-                            else {
-                                let fp_vec = vec::from_buf(
-                                    fp_buf, wcslen(fp_buf) as uint);
-                                let fp_str = str::from_utf16(fp_vec);
-                                paths.push(Path::new(fp_str));
-                            }
-                            more_files = FindNextFileW(find_handle, wfd_ptr as HANDLE);
-                        }
-                        FindClose(find_handle);
-                        free(wfd_ptr)
-                    }
-                    paths
-                }
-            }
-            do get_list(p).move_iter().filter |path| {
-                path.as_vec() != bytes!(".") && path.as_vec() != bytes!("..")
-            }.collect()
-        }
-    }
-
-    /// Removes a directory at the specified path, after removing
-    /// all its contents. Use carefully!
-    pub fn remove_dir_recursive(p: &Path) -> bool {
-        let mut error_happened = false;
-        do walk_dir(p) |inner| {
-            if !error_happened {
-                if path_is_dir(inner) {
-                    if !remove_dir_recursive(inner) {
-                        error_happened = true;
-                    }
-                }
-                else {
-                    if !remove_file(inner) {
-                        error_happened = true;
-                    }
-                }
-            }
-            true
-        };
-        // Directory should now be empty
-        !error_happened && remove_dir(p)
-    }
-
-    /// Removes a directory at the specified path
-    pub fn remove_dir(p: &Path) -> bool {
-       return rmdir(p);
-
-        #[cfg(windows)]
-        fn rmdir(p: &Path) -> bool {
-            unsafe {
-                use os::win32::as_utf16_p;
-                return do as_utf16_p(p.as_str().unwrap()) |buf| {
-                    libc::RemoveDirectoryW(buf) != (0 as libc::BOOL)
-                };
-            }
-        }
-
-        #[cfg(unix)]
-        fn rmdir(p: &Path) -> bool {
-            do p.with_c_str |buf| {
-                unsafe {
-                    libc::rmdir(buf) == (0 as c_int)
-                }
-            }
-        }
-    }
-
-    /// Deletes an existing file
-    pub fn remove_file(p: &Path) -> bool {
-        return unlink(p);
-
-        #[cfg(windows)]
-        fn unlink(p: &Path) -> bool {
-            unsafe {
-                use os::win32::as_utf16_p;
-                return do as_utf16_p(p.as_str().unwrap()) |buf| {
-                    libc::DeleteFileW(buf) != (0 as libc::BOOL)
-                };
-            }
-        }
-
-        #[cfg(unix)]
-        fn unlink(p: &Path) -> bool {
-            unsafe {
-                do p.with_c_str |buf| {
-                    libc::unlink(buf) == (0 as c_int)
-                }
-            }
-        }
-    }
-
-    /// Renames an existing file or directory
-    pub fn rename_file(old: &Path, new: &Path) -> bool {
-        unsafe {
-           do old.with_c_str |old_buf| {
-                do new.with_c_str |new_buf| {
-                    libc::rename(old_buf, new_buf) == (0 as c_int)
-                }
-           }
-        }
-    }
-
-    /// Copies a file from one location to another
-    pub fn copy_file(from: &Path, to: &Path) -> bool {
-        return do_copy_file(from, to);
-
-        #[cfg(windows)]
-        fn do_copy_file(from: &Path, to: &Path) -> bool {
-            unsafe {
-                use os::win32::as_utf16_p;
-                return do as_utf16_p(from.as_str().unwrap()) |fromp| {
-                    do as_utf16_p(to.as_str().unwrap()) |top| {
-                        libc::CopyFileW(fromp, top, (0 as libc::BOOL)) !=
-                            (0 as libc::BOOL)
-                    }
-                }
-            }
-        }
-
-        #[cfg(unix)]
-        fn do_copy_file(from: &Path, to: &Path) -> bool {
-            unsafe {
-                let istream = do from.with_c_str |fromp| {
-                    do "rb".with_c_str |modebuf| {
-                        libc::fopen(fromp, modebuf)
-                    }
-                };
-                if istream as uint == 0u {
-                    return false;
-                }
-                // Preserve permissions
-                let from_mode = from.stat().perm;
-
-                let ostream = do to.with_c_str |top| {
-                    do "w+b".with_c_str |modebuf| {
-                        libc::fopen(top, modebuf)
-                    }
-                };
-                if ostream as uint == 0u {
-                    fclose(istream);
-                    return false;
-                }
-                let bufsize = 8192u;
-                let mut buf = vec::with_capacity::<u8>(bufsize);
-                let mut done = false;
-                let mut ok = true;
-                while !done {
-                    do buf.as_mut_buf |b, _sz| {
-                      let nread = libc::fread(b as *mut c_void, 1u as size_t,
-                                              bufsize as size_t,
-                                              istream);
-                      if nread > 0 as size_t {
-                          if libc::fwrite(b as *c_void, 1u as size_t, nread,
-                                          ostream) != nread {
-                              ok = false;
-                              done = true;
-                          }
-                      } else {
-                          done = true;
-                      }
-                  }
-                }
-                fclose(istream);
-                fclose(ostream);
-
-                // Give the new file the old file's permissions
-                if do to.with_c_str |to_buf| {
-                    libc::chmod(to_buf, from_mode as libc::mode_t)
-                } != 0 {
-                    return false; // should be a condition...
-                }
-                return ok;
-            }
-        }
-    }
-
-    #[test]
-    fn tmpdir() {
-        let p = os::tmpdir();
-        let s = p.as_str();
-        assert!(s.is_some() && s.unwrap() != ".");
-    }
-
-    // Issue #712
-    #[test]
-    fn test_list_dir_no_invalid_memory_access() {
-        list_dir(&Path::new("."));
-    }
-
-    #[test]
-    fn test_list_dir() {
-        let dirs = list_dir(&Path::new("."));
-        // Just assuming that we've got some contents in the current directory
-        assert!(dirs.len() > 0u);
-
-        for dir in dirs.iter() {
-            debug!("{:?}", (*dir).clone());
-        }
-    }
-
-    #[test]
-    #[cfg(not(windows))]
-    fn test_list_dir_root() {
-        let dirs = list_dir(&Path::new("/"));
-        assert!(dirs.len() > 1);
-    }
-    #[test]
-    #[cfg(windows)]
-    fn test_list_dir_root() {
-        let dirs = list_dir(&Path::new("C:\\"));
-        assert!(dirs.len() > 1);
-    }
-
-    #[test]
-    fn test_path_is_dir() {
-        use rt::io::fs::{mkdir_recursive};
-        use rt::io::{File, UserRWX};
-
-        assert!((path_is_dir(&Path::new("."))));
-        assert!((!path_is_dir(&Path::new("test/stdtest/fs.rs"))));
-
-        let mut dirpath = os::tmpdir();
-        dirpath.push(format!("rust-test-{}/test-\uac00\u4e00\u30fc\u4f60\u597d",
-            rand::random::<u32>())); // 가一ー你好
-        debug!("path_is_dir dirpath: {}", dirpath.display());
-
-        mkdir_recursive(&dirpath, UserRWX);
-
-        assert!((path_is_dir(&dirpath)));
-
-        let mut filepath = dirpath;
-        filepath.push("unicode-file-\uac00\u4e00\u30fc\u4f60\u597d.rs");
-        debug!("path_is_dir filepath: {}", filepath.display());
-
-        File::create(&filepath); // ignore return; touch only
-        assert!((!path_is_dir(&filepath)));
-
-        assert!((!path_is_dir(&Path::new(
-                     "test/unicode-bogus-dir-\uac00\u4e00\u30fc\u4f60\u597d"))));
-    }
-
-    #[test]
-    fn test_path_exists() {
-        use rt::io::fs::mkdir_recursive;
-        use rt::io::UserRWX;
-
-        assert!((path_exists(&Path::new("."))));
-        assert!((!path_exists(&Path::new(
-                     "test/nonexistent-bogus-path"))));
-
-        let mut dirpath = os::tmpdir();
-        dirpath.push(format!("rust-test-{}/test-\uac01\u4e01\u30fc\u518d\u89c1",
-            rand::random::<u32>())); // 각丁ー再见
-
-        mkdir_recursive(&dirpath, UserRWX);
-        assert!((path_exists(&dirpath)));
-        assert!((!path_exists(&Path::new(
-                     "test/unicode-bogus-path-\uac01\u4e01\u30fc\u518d\u89c1"))));
-    }
-}
diff --git a/src/libstd/rt/io/native/process.rs b/src/libstd/rt/io/native/process.rs
deleted file mode 100644 (file)
index 9bf0ed6..0000000
+++ /dev/null
@@ -1,734 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use cast;
-use libc::{pid_t, c_void, c_int};
-use libc;
-use os;
-use prelude::*;
-use ptr;
-use rt::io;
-use super::file;
-
-/**
- * A value representing a child process.
- *
- * The lifetime of this value is linked to the lifetime of the actual
- * process - the Process destructor calls self.finish() which waits
- * for the process to terminate.
- */
-pub struct Process {
-    /// The unique id of the process (this should never be negative).
-    priv pid: pid_t,
-
-    /// A handle to the process - on unix this will always be NULL, but on
-    /// windows it will be a HANDLE to the process, which will prevent the
-    /// pid being re-used until the handle is closed.
-    priv handle: *(),
-
-    /// Currently known stdin of the child, if any
-    priv input: Option<file::FileDesc>,
-    /// Currently known stdout of the child, if any
-    priv output: Option<file::FileDesc>,
-    /// Currently known stderr of the child, if any
-    priv error: Option<file::FileDesc>,
-
-    /// None until finish() is called.
-    priv exit_code: Option<int>,
-}
-
-impl Process {
-    /// Creates a new process using native process-spawning abilities provided
-    /// by the OS. Operations on this process will be blocking instead of using
-    /// the runtime for sleeping just this current task.
-    ///
-    /// # Arguments
-    ///
-    /// * prog - the program to run
-    /// * args - the arguments to pass to the program, not including the program
-    ///          itself
-    /// * env - an optional envrionment to specify for the child process. If
-    ///         this value is `None`, then the child will inherit the parent's
-    ///         environment
-    /// * cwd - an optionally specified current working directory of the child,
-    ///         defaulting to the parent's current working directory
-    /// * stdin, stdout, stderr - These optionally specified file descriptors
-    ///     dictate where the stdin/out/err of the child process will go. If
-    ///     these are `None`, then this module will bind the input/output to an
-    ///     os pipe instead. This process takes ownership of these file
-    ///     descriptors, closing them upon destruction of the process.
-    pub fn new(prog: &str, args: &[~str], env: Option<~[(~str, ~str)]>,
-               cwd: Option<&Path>,
-               stdin: Option<file::fd_t>,
-               stdout: Option<file::fd_t>,
-               stderr: Option<file::fd_t>) -> Process {
-        let (in_pipe, in_fd) = match stdin {
-            None => {
-                let pipe = os::pipe();
-                (Some(pipe), pipe.input)
-            },
-            Some(fd) => (None, fd)
-        };
-        let (out_pipe, out_fd) = match stdout {
-            None => {
-                let pipe = os::pipe();
-                (Some(pipe), pipe.out)
-            },
-            Some(fd) => (None, fd)
-        };
-        let (err_pipe, err_fd) = match stderr {
-            None => {
-                let pipe = os::pipe();
-                (Some(pipe), pipe.out)
-            },
-            Some(fd) => (None, fd)
-        };
-
-        let res = spawn_process_os(prog, args, env, cwd,
-                                   in_fd, out_fd, err_fd);
-
-        unsafe {
-            for pipe in in_pipe.iter() { libc::close(pipe.input); }
-            for pipe in out_pipe.iter() { libc::close(pipe.out); }
-            for pipe in err_pipe.iter() { libc::close(pipe.out); }
-        }
-
-        Process {
-            pid: res.pid,
-            handle: res.handle,
-            input: in_pipe.map(|pipe| file::FileDesc::new(pipe.out, true)),
-            output: out_pipe.map(|pipe| file::FileDesc::new(pipe.input, true)),
-            error: err_pipe.map(|pipe| file::FileDesc::new(pipe.input, true)),
-            exit_code: None,
-        }
-    }
-
-    /// Returns the unique id of the process
-    pub fn id(&self) -> pid_t { self.pid }
-
-    /**
-     * Returns an io::Writer that can be used to write to this Process's stdin.
-     *
-     * Fails if there is no stdinavailable (it's already been removed by
-     * take_input)
-     */
-    pub fn input<'a>(&'a mut self) -> &'a mut io::Writer {
-        match self.input {
-            Some(ref mut fd) => fd as &mut io::Writer,
-            None => fail!("This process has no stdin")
-        }
-    }
-
-    /**
-     * Returns an io::Reader that can be used to read from this Process's
-     * stdout.
-     *
-     * Fails if there is no stdin available (it's already been removed by
-     * take_output)
-     */
-    pub fn output<'a>(&'a mut self) -> &'a mut io::Reader {
-        match self.input {
-            Some(ref mut fd) => fd as &mut io::Reader,
-            None => fail!("This process has no stdout")
-        }
-    }
-
-    /**
-     * Returns an io::Reader that can be used to read from this Process's
-     * stderr.
-     *
-     * Fails if there is no stdin available (it's already been removed by
-     * take_error)
-     */
-    pub fn error<'a>(&'a mut self) -> &'a mut io::Reader {
-        match self.error {
-            Some(ref mut fd) => fd as &mut io::Reader,
-            None => fail!("This process has no stderr")
-        }
-    }
-
-    /**
-     * Takes the stdin of this process, transferring ownership to the caller.
-     * Note that when the return value is destroyed, the handle will be closed
-     * for the child process.
-     */
-    pub fn take_input(&mut self) -> Option<~io::Writer> {
-        self.input.take().map(|fd| ~fd as ~io::Writer)
-    }
-
-    /**
-     * Takes the stdout of this process, transferring ownership to the caller.
-     * Note that when the return value is destroyed, the handle will be closed
-     * for the child process.
-     */
-    pub fn take_output(&mut self) -> Option<~io::Reader> {
-        self.output.take().map(|fd| ~fd as ~io::Reader)
-    }
-
-    /**
-     * Takes the stderr of this process, transferring ownership to the caller.
-     * Note that when the return value is destroyed, the handle will be closed
-     * for the child process.
-     */
-    pub fn take_error(&mut self) -> Option<~io::Reader> {
-        self.error.take().map(|fd| ~fd as ~io::Reader)
-    }
-
-    pub fn wait(&mut self) -> int {
-        for &code in self.exit_code.iter() {
-            return code;
-        }
-        let code = waitpid(self.pid);
-        self.exit_code = Some(code);
-        return code;
-    }
-
-    pub fn signal(&mut self, signum: int) -> Result<(), io::IoError> {
-        // if the process has finished, and therefore had waitpid called,
-        // and we kill it, then on unix we might ending up killing a
-        // newer process that happens to have the same (re-used) id
-        match self.exit_code {
-            Some(*) => return Err(io::IoError {
-                kind: io::OtherIoError,
-                desc: "can't kill an exited process",
-                detail: None,
-            }),
-            None => {}
-        }
-        return unsafe { killpid(self.pid, signum) };
-
-        #[cfg(windows)]
-        unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> {
-            match signal {
-                io::process::PleaseExitSignal |
-                io::process::MustDieSignal => {
-                    libc::funcs::extra::kernel32::TerminateProcess(
-                        cast::transmute(pid), 1);
-                    Ok(())
-                }
-                _ => Err(io::IoError {
-                    kind: io::OtherIoError,
-                    desc: "unsupported signal on windows",
-                    detail: None,
-                })
-            }
-        }
-
-        #[cfg(not(windows))]
-        unsafe fn killpid(pid: pid_t, signal: int) -> Result<(), io::IoError> {
-            libc::funcs::posix88::signal::kill(pid, signal as c_int);
-            Ok(())
-        }
-    }
-}
-
-impl Drop for Process {
-    fn drop(&mut self) {
-        // close all these handles
-        self.take_input();
-        self.take_output();
-        self.take_error();
-        self.wait();
-        free_handle(self.handle);
-    }
-}
-
-struct SpawnProcessResult {
-    pid: pid_t,
-    handle: *(),
-}
-
-#[cfg(windows)]
-fn spawn_process_os(prog: &str, args: &[~str],
-                    env: Option<~[(~str, ~str)]>,
-                    dir: Option<&Path>,
-                    in_fd: c_int, out_fd: c_int, err_fd: c_int) -> SpawnProcessResult {
-    use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO};
-    use libc::consts::os::extra::{
-        TRUE, FALSE,
-        STARTF_USESTDHANDLES,
-        INVALID_HANDLE_VALUE,
-        DUPLICATE_SAME_ACCESS
-    };
-    use libc::funcs::extra::kernel32::{
-        GetCurrentProcess,
-        DuplicateHandle,
-        CloseHandle,
-        CreateProcessA
-    };
-    use libc::funcs::extra::msvcrt::get_osfhandle;
-
-    use mem;
-
-    unsafe {
-
-        let mut si = zeroed_startupinfo();
-        si.cb = mem::size_of::<STARTUPINFO>() as DWORD;
-        si.dwFlags = STARTF_USESTDHANDLES;
-
-        let cur_proc = GetCurrentProcess();
-
-        let orig_std_in = get_osfhandle(in_fd) as HANDLE;
-        if orig_std_in == INVALID_HANDLE_VALUE as HANDLE {
-            fail!("failure in get_osfhandle: {}", os::last_os_error());
-        }
-        if DuplicateHandle(cur_proc, orig_std_in, cur_proc, &mut si.hStdInput,
-                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
-            fail!("failure in DuplicateHandle: {}", os::last_os_error());
-        }
-
-        let orig_std_out = get_osfhandle(out_fd) as HANDLE;
-        if orig_std_out == INVALID_HANDLE_VALUE as HANDLE {
-            fail!("failure in get_osfhandle: {}", os::last_os_error());
-        }
-        if DuplicateHandle(cur_proc, orig_std_out, cur_proc, &mut si.hStdOutput,
-                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
-            fail!("failure in DuplicateHandle: {}", os::last_os_error());
-        }
-
-        let orig_std_err = get_osfhandle(err_fd) as HANDLE;
-        if orig_std_err == INVALID_HANDLE_VALUE as HANDLE {
-            fail!("failure in get_osfhandle: {}", os::last_os_error());
-        }
-        if DuplicateHandle(cur_proc, orig_std_err, cur_proc, &mut si.hStdError,
-                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
-            fail!("failure in DuplicateHandle: {}", os::last_os_error());
-        }
-
-        let cmd = make_command_line(prog, args);
-        let mut pi = zeroed_process_information();
-        let mut create_err = None;
-
-        do with_envp(env) |envp| {
-            do with_dirp(dir) |dirp| {
-                do cmd.with_c_str |cmdp| {
-                    let created = CreateProcessA(ptr::null(), cast::transmute(cmdp),
-                                                 ptr::mut_null(), ptr::mut_null(), TRUE,
-                                                 0, envp, dirp, &mut si, &mut pi);
-                    if created == FALSE {
-                        create_err = Some(os::last_os_error());
-                    }
-                }
-            }
-        }
-
-        CloseHandle(si.hStdInput);
-        CloseHandle(si.hStdOutput);
-        CloseHandle(si.hStdError);
-
-        for msg in create_err.iter() {
-            fail!("failure in CreateProcess: {}", *msg);
-        }
-
-        // We close the thread handle because we don't care about keeping the
-        // thread id valid, and we aren't keeping the thread handle around to be
-        // able to close it later. We don't close the process handle however
-        // because we want the process id to stay valid at least until the
-        // calling code closes the process handle.
-        CloseHandle(pi.hThread);
-
-        SpawnProcessResult {
-            pid: pi.dwProcessId as pid_t,
-            handle: pi.hProcess as *()
-        }
-    }
-}
-
-#[cfg(windows)]
-fn zeroed_startupinfo() -> libc::types::os::arch::extra::STARTUPINFO {
-    libc::types::os::arch::extra::STARTUPINFO {
-        cb: 0,
-        lpReserved: ptr::mut_null(),
-        lpDesktop: ptr::mut_null(),
-        lpTitle: ptr::mut_null(),
-        dwX: 0,
-        dwY: 0,
-        dwXSize: 0,
-        dwYSize: 0,
-        dwXCountChars: 0,
-        dwYCountCharts: 0,
-        dwFillAttribute: 0,
-        dwFlags: 0,
-        wShowWindow: 0,
-        cbReserved2: 0,
-        lpReserved2: ptr::mut_null(),
-        hStdInput: ptr::mut_null(),
-        hStdOutput: ptr::mut_null(),
-        hStdError: ptr::mut_null()
-    }
-}
-
-#[cfg(windows)]
-fn zeroed_process_information() -> libc::types::os::arch::extra::PROCESS_INFORMATION {
-    libc::types::os::arch::extra::PROCESS_INFORMATION {
-        hProcess: ptr::mut_null(),
-        hThread: ptr::mut_null(),
-        dwProcessId: 0,
-        dwThreadId: 0
-    }
-}
-
-// FIXME: this is only pub so it can be tested (see issue #4536)
-#[cfg(windows)]
-pub fn make_command_line(prog: &str, args: &[~str]) -> ~str {
-    let mut cmd = ~"";
-    append_arg(&mut cmd, prog);
-    for arg in args.iter() {
-        cmd.push_char(' ');
-        append_arg(&mut cmd, *arg);
-    }
-    return cmd;
-
-    fn append_arg(cmd: &mut ~str, arg: &str) {
-        let quote = arg.iter().any(|c| c == ' ' || c == '\t');
-        if quote {
-            cmd.push_char('"');
-        }
-        for i in range(0u, arg.len()) {
-            append_char_at(cmd, arg, i);
-        }
-        if quote {
-            cmd.push_char('"');
-        }
-    }
-
-    fn append_char_at(cmd: &mut ~str, arg: &str, i: uint) {
-        match arg[i] as char {
-            '"' => {
-                // Escape quotes.
-                cmd.push_str("\\\"");
-            }
-            '\\' => {
-                if backslash_run_ends_in_quote(arg, i) {
-                    // Double all backslashes that are in runs before quotes.
-                    cmd.push_str("\\\\");
-                } else {
-                    // Pass other backslashes through unescaped.
-                    cmd.push_char('\\');
-                }
-            }
-            c => {
-                cmd.push_char(c);
-            }
-        }
-    }
-
-    fn backslash_run_ends_in_quote(s: &str, mut i: uint) -> bool {
-        while i < s.len() && s[i] as char == '\\' {
-            i += 1;
-        }
-        return i < s.len() && s[i] as char == '"';
-    }
-}
-
-#[cfg(unix)]
-fn spawn_process_os(prog: &str, args: &[~str],
-                    env: Option<~[(~str, ~str)]>,
-                    dir: Option<&Path>,
-                    in_fd: c_int, out_fd: c_int, err_fd: c_int) -> SpawnProcessResult {
-    use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
-    use libc::funcs::bsd44::getdtablesize;
-
-    mod rustrt {
-        #[abi = "cdecl"]
-        extern {
-            pub fn rust_unset_sigprocmask();
-        }
-    }
-
-    #[cfg(windows)]
-    unsafe fn set_environ(_envp: *c_void) {}
-    #[cfg(target_os = "macos")]
-    unsafe fn set_environ(envp: *c_void) {
-        extern { fn _NSGetEnviron() -> *mut *c_void; }
-
-        *_NSGetEnviron() = envp;
-    }
-    #[cfg(not(target_os = "macos"), not(windows))]
-    unsafe fn set_environ(envp: *c_void) {
-        extern {
-            static mut environ: *c_void;
-        }
-        environ = envp;
-    }
-
-    unsafe {
-
-        let pid = fork();
-        if pid < 0 {
-            fail!("failure in fork: {}", os::last_os_error());
-        } else if pid > 0 {
-            return SpawnProcessResult {pid: pid, handle: ptr::null()};
-        }
-
-        rustrt::rust_unset_sigprocmask();
-
-        if dup2(in_fd, 0) == -1 {
-            fail!("failure in dup2(in_fd, 0): {}", os::last_os_error());
-        }
-        if dup2(out_fd, 1) == -1 {
-            fail!("failure in dup2(out_fd, 1): {}", os::last_os_error());
-        }
-        if dup2(err_fd, 2) == -1 {
-            fail!("failure in dup3(err_fd, 2): {}", os::last_os_error());
-        }
-        // close all other fds
-        for fd in range(3, getdtablesize()).invert() {
-            close(fd as c_int);
-        }
-
-        do with_dirp(dir) |dirp| {
-            if !dirp.is_null() && chdir(dirp) == -1 {
-                fail!("failure in chdir: {}", os::last_os_error());
-            }
-        }
-
-        do with_envp(env) |envp| {
-            if !envp.is_null() {
-                set_environ(envp);
-            }
-            do with_argv(prog, args) |argv| {
-                execvp(*argv, argv);
-                // execvp only returns if an error occurred
-                fail!("failure in execvp: {}", os::last_os_error());
-            }
-        }
-    }
-}
-
-#[cfg(unix)]
-fn with_argv<T>(prog: &str, args: &[~str], cb: &fn(**libc::c_char) -> T) -> T {
-    use vec;
-
-    // We can't directly convert `str`s into `*char`s, as someone needs to hold
-    // a reference to the intermediary byte buffers. So first build an array to
-    // hold all the ~[u8] byte strings.
-    let mut tmps = vec::with_capacity(args.len() + 1);
-
-    tmps.push(prog.to_c_str());
-
-    for arg in args.iter() {
-        tmps.push(arg.to_c_str());
-    }
-
-    // Next, convert each of the byte strings into a pointer. This is
-    // technically unsafe as the caller could leak these pointers out of our
-    // scope.
-    let mut ptrs = do tmps.map |tmp| {
-        tmp.with_ref(|buf| buf)
-    };
-
-    // Finally, make sure we add a null pointer.
-    ptrs.push(ptr::null());
-
-    ptrs.as_imm_buf(|buf, _| cb(buf))
-}
-
-#[cfg(unix)]
-fn with_envp<T>(env: Option<~[(~str, ~str)]>, cb: &fn(*c_void) -> T) -> T {
-    use vec;
-
-    // On posixy systems we can pass a char** for envp, which is a
-    // null-terminated array of "k=v\n" strings. Like `with_argv`, we have to
-    // have a temporary buffer to hold the intermediary `~[u8]` byte strings.
-    match env {
-        Some(env) => {
-            let mut tmps = vec::with_capacity(env.len());
-
-            for pair in env.iter() {
-                let kv = format!("{}={}", pair.first(), pair.second());
-                tmps.push(kv.to_c_str());
-            }
-
-            // Once again, this is unsafe.
-            let mut ptrs = do tmps.map |tmp| {
-                tmp.with_ref(|buf| buf)
-            };
-            ptrs.push(ptr::null());
-
-            do ptrs.as_imm_buf |buf, _| {
-                unsafe { cb(cast::transmute(buf)) }
-            }
-        }
-        _ => cb(ptr::null())
-    }
-}
-
-#[cfg(windows)]
-fn with_envp<T>(env: Option<~[(~str, ~str)]>, cb: &fn(*mut c_void) -> T) -> T {
-    // On win32 we pass an "environment block" which is not a char**, but
-    // rather a concatenation of null-terminated k=v\0 sequences, with a final
-    // \0 to terminate.
-    match env {
-        Some(env) => {
-            let mut blk = ~[];
-
-            for pair in env.iter() {
-                let kv = format!("{}={}", pair.first(), pair.second());
-                blk.push_all(kv.as_bytes());
-                blk.push(0);
-            }
-
-            blk.push(0);
-
-            do blk.as_imm_buf |p, _len| {
-                unsafe { cb(cast::transmute(p)) }
-            }
-        }
-        _ => cb(ptr::mut_null())
-    }
-}
-
-fn with_dirp<T>(d: Option<&Path>, cb: &fn(*libc::c_char) -> T) -> T {
-    match d {
-      Some(dir) => dir.with_c_str(|buf| cb(buf)),
-      None => cb(ptr::null())
-    }
-}
-
-#[cfg(windows)]
-fn free_handle(handle: *()) {
-    unsafe {
-        libc::funcs::extra::kernel32::CloseHandle(cast::transmute(handle));
-    }
-}
-
-#[cfg(unix)]
-fn free_handle(_handle: *()) {
-    // unix has no process handle object, just a pid
-}
-
-/**
- * Waits for a process to exit and returns the exit code, failing
- * if there is no process with the specified id.
- *
- * Note that this is private to avoid race conditions on unix where if
- * a user calls waitpid(some_process.get_id()) then some_process.finish()
- * and some_process.destroy() and some_process.finalize() will then either
- * operate on a none-existent process or, even worse, on a newer process
- * with the same id.
- */
-fn waitpid(pid: pid_t) -> int {
-    return waitpid_os(pid);
-
-    #[cfg(windows)]
-    fn waitpid_os(pid: pid_t) -> int {
-        use libc::types::os::arch::extra::DWORD;
-        use libc::consts::os::extra::{
-            SYNCHRONIZE,
-            PROCESS_QUERY_INFORMATION,
-            FALSE,
-            STILL_ACTIVE,
-            INFINITE,
-            WAIT_FAILED
-        };
-        use libc::funcs::extra::kernel32::{
-            OpenProcess,
-            GetExitCodeProcess,
-            CloseHandle,
-            WaitForSingleObject
-        };
-
-        unsafe {
-
-            let process = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
-                                      FALSE,
-                                      pid as DWORD);
-            if process.is_null() {
-                fail!("failure in OpenProcess: {}", os::last_os_error());
-            }
-
-            loop {
-                let mut status = 0;
-                if GetExitCodeProcess(process, &mut status) == FALSE {
-                    CloseHandle(process);
-                    fail!("failure in GetExitCodeProcess: {}", os::last_os_error());
-                }
-                if status != STILL_ACTIVE {
-                    CloseHandle(process);
-                    return status as int;
-                }
-                if WaitForSingleObject(process, INFINITE) == WAIT_FAILED {
-                    CloseHandle(process);
-                    fail!("failure in WaitForSingleObject: {}", os::last_os_error());
-                }
-            }
-        }
-    }
-
-    #[cfg(unix)]
-    fn waitpid_os(pid: pid_t) -> int {
-        use libc::funcs::posix01::wait::*;
-
-        #[cfg(target_os = "linux")]
-        #[cfg(target_os = "android")]
-        fn WIFEXITED(status: i32) -> bool {
-            (status & 0xffi32) == 0i32
-        }
-
-        #[cfg(target_os = "macos")]
-        #[cfg(target_os = "freebsd")]
-        fn WIFEXITED(status: i32) -> bool {
-            (status & 0x7fi32) == 0i32
-        }
-
-        #[cfg(target_os = "linux")]
-        #[cfg(target_os = "android")]
-        fn WEXITSTATUS(status: i32) -> i32 {
-            (status >> 8i32) & 0xffi32
-        }
-
-        #[cfg(target_os = "macos")]
-        #[cfg(target_os = "freebsd")]
-        fn WEXITSTATUS(status: i32) -> i32 {
-            status >> 8i32
-        }
-
-        let mut status = 0 as c_int;
-        if unsafe { waitpid(pid, &mut status, 0) } == -1 {
-            fail!("failure in waitpid: {}", os::last_os_error());
-        }
-
-        return if WIFEXITED(status) {
-            WEXITSTATUS(status) as int
-        } else {
-            1
-        };
-    }
-}
-
-#[cfg(test)]
-mod tests {
-
-    #[test] #[cfg(windows)]
-    fn test_make_command_line() {
-        use super::make_command_line;
-        assert_eq!(
-            make_command_line("prog", [~"aaa", ~"bbb", ~"ccc"]),
-            ~"prog aaa bbb ccc"
-        );
-        assert_eq!(
-            make_command_line("C:\\Program Files\\blah\\blah.exe", [~"aaa"]),
-            ~"\"C:\\Program Files\\blah\\blah.exe\" aaa"
-        );
-        assert_eq!(
-            make_command_line("C:\\Program Files\\test", [~"aa\"bb"]),
-            ~"\"C:\\Program Files\\test\" aa\\\"bb"
-        );
-        assert_eq!(
-            make_command_line("echo", [~"a b c"]),
-            ~"echo \"a b c\""
-        );
-    }
-
-    // Currently most of the tests of this functionality live inside std::run,
-    // but they may move here eventually as a non-blocking backend is added to
-    // std::run
-}
diff --git a/src/libstd/rt/io/native/stdio.rs b/src/libstd/rt/io/native/stdio.rs
deleted file mode 100644 (file)
index ddfbb9a..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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.
-
-use libc;
-use option::Option;
-use rt::io::{Reader, Writer};
-use super::file;
-
-/// Creates a new handle to the stdin of this process
-pub fn stdin() -> StdIn { StdIn::new() }
-/// Creates a new handle to the stdout of this process
-pub fn stdout() -> StdOut { StdOut::new(libc::STDOUT_FILENO) }
-/// Creates a new handle to the stderr of this process
-pub fn stderr() -> StdOut { StdOut::new(libc::STDERR_FILENO) }
-
-pub fn print(s: &str) {
-    stdout().write(s.as_bytes())
-}
-
-pub fn println(s: &str) {
-    let mut out = stdout();
-    out.write(s.as_bytes());
-    out.write(['\n' as u8]);
-}
-
-pub struct StdIn {
-    priv fd: file::FileDesc
-}
-
-impl StdIn {
-    /// Duplicates the stdin file descriptor, returning an io::Reader
-    pub fn new() -> StdIn {
-        StdIn { fd: file::FileDesc::new(libc::STDIN_FILENO, false) }
-    }
-}
-
-impl Reader for StdIn {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.fd.read(buf) }
-    fn eof(&mut self) -> bool { self.fd.eof() }
-}
-
-pub struct StdOut {
-    priv fd: file::FileDesc
-}
-
-impl StdOut {
-    /// Duplicates the specified file descriptor, returning an io::Writer
-    pub fn new(fd: file::fd_t) -> StdOut {
-        StdOut { fd: file::FileDesc::new(fd, false) }
-    }
-}
-
-impl Writer for StdOut {
-    fn write(&mut self, buf: &[u8]) { self.fd.write(buf) }
-    fn flush(&mut self) { self.fd.flush() }
-}
diff --git a/src/libstd/rt/io/net/addrinfo.rs b/src/libstd/rt/io/net/addrinfo.rs
deleted file mode 100644 (file)
index 684a642..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-// 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.
-
-/*!
-
-Synchronous DNS Resolution
-
-Contains the functionality to perform DNS resolution in a style related to
-getaddrinfo()
-
-*/
-
-use option::{Option, Some, None};
-use result::{Ok, Err};
-use rt::io::{io_error};
-use rt::io::net::ip::{SocketAddr, IpAddr};
-use rt::rtio::{IoFactory, with_local_io};
-
-/// Hints to the types of sockets that are desired when looking up hosts
-pub enum SocketType {
-    Stream, Datagram, Raw
-}
-
-/// Flags which can be or'd into the `flags` field of a `Hint`. These are used
-/// to manipulate how a query is performed.
-///
-/// The meaning of each of these flags can be found with `man -s 3 getaddrinfo`
-pub enum Flag {
-    AddrConfig,
-    All,
-    CanonName,
-    NumericHost,
-    NumericServ,
-    Passive,
-    V4Mapped,
-}
-
-/// A transport protocol associated with either a hint or a return value of
-/// `lookup`
-pub enum Protocol {
-    TCP, UDP
-}
-
-/// This structure is used to provide hints when fetching addresses for a
-/// remote host to control how the lookup is performed.
-///
-/// For details on these fields, see their corresponding definitions via
-/// `man -s 3 getaddrinfo`
-pub struct Hint {
-    family: uint,
-    socktype: Option<SocketType>,
-    protocol: Option<Protocol>,
-    flags: uint,
-}
-
-pub struct Info {
-    address: SocketAddr,
-    family: uint,
-    socktype: Option<SocketType>,
-    protocol: Option<Protocol>,
-    flags: uint,
-}
-
-/// Easy name resolution. Given a hostname, returns the list of IP addresses for
-/// that hostname.
-///
-/// # Failure
-///
-/// On failure, this will raise on the `io_error` condition.
-pub fn get_host_addresses(host: &str) -> Option<~[IpAddr]> {
-    lookup(Some(host), None, None).map(|a| a.map(|i| i.address.ip))
-}
-
-/// Full-fleged resolution. This function will perform a synchronous call to
-/// getaddrinfo, controlled by the parameters
-///
-/// # Arguments
-///
-/// * hostname - an optional hostname to lookup against
-/// * servname - an optional service name, listed in the system services
-/// * hint - see the hint structure, and "man -s 3 getaddrinfo", for how this
-///          controls lookup
-///
-/// # Failure
-///
-/// On failure, this will raise on the `io_error` condition.
-///
-/// XXX: this is not public because the `Hint` structure is not ready for public
-///      consumption just yet.
-fn lookup(hostname: Option<&str>, servname: Option<&str>,
-          hint: Option<Hint>) -> Option<~[Info]> {
-    do with_local_io |io| {
-        match io.get_host_addresses(hostname, servname, hint) {
-            Ok(i) => Some(i),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use option::Some;
-    use rt::io::net::ip::Ipv4Addr;
-    use super::*;
-
-    #[test]
-    #[ignore(cfg(target_os="android"))] // cannot give tcp/ip permission without help of apk
-    fn dns_smoke_test() {
-        let ipaddrs = get_host_addresses("localhost").unwrap();
-        let mut found_local = false;
-        let local_addr = &Ipv4Addr(127, 0, 0, 1);
-        for addr in ipaddrs.iter() {
-            found_local = found_local || addr == local_addr;
-        }
-        assert!(found_local);
-    }
-}
diff --git a/src/libstd/rt/io/net/ip.rs b/src/libstd/rt/io/net/ip.rs
deleted file mode 100644 (file)
index f72d2e1..0000000
+++ /dev/null
@@ -1,449 +0,0 @@
-// 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.
-
-use vec::MutableCloneableVector;
-use to_str::ToStr;
-use from_str::FromStr;
-use option::{Option, None, Some};
-
-
-pub type Port = u16;
-
-#[deriving(Eq, TotalEq, Clone)]
-pub enum IpAddr {
-    Ipv4Addr(u8, u8, u8, u8),
-    Ipv6Addr(u16, u16, u16, u16, u16, u16, u16, u16)
-}
-
-impl ToStr for IpAddr {
-    fn to_str(&self) -> ~str {
-        match *self {
-            Ipv4Addr(a, b, c, d) =>
-                format!("{}.{}.{}.{}", a, b, c, d),
-
-            // Ipv4 Compatible address
-            Ipv6Addr(0, 0, 0, 0, 0, 0, g, h) => {
-                format!("::{}.{}.{}.{}", (g >> 8) as u8, g as u8,
-                        (h >> 8) as u8, h as u8)
-            }
-
-            // Ipv4-Mapped address
-            Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, g, h) => {
-                format!("::FFFF:{}.{}.{}.{}", (g >> 8) as u8, g as u8,
-                        (h >> 8) as u8, h as u8)
-            }
-
-            Ipv6Addr(a, b, c, d, e, f, g, h) =>
-                format!("{}:{}:{}:{}:{}:{}:{}:{}", a, b, c, d, e, f, g, h)
-        }
-    }
-}
-
-#[deriving(Eq, TotalEq, Clone)]
-pub struct SocketAddr {
-    ip: IpAddr,
-    port: Port,
-}
-
-
-impl ToStr for SocketAddr {
-    fn to_str(&self) -> ~str {
-        match self.ip {
-            Ipv4Addr(*) => format!("{}:{}", self.ip.to_str(), self.port),
-            Ipv6Addr(*) => format!("[{}]:{}", self.ip.to_str(), self.port),
-        }
-    }
-}
-
-struct Parser<'self> {
-    // parsing as ASCII, so can use byte array
-    s: &'self [u8],
-    pos: uint,
-}
-
-impl<'self> Parser<'self> {
-    fn new(s: &'self str) -> Parser<'self> {
-        Parser {
-            s: s.as_bytes(),
-            pos: 0,
-        }
-    }
-
-    fn is_eof(&self) -> bool {
-        self.pos == self.s.len()
-    }
-
-    // Commit only if parser returns Some
-    fn read_atomically<T>(&mut self, cb: &fn(&mut Parser) -> Option<T>) -> Option<T> {
-        let pos = self.pos;
-        let r = cb(self);
-        if r.is_none() {
-            self.pos = pos;
-        }
-        r
-    }
-
-    // Commit only if parser read till EOF
-    fn read_till_eof<T>(&mut self, cb: &fn(&mut Parser) -> Option<T>) -> Option<T> {
-        do self.read_atomically |p| {
-            cb(p).filtered(|_| p.is_eof())
-        }
-    }
-
-    // Return result of first successful parser
-    fn read_or<T>(&mut self, parsers: &[&fn(&mut Parser) -> Option<T>]) -> Option<T> {
-        for pf in parsers.iter() {
-            match self.read_atomically(|p: &mut Parser| (*pf)(p)) {
-                Some(r) => return Some(r),
-                None => {}
-            }
-        }
-        None
-    }
-
-    // Apply 3 parsers sequentially
-    fn read_seq_3<A, B, C>(&mut self,
-            pa: &fn(&mut Parser) -> Option<A>,
-            pb: &fn(&mut Parser) -> Option<B>,
-            pc: &fn(&mut Parser) -> Option<C>
-        ) -> Option<(A, B, C)>
-    {
-        do self.read_atomically |p| {
-            let a = pa(p);
-            let b = if a.is_some() { pb(p) } else { None };
-            let c = if b.is_some() { pc(p) } else { None };
-            match (a, b, c) {
-                (Some(a), Some(b), Some(c)) => Some((a, b, c)),
-                _ => None
-            }
-        }
-    }
-
-    // Read next char
-    fn read_char(&mut self) -> Option<char> {
-        if self.is_eof() {
-            None
-        } else {
-            let r = self.s[self.pos] as char;
-            self.pos += 1;
-            Some(r)
-        }
-    }
-
-    // Return char and advance iff next char is equal to requested
-    fn read_given_char(&mut self, c: char) -> Option<char> {
-        do self.read_atomically |p| {
-            p.read_char().filtered(|&next| next == c)
-        }
-    }
-
-    // Read digit
-    fn read_digit(&mut self, radix: u8) -> Option<u8> {
-        fn parse_digit(c: char, radix: u8) -> Option<u8> {
-            let c = c as u8;
-            // assuming radix is either 10 or 16
-            if c >= '0' as u8 && c <= '9' as u8 {
-                Some((c - '0' as u8) as u8)
-            } else if radix > 10 && c >= 'a' as u8 && c < 'a' as u8 + (radix - 10) {
-                Some((c - 'a' as u8 + 10) as u8)
-            } else if radix > 10 && c >= 'A' as u8 && c < 'A' as u8 + (radix - 10) {
-                Some((c - 'A' as u8 + 10) as u8)
-            } else {
-                None
-            }
-        }
-
-        do self.read_atomically |p| {
-            p.read_char().and_then(|c| parse_digit(c, radix))
-        }
-    }
-
-    fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
-        let mut r = 0u32;
-        let mut digit_count = 0;
-        loop {
-            match self.read_digit(radix) {
-                Some(d) => {
-                    r = r * (radix as u32) + (d as u32);
-                    digit_count += 1;
-                    if digit_count > max_digits || r >= upto {
-                        return None
-                    }
-                }
-                None => {
-                    if digit_count == 0 {
-                        return None
-                    } else {
-                        return Some(r)
-                    }
-                }
-            };
-        }
-    }
-
-    // Read number, failing if max_digits of number value exceeded
-    fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
-        do self.read_atomically |p| {
-            p.read_number_impl(radix, max_digits, upto)
-        }
-    }
-
-    fn read_ipv4_addr_impl(&mut self) -> Option<IpAddr> {
-        let mut bs = [0u8, ..4];
-        let mut i = 0;
-        while i < 4 {
-            if i != 0 && self.read_given_char('.').is_none() {
-                return None;
-            }
-
-            let octet = self.read_number(10, 3, 0x100).map(|n| n as u8);
-            match octet {
-                Some(d) => bs[i] = d,
-                None => return None,
-            };
-            i += 1;
-        }
-        Some(Ipv4Addr(bs[0], bs[1], bs[2], bs[3]))
-    }
-
-    // Read IPv4 address
-    fn read_ipv4_addr(&mut self) -> Option<IpAddr> {
-        do self.read_atomically |p| {
-            p.read_ipv4_addr_impl()
-        }
-    }
-
-    fn read_ipv6_addr_impl(&mut self) -> Option<IpAddr> {
-        fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> IpAddr {
-            assert!(head.len() + tail.len() <= 8);
-            let mut gs = [0u16, ..8];
-            gs.copy_from(head);
-            gs.mut_slice(8 - tail.len(), 8).copy_from(tail);
-            Ipv6Addr(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
-        }
-
-        fn read_groups(p: &mut Parser, groups: &mut [u16, ..8], limit: uint) -> (uint, bool) {
-            let mut i = 0;
-            while i < limit {
-                if i < limit - 1 {
-                    let ipv4 = do p.read_atomically |p| {
-                        if i == 0 || p.read_given_char(':').is_some() {
-                            p.read_ipv4_addr()
-                        } else {
-                            None
-                        }
-                    };
-                    match ipv4 {
-                        Some(Ipv4Addr(a, b, c, d)) => {
-                            groups[i + 0] = (a as u16 << 8) | (b as u16);
-                            groups[i + 1] = (c as u16 << 8) | (d as u16);
-                            return (i + 2, true);
-                        }
-                        _ => {}
-                    }
-                }
-
-                let group = do p.read_atomically |p| {
-                    if i == 0 || p.read_given_char(':').is_some() {
-                        p.read_number(16, 4, 0x10000).map(|n| n as u16)
-                    } else {
-                        None
-                    }
-                };
-                match group {
-                    Some(g) => groups[i] = g,
-                    None => return (i, false)
-                }
-                i += 1;
-            }
-            (i, false)
-        }
-
-        let mut head = [0u16, ..8];
-        let (head_size, head_ipv4) = read_groups(self, &mut head, 8);
-
-        if head_size == 8 {
-            return Some(Ipv6Addr(
-                head[0], head[1], head[2], head[3],
-                head[4], head[5], head[6], head[7]))
-        }
-
-        // IPv4 part is not allowed before `::`
-        if head_ipv4 {
-            return None
-        }
-
-        // read `::` if previous code parsed less than 8 groups
-        if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
-            return None;
-        }
-
-        let mut tail = [0u16, ..8];
-        let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
-        Some(ipv6_addr_from_head_tail(head.slice(0, head_size), tail.slice(0, tail_size)))
-    }
-
-    fn read_ipv6_addr(&mut self) -> Option<IpAddr> {
-        do self.read_atomically |p| {
-            p.read_ipv6_addr_impl()
-        }
-    }
-
-    fn read_ip_addr(&mut self) -> Option<IpAddr> {
-        let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr();
-        let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr();
-        self.read_or([ipv4_addr, ipv6_addr])
-    }
-
-    fn read_socket_addr(&mut self) -> Option<SocketAddr> {
-        let ip_addr = |p: &mut Parser| {
-            let ipv4_p = |p: &mut Parser| p.read_ip_addr();
-            let ipv6_p = |p: &mut Parser| {
-                let open_br = |p: &mut Parser| p.read_given_char('[');
-                let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
-                let clos_br = |p: &mut Parser| p.read_given_char(']');
-                p.read_seq_3::<char, IpAddr, char>(open_br, ip_addr, clos_br)
-                        .map(|t| match t { (_, ip, _) => ip })
-            };
-            p.read_or([ipv4_p, ipv6_p])
-        };
-        let colon = |p: &mut Parser| p.read_given_char(':');
-        let port  = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|n| n as u16);
-
-        // host, colon, port
-        self.read_seq_3::<IpAddr, char, u16>(ip_addr, colon, port)
-                .map(|t| match t { (ip, _, port) => SocketAddr { ip: ip, port: port } })
-    }
-}
-
-impl FromStr for IpAddr {
-    fn from_str(s: &str) -> Option<IpAddr> {
-        do Parser::new(s).read_till_eof |p| {
-            p.read_ip_addr()
-        }
-    }
-}
-
-impl FromStr for SocketAddr {
-    fn from_str(s: &str) -> Option<SocketAddr> {
-        do Parser::new(s).read_till_eof |p| {
-            p.read_socket_addr()
-        }
-    }
-}
-
-
-#[cfg(test)]
-mod test {
-    use super::*;
-    use from_str::FromStr;
-    use option::{Option, Some, None};
-
-    #[test]
-    fn test_from_str_ipv4() {
-        assert_eq!(Some(Ipv4Addr(127, 0, 0, 1)), FromStr::from_str("127.0.0.1"));
-        assert_eq!(Some(Ipv4Addr(255, 255, 255, 255)), FromStr::from_str("255.255.255.255"));
-        assert_eq!(Some(Ipv4Addr(0, 0, 0, 0)), FromStr::from_str("0.0.0.0"));
-
-        // out of range
-        let none: Option<IpAddr> = FromStr::from_str("256.0.0.1");
-        assert_eq!(None, none);
-        // too short
-        let none: Option<IpAddr> = FromStr::from_str("255.0.0");
-        assert_eq!(None, none);
-        // too long
-        let none: Option<IpAddr> = FromStr::from_str("255.0.0.1.2");
-        assert_eq!(None, none);
-        // no number between dots
-        let none: Option<IpAddr> = FromStr::from_str("255.0..1");
-        assert_eq!(None, none);
-    }
-
-    #[test]
-    fn test_from_str_ipv6() {
-        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("0:0:0:0:0:0:0:0"));
-        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("0:0:0:0:0:0:0:1"));
-
-        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("::1"));
-        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("::"));
-
-        assert_eq!(Some(Ipv6Addr(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
-                FromStr::from_str("2a02:6b8::11:11"));
-
-        // too long group
-        let none: Option<IpAddr> = FromStr::from_str("::00000");
-        assert_eq!(None, none);
-        // too short
-        let none: Option<IpAddr> = FromStr::from_str("1:2:3:4:5:6:7");
-        assert_eq!(None, none);
-        // too long
-        let none: Option<IpAddr> = FromStr::from_str("1:2:3:4:5:6:7:8:9");
-        assert_eq!(None, none);
-        // triple colon
-        let none: Option<IpAddr> = FromStr::from_str("1:2:::6:7:8");
-        assert_eq!(None, none);
-        // two double colons
-        let none: Option<IpAddr> = FromStr::from_str("1:2::6::8");
-        assert_eq!(None, none);
-    }
-
-    #[test]
-    fn test_from_str_ipv4_in_ipv6() {
-        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 49152, 545)),
-                FromStr::from_str("::192.0.2.33"));
-        assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
-                FromStr::from_str("::FFFF:192.0.2.33"));
-        assert_eq!(Some(Ipv6Addr(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
-                FromStr::from_str("64:ff9b::192.0.2.33"));
-        assert_eq!(Some(Ipv6Addr(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
-                FromStr::from_str("2001:db8:122:c000:2:2100:192.0.2.33"));
-
-        // colon after v4
-        let none: Option<IpAddr> = FromStr::from_str("::127.0.0.1:");
-        assert_eq!(None, none);
-        // not enought groups
-        let none: Option<IpAddr> = FromStr::from_str("1.2.3.4.5:127.0.0.1");
-        assert_eq!(None, none);
-        // too many groups
-        let none: Option<IpAddr> =
-            FromStr::from_str("1.2.3.4.5:6:7:127.0.0.1");
-        assert_eq!(None, none);
-    }
-
-    #[test]
-    fn test_from_str_socket_addr() {
-        assert_eq!(Some(SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 80 }),
-                FromStr::from_str("77.88.21.11:80"));
-        assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 }),
-                FromStr::from_str("[2a02:6b8:0:1::1]:53"));
-        assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0, 0, 0, 0, 0, 0, 0x7F00, 1), port: 22 }),
-                FromStr::from_str("[::127.0.0.1]:22"));
-
-        // without port
-        let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1");
-        assert_eq!(None, none);
-        // without port
-        let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1:");
-        assert_eq!(None, none);
-        // wrong brackets around v4
-        let none: Option<SocketAddr> = FromStr::from_str("[127.0.0.1]:22");
-        assert_eq!(None, none);
-        // port out of range
-        let none: Option<SocketAddr> = FromStr::from_str("127.0.0.1:123456");
-        assert_eq!(None, none);
-    }
-
-    #[test]
-    fn ipv6_addr_to_str() {
-        let a1 = Ipv6Addr(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
-        assert!(a1.to_str() == ~"::ffff:192.0.2.128" || a1.to_str() == ~"::FFFF:192.0.2.128");
-    }
-
-}
diff --git a/src/libstd/rt/io/net/mod.rs b/src/libstd/rt/io/net/mod.rs
deleted file mode 100644 (file)
index cf10916..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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.
-
-pub use self::addrinfo::get_host_addresses;
-
-pub mod addrinfo;
-pub mod tcp;
-pub mod udp;
-pub mod ip;
-#[cfg(unix)]
-pub mod unix;
diff --git a/src/libstd/rt/io/net/tcp.rs b/src/libstd/rt/io/net/tcp.rs
deleted file mode 100644 (file)
index 493ed6a..0000000
+++ /dev/null
@@ -1,725 +0,0 @@
-// 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.
-
-use option::{Option, Some, None};
-use result::{Ok, Err};
-use rt::io::net::ip::SocketAddr;
-use rt::io::{Reader, Writer, Listener, Acceptor};
-use rt::io::{io_error, EndOfFile};
-use rt::rtio::{IoFactory, with_local_io,
-               RtioSocket, RtioTcpListener, RtioTcpAcceptor, RtioTcpStream};
-
-pub struct TcpStream {
-    priv obj: ~RtioTcpStream
-}
-
-impl TcpStream {
-    fn new(s: ~RtioTcpStream) -> TcpStream {
-        TcpStream { obj: s }
-    }
-
-    pub fn connect(addr: SocketAddr) -> Option<TcpStream> {
-        do with_local_io |io| {
-            match io.tcp_connect(addr) {
-                Ok(s) => Some(TcpStream::new(s)),
-                Err(ioerr) => {
-                    io_error::cond.raise(ioerr);
-                    None
-                }
-            }
-        }
-    }
-
-    pub fn peer_name(&mut self) -> Option<SocketAddr> {
-        match self.obj.peer_name() {
-            Ok(pn) => Some(pn),
-            Err(ioerr) => {
-                rtdebug!("failed to get peer name: {:?}", ioerr);
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
-    }
-
-    pub fn socket_name(&mut self) -> Option<SocketAddr> {
-        match self.obj.socket_name() {
-            Ok(sn) => Some(sn),
-            Err(ioerr) => {
-                rtdebug!("failed to get socket name: {:?}", ioerr);
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
-    }
-}
-
-impl Reader for TcpStream {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        match self.obj.read(buf) {
-            Ok(read) => Some(read),
-            Err(ioerr) => {
-                // EOF is indicated by returning None
-                if ioerr.kind != EndOfFile {
-                    io_error::cond.raise(ioerr);
-                }
-                return None;
-            }
-        }
-    }
-
-    fn eof(&mut self) -> bool { fail!() }
-}
-
-impl Writer for TcpStream {
-    fn write(&mut self, buf: &[u8]) {
-        match self.obj.write(buf) {
-            Ok(_) => (),
-            Err(ioerr) => io_error::cond.raise(ioerr),
-        }
-    }
-}
-
-pub struct TcpListener {
-    priv obj: ~RtioTcpListener
-}
-
-impl TcpListener {
-    pub fn bind(addr: SocketAddr) -> Option<TcpListener> {
-        do with_local_io |io| {
-            match io.tcp_bind(addr) {
-                Ok(l) => Some(TcpListener { obj: l }),
-                Err(ioerr) => {
-                    io_error::cond.raise(ioerr);
-                    None
-                }
-            }
-        }
-    }
-
-    pub fn socket_name(&mut self) -> Option<SocketAddr> {
-        match self.obj.socket_name() {
-            Ok(sn) => Some(sn),
-            Err(ioerr) => {
-                rtdebug!("failed to get socket name: {:?}", ioerr);
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
-    }
-}
-
-impl Listener<TcpStream, TcpAcceptor> for TcpListener {
-    fn listen(self) -> Option<TcpAcceptor> {
-        match self.obj.listen() {
-            Ok(acceptor) => Some(TcpAcceptor { obj: acceptor }),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
-    }
-}
-
-pub struct TcpAcceptor {
-    priv obj: ~RtioTcpAcceptor
-}
-
-impl Acceptor<TcpStream> for TcpAcceptor {
-    fn accept(&mut self) -> Option<TcpStream> {
-        match self.obj.accept() {
-            Ok(s) => Some(TcpStream::new(s)),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use super::*;
-    use cell::Cell;
-    use rt::test::*;
-    use rt::io::net::ip::{Ipv4Addr, SocketAddr};
-    use rt::io::*;
-    use prelude::*;
-    use rt::comm::oneshot;
-
-    #[test] #[ignore]
-    fn bind_error() {
-        do run_in_mt_newsched_task {
-            let mut called = false;
-            do io_error::cond.trap(|e| {
-                assert!(e.kind == PermissionDenied);
-                called = true;
-            }).inside {
-                let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
-                let listener = TcpListener::bind(addr);
-                assert!(listener.is_none());
-            }
-            assert!(called);
-        }
-    }
-
-    #[test]
-    fn connect_error() {
-        do run_in_mt_newsched_task {
-            let mut called = false;
-            do io_error::cond.trap(|e| {
-                let expected_error = if cfg!(unix) {
-                    ConnectionRefused
-                } else {
-                    // On Win32, opening port 1 gives WSAEADDRNOTAVAIL error.
-                    OtherIoError
-                };
-                assert_eq!(e.kind, expected_error);
-                called = true;
-            }).inside {
-                let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
-                let stream = TcpStream::connect(addr);
-                assert!(stream.is_none());
-            }
-            assert!(called);
-        }
-    }
-
-    #[test]
-    fn smoke_test_ip4() {
-        do run_in_mt_newsched_task {
-            let addr = next_test_ip4();
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-                let mut stream = acceptor.accept();
-                let mut buf = [0];
-                stream.read(buf);
-                assert!(buf[0] == 99);
-            }
-
-            do spawntask {
-                port.take().recv();
-                let mut stream = TcpStream::connect(addr);
-                stream.write([99]);
-            }
-        }
-    }
-
-    #[test]
-    fn smoke_test_ip6() {
-        do run_in_mt_newsched_task {
-            let addr = next_test_ip6();
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-                let mut stream = acceptor.accept();
-                let mut buf = [0];
-                stream.read(buf);
-                assert!(buf[0] == 99);
-            }
-
-            do spawntask {
-                port.take().recv();
-                let mut stream = TcpStream::connect(addr);
-                stream.write([99]);
-            }
-        }
-    }
-
-    #[test]
-    fn read_eof_ip4() {
-        do run_in_mt_newsched_task {
-            let addr = next_test_ip4();
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-                let mut stream = acceptor.accept();
-                let mut buf = [0];
-                let nread = stream.read(buf);
-                assert!(nread.is_none());
-            }
-
-            do spawntask {
-                port.take().recv();
-                let _stream = TcpStream::connect(addr);
-                // Close
-            }
-        }
-    }
-
-    #[test]
-    fn read_eof_ip6() {
-        do run_in_mt_newsched_task {
-            let addr = next_test_ip6();
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-                let mut stream = acceptor.accept();
-                let mut buf = [0];
-                let nread = stream.read(buf);
-                assert!(nread.is_none());
-            }
-
-            do spawntask {
-                port.take().recv();
-                let _stream = TcpStream::connect(addr);
-                // Close
-            }
-        }
-    }
-
-    #[test]
-    fn read_eof_twice_ip4() {
-        do run_in_mt_newsched_task {
-            let addr = next_test_ip4();
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-                let mut stream = acceptor.accept();
-                let mut buf = [0];
-                let nread = stream.read(buf);
-                assert!(nread.is_none());
-                do io_error::cond.trap(|e| {
-                    if cfg!(windows) {
-                        assert_eq!(e.kind, NotConnected);
-                    } else {
-                        fail!();
-                    }
-                }).inside {
-                    let nread = stream.read(buf);
-                    assert!(nread.is_none());
-                }
-            }
-
-            do spawntask {
-                port.take().recv();
-                let _stream = TcpStream::connect(addr);
-                // Close
-            }
-        }
-    }
-
-    #[test]
-    fn read_eof_twice_ip6() {
-        do run_in_mt_newsched_task {
-            let addr = next_test_ip6();
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-                let mut stream = acceptor.accept();
-                let mut buf = [0];
-                let nread = stream.read(buf);
-                assert!(nread.is_none());
-                do io_error::cond.trap(|e| {
-                    if cfg!(windows) {
-                        assert_eq!(e.kind, NotConnected);
-                    } else {
-                        fail!();
-                    }
-                }).inside {
-                    let nread = stream.read(buf);
-                    assert!(nread.is_none());
-                }
-            }
-
-            do spawntask {
-                port.take().recv();
-                let _stream = TcpStream::connect(addr);
-                // Close
-            }
-        }
-    }
-
-    #[test]
-    fn write_close_ip4() {
-        do run_in_mt_newsched_task {
-            let addr = next_test_ip4();
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-                let mut stream = acceptor.accept();
-                let buf = [0];
-                loop {
-                    let mut stop = false;
-                    do io_error::cond.trap(|e| {
-                        // NB: ECONNRESET on linux, EPIPE on mac, ECONNABORTED
-                        //     on windows
-                        assert!(e.kind == ConnectionReset ||
-                                e.kind == BrokenPipe ||
-                                e.kind == ConnectionAborted,
-                                "unknown error: {:?}", e);
-                        stop = true;
-                    }).inside {
-                        stream.write(buf);
-                    }
-                    if stop { break }
-                }
-            }
-
-            do spawntask {
-                port.take().recv();
-                let _stream = TcpStream::connect(addr);
-                // Close
-            }
-        }
-    }
-
-    #[test]
-    fn write_close_ip6() {
-        do run_in_mt_newsched_task {
-            let addr = next_test_ip6();
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-                let mut stream = acceptor.accept();
-                let buf = [0];
-                loop {
-                    let mut stop = false;
-                    do io_error::cond.trap(|e| {
-                        // NB: ECONNRESET on linux, EPIPE on mac, ECONNABORTED
-                        //     on windows
-                        assert!(e.kind == ConnectionReset ||
-                                e.kind == BrokenPipe ||
-                                e.kind == ConnectionAborted,
-                                "unknown error: {:?}", e);
-                        stop = true;
-                    }).inside {
-                        stream.write(buf);
-                    }
-                    if stop { break }
-                }
-            }
-
-            do spawntask {
-                port.take().recv();
-                let _stream = TcpStream::connect(addr);
-                // Close
-            }
-        }
-    }
-
-    #[test]
-    fn multiple_connect_serial_ip4() {
-        do run_in_mt_newsched_task {
-            let addr = next_test_ip4();
-            let max = 10;
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-                for ref mut stream in acceptor.incoming().take(max) {
-                    let mut buf = [0];
-                    stream.read(buf);
-                    assert_eq!(buf[0], 99);
-                }
-            }
-
-            do spawntask {
-                port.take().recv();
-                do max.times {
-                    let mut stream = TcpStream::connect(addr);
-                    stream.write([99]);
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn multiple_connect_serial_ip6() {
-        do run_in_mt_newsched_task {
-            let addr = next_test_ip6();
-            let max = 10;
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-                for ref mut stream in acceptor.incoming().take(max) {
-                    let mut buf = [0];
-                    stream.read(buf);
-                    assert_eq!(buf[0], 99);
-                }
-            }
-
-            do spawntask {
-                port.take().recv();
-                do max.times {
-                    let mut stream = TcpStream::connect(addr);
-                    stream.write([99]);
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn multiple_connect_interleaved_greedy_schedule_ip4() {
-        do run_in_mt_newsched_task {
-            let addr = next_test_ip4();
-            static MAX: int = 10;
-            let (port, chan) = oneshot();
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-                for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) {
-                    let stream = Cell::new(stream);
-                    // Start another task to handle the connection
-                    do spawntask {
-                        let mut stream = stream.take();
-                        let mut buf = [0];
-                        stream.read(buf);
-                        assert!(buf[0] == i as u8);
-                        rtdebug!("read");
-                    }
-                }
-            }
-
-            port.recv();
-            connect(0, addr);
-
-            fn connect(i: int, addr: SocketAddr) {
-                if i == MAX { return }
-
-                do spawntask {
-                    rtdebug!("connecting");
-                    let mut stream = TcpStream::connect(addr);
-                    // Connect again before writing
-                    connect(i + 1, addr);
-                    rtdebug!("writing");
-                    stream.write([i as u8]);
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn multiple_connect_interleaved_greedy_schedule_ip6() {
-        do run_in_mt_newsched_task {
-            let addr = next_test_ip6();
-            static MAX: int = 10;
-            let (port, chan) = oneshot();
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-                for (i, stream) in acceptor.incoming().enumerate().take(MAX as uint) {
-                    let stream = Cell::new(stream);
-                    // Start another task to handle the connection
-                    do spawntask {
-                        let mut stream = stream.take();
-                        let mut buf = [0];
-                        stream.read(buf);
-                        assert!(buf[0] == i as u8);
-                        rtdebug!("read");
-                    }
-                }
-            }
-
-            port.recv();
-            connect(0, addr);
-
-            fn connect(i: int, addr: SocketAddr) {
-                if i == MAX { return }
-
-                do spawntask {
-                    rtdebug!("connecting");
-                    let mut stream = TcpStream::connect(addr);
-                    // Connect again before writing
-                    connect(i + 1, addr);
-                    rtdebug!("writing");
-                    stream.write([i as u8]);
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn multiple_connect_interleaved_lazy_schedule_ip4() {
-        do run_in_mt_newsched_task {
-            let addr = next_test_ip4();
-            static MAX: int = 10;
-            let (port, chan) = oneshot();
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-                for stream in acceptor.incoming().take(MAX as uint) {
-                    let stream = Cell::new(stream);
-                    // Start another task to handle the connection
-                    do spawntask_later {
-                        let mut stream = stream.take();
-                        let mut buf = [0];
-                        stream.read(buf);
-                        assert!(buf[0] == 99);
-                        rtdebug!("read");
-                    }
-                }
-            }
-
-            port.recv();
-            connect(0, addr);
-
-            fn connect(i: int, addr: SocketAddr) {
-                if i == MAX { return }
-
-                do spawntask_later {
-                    rtdebug!("connecting");
-                    let mut stream = TcpStream::connect(addr);
-                    // Connect again before writing
-                    connect(i + 1, addr);
-                    rtdebug!("writing");
-                    stream.write([99]);
-                }
-            }
-        }
-    }
-    #[test]
-    fn multiple_connect_interleaved_lazy_schedule_ip6() {
-        do run_in_mt_newsched_task {
-            let addr = next_test_ip6();
-            static MAX: int = 10;
-            let (port, chan) = oneshot();
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-                for stream in acceptor.incoming().take(MAX as uint) {
-                    let stream = Cell::new(stream);
-                    // Start another task to handle the connection
-                    do spawntask_later {
-                        let mut stream = stream.take();
-                        let mut buf = [0];
-                        stream.read(buf);
-                        assert!(buf[0] == 99);
-                        rtdebug!("read");
-                    }
-                }
-            }
-
-            port.recv();
-            connect(0, addr);
-
-            fn connect(i: int, addr: SocketAddr) {
-                if i == MAX { return }
-
-                do spawntask_later {
-                    rtdebug!("connecting");
-                    let mut stream = TcpStream::connect(addr);
-                    // Connect again before writing
-                    connect(i + 1, addr);
-                    rtdebug!("writing");
-                    stream.write([99]);
-                }
-            }
-        }
-    }
-
-    #[cfg(test)]
-    fn socket_name(addr: SocketAddr) {
-        do run_in_mt_newsched_task {
-            do spawntask {
-                let mut listener = TcpListener::bind(addr).unwrap();
-
-                // Make sure socket_name gives
-                // us the socket we binded to.
-                let so_name = listener.socket_name();
-                assert!(so_name.is_some());
-                assert_eq!(addr, so_name.unwrap());
-
-            }
-        }
-    }
-
-    #[cfg(test)]
-    fn peer_name(addr: SocketAddr) {
-        do run_in_mt_newsched_task {
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = TcpListener::bind(addr).listen();
-                chan.take().send(());
-
-                acceptor.accept();
-            }
-
-            do spawntask {
-                port.take().recv();
-                let stream = TcpStream::connect(addr);
-
-                assert!(stream.is_some());
-                let mut stream = stream.unwrap();
-
-                // Make sure peer_name gives us the
-                // address/port of the peer we've
-                // connected to.
-                let peer_name = stream.peer_name();
-                assert!(peer_name.is_some());
-                assert_eq!(addr, peer_name.unwrap());
-            }
-        }
-    }
-
-    #[test]
-    fn socket_and_peer_name_ip4() {
-        peer_name(next_test_ip4());
-        socket_name(next_test_ip4());
-    }
-
-    #[test]
-    fn socket_and_peer_name_ip6() {
-        // XXX: peer name is not consistent
-        //peer_name(next_test_ip6());
-        socket_name(next_test_ip6());
-    }
-
-}
diff --git a/src/libstd/rt/io/net/udp.rs b/src/libstd/rt/io/net/udp.rs
deleted file mode 100644 (file)
index f9cf8f5..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-// 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.
-
-use option::{Option, Some, None};
-use result::{Ok, Err};
-use rt::io::net::ip::SocketAddr;
-use rt::io::{Reader, Writer};
-use rt::io::{io_error, EndOfFile};
-use rt::rtio::{RtioSocket, RtioUdpSocket, IoFactory, with_local_io};
-
-pub struct UdpSocket {
-    priv obj: ~RtioUdpSocket
-}
-
-impl UdpSocket {
-    pub fn bind(addr: SocketAddr) -> Option<UdpSocket> {
-        do with_local_io |io| {
-            match io.udp_bind(addr) {
-                Ok(s) => Some(UdpSocket { obj: s }),
-                Err(ioerr) => {
-                    io_error::cond.raise(ioerr);
-                    None
-                }
-            }
-        }
-    }
-
-    pub fn recvfrom(&mut self, buf: &mut [u8]) -> Option<(uint, SocketAddr)> {
-        match self.obj.recvfrom(buf) {
-            Ok((nread, src)) => Some((nread, src)),
-            Err(ioerr) => {
-                // EOF is indicated by returning None
-                if ioerr.kind != EndOfFile {
-                    io_error::cond.raise(ioerr);
-                }
-                None
-            }
-        }
-    }
-
-    pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) {
-        match self.obj.sendto(buf, dst) {
-            Ok(_) => (),
-            Err(ioerr) => io_error::cond.raise(ioerr),
-        }
-    }
-
-    pub fn connect(self, other: SocketAddr) -> UdpStream {
-        UdpStream { socket: self, connectedTo: other }
-    }
-
-    pub fn socket_name(&mut self) -> Option<SocketAddr> {
-        match self.obj.socket_name() {
-            Ok(sn) => Some(sn),
-            Err(ioerr) => {
-                rtdebug!("failed to get socket name: {:?}", ioerr);
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
-    }
-}
-
-pub struct UdpStream {
-    priv socket: UdpSocket,
-    priv connectedTo: SocketAddr
-}
-
-impl UdpStream {
-    pub fn as_socket<T>(&mut self, f: &fn(&mut UdpSocket) -> T) -> T { f(&mut self.socket) }
-
-    pub fn disconnect(self) -> UdpSocket { self.socket }
-}
-
-impl Reader for UdpStream {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        let peer = self.connectedTo;
-        do self.as_socket |sock| {
-            match sock.recvfrom(buf) {
-                Some((_nread, src)) if src != peer => Some(0),
-                Some((nread, _src)) => Some(nread),
-                None => None,
-            }
-        }
-    }
-
-    fn eof(&mut self) -> bool { fail!() }
-}
-
-impl Writer for UdpStream {
-    fn write(&mut self, buf: &[u8]) {
-        do self.as_socket |sock| {
-            sock.sendto(buf, self.connectedTo);
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use super::*;
-    use rt::test::*;
-    use rt::io::net::ip::{Ipv4Addr, SocketAddr};
-    use rt::io::*;
-    use option::{Some, None};
-    use rt::comm::oneshot;
-    use cell::Cell;
-
-    #[test]  #[ignore]
-    fn bind_error() {
-        do run_in_mt_newsched_task {
-            let mut called = false;
-            do io_error::cond.trap(|e| {
-                assert!(e.kind == PermissionDenied);
-                called = true;
-            }).inside {
-                let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
-                let socket = UdpSocket::bind(addr);
-                assert!(socket.is_none());
-            }
-            assert!(called);
-        }
-    }
-
-    #[test]
-    fn socket_smoke_test_ip4() {
-        do run_in_mt_newsched_task {
-            let server_ip = next_test_ip4();
-            let client_ip = next_test_ip4();
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                match UdpSocket::bind(server_ip) {
-                    Some(ref mut server) => {
-                        chan.take().send(());
-                        let mut buf = [0];
-                        match server.recvfrom(buf) {
-                            Some((nread, src)) => {
-                                assert_eq!(nread, 1);
-                                assert_eq!(buf[0], 99);
-                                assert_eq!(src, client_ip);
-                            }
-                            None => fail!()
-                        }
-                    }
-                    None => fail!()
-                }
-            }
-
-            do spawntask {
-                match UdpSocket::bind(client_ip) {
-                    Some(ref mut client) => {
-                        port.take().recv();
-                        client.sendto([99], server_ip)
-                    }
-                    None => fail!()
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn socket_smoke_test_ip6() {
-        do run_in_mt_newsched_task {
-            let server_ip = next_test_ip6();
-            let client_ip = next_test_ip6();
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                match UdpSocket::bind(server_ip) {
-                    Some(ref mut server) => {
-                        chan.take().send(());
-                        let mut buf = [0];
-                        match server.recvfrom(buf) {
-                            Some((nread, src)) => {
-                                assert_eq!(nread, 1);
-                                assert_eq!(buf[0], 99);
-                                assert_eq!(src, client_ip);
-                            }
-                            None => fail!()
-                        }
-                    }
-                    None => fail!()
-                }
-            }
-
-            do spawntask {
-                match UdpSocket::bind(client_ip) {
-                    Some(ref mut client) => {
-                        port.take().recv();
-                        client.sendto([99], server_ip)
-                    }
-                    None => fail!()
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn stream_smoke_test_ip4() {
-        do run_in_mt_newsched_task {
-            let server_ip = next_test_ip4();
-            let client_ip = next_test_ip4();
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                match UdpSocket::bind(server_ip) {
-                    Some(server) => {
-                        let server = ~server;
-                        let mut stream = server.connect(client_ip);
-                        chan.take().send(());
-                        let mut buf = [0];
-                        match stream.read(buf) {
-                            Some(nread) => {
-                                assert_eq!(nread, 1);
-                                assert_eq!(buf[0], 99);
-                            }
-                            None => fail!()
-                        }
-                    }
-                    None => fail!()
-                }
-            }
-
-            do spawntask {
-                match UdpSocket::bind(client_ip) {
-                    Some(client) => {
-                        let client = ~client;
-                        let mut stream = client.connect(server_ip);
-                        port.take().recv();
-                        stream.write([99]);
-                    }
-                    None => fail!()
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn stream_smoke_test_ip6() {
-        do run_in_mt_newsched_task {
-            let server_ip = next_test_ip6();
-            let client_ip = next_test_ip6();
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                match UdpSocket::bind(server_ip) {
-                    Some(server) => {
-                        let server = ~server;
-                        let mut stream = server.connect(client_ip);
-                        chan.take().send(());
-                        let mut buf = [0];
-                        match stream.read(buf) {
-                            Some(nread) => {
-                                assert_eq!(nread, 1);
-                                assert_eq!(buf[0], 99);
-                            }
-                            None => fail!()
-                        }
-                    }
-                    None => fail!()
-                }
-            }
-
-            do spawntask {
-                match UdpSocket::bind(client_ip) {
-                    Some(client) => {
-                        let client = ~client;
-                        let mut stream = client.connect(server_ip);
-                        port.take().recv();
-                        stream.write([99]);
-                    }
-                    None => fail!()
-                }
-            }
-        }
-    }
-
-    #[cfg(test)]
-    fn socket_name(addr: SocketAddr) {
-        do run_in_mt_newsched_task {
-            do spawntask {
-                let server = UdpSocket::bind(addr);
-
-                assert!(server.is_some());
-                let mut server = server.unwrap();
-
-                // Make sure socket_name gives
-                // us the socket we binded to.
-                let so_name = server.socket_name();
-                assert!(so_name.is_some());
-                assert_eq!(addr, so_name.unwrap());
-
-            }
-        }
-    }
-
-    #[test]
-    fn socket_name_ip4() {
-        socket_name(next_test_ip4());
-    }
-
-    #[test]
-    fn socket_name_ip6() {
-        socket_name(next_test_ip6());
-    }
-}
diff --git a/src/libstd/rt/io/net/unix.rs b/src/libstd/rt/io/net/unix.rs
deleted file mode 100644 (file)
index dd8a999..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-// 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.
-
-/*!
-
-Named pipes
-
-This module contains the ability to communicate over named pipes with
-synchronous I/O. On windows, this corresponds to talking over a Named Pipe,
-while on Unix it corresponds to UNIX domain sockets.
-
-These pipes are similar to TCP in the sense that you can have both a stream to a
-server and a server itself. The server provided accepts other `UnixStream`
-instances as clients.
-
-*/
-
-use prelude::*;
-
-use c_str::ToCStr;
-use rt::rtio::{IoFactory, RtioUnixListener, with_local_io};
-use rt::rtio::{RtioUnixAcceptor, RtioPipe};
-use rt::io::pipe::PipeStream;
-use rt::io::{io_error, Listener, Acceptor, Reader, Writer};
-
-/// A stream which communicates over a named pipe.
-pub struct UnixStream {
-    priv obj: PipeStream,
-}
-
-impl UnixStream {
-    fn new(obj: ~RtioPipe) -> UnixStream {
-        UnixStream { obj: PipeStream::new(obj) }
-    }
-
-    /// Connect to a pipe named by `path`. This will attempt to open a
-    /// connection to the underlying socket.
-    ///
-    /// The returned stream will be closed when the object falls out of scope.
-    ///
-    /// # Failure
-    ///
-    /// This function will raise on the `io_error` condition if the connection
-    /// could not be made.
-    ///
-    /// # Example
-    ///
-    ///     use std::rt::io::net::unix::UnixStream;
-    ///
-    ///     let server = Path("path/to/my/socket");
-    ///     let mut stream = UnixStream::connect(&server);
-    ///     stream.write([1, 2, 3]);
-    ///
-    pub fn connect<P: ToCStr>(path: &P) -> Option<UnixStream> {
-        do with_local_io |io| {
-            match io.unix_connect(&path.to_c_str()) {
-                Ok(s) => Some(UnixStream::new(s)),
-                Err(ioerr) => {
-                    io_error::cond.raise(ioerr);
-                    None
-                }
-            }
-        }
-    }
-}
-
-impl Reader for UnixStream {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> { self.obj.read(buf) }
-    fn eof(&mut self) -> bool { self.obj.eof() }
-}
-
-impl Writer for UnixStream {
-    fn write(&mut self, buf: &[u8]) { self.obj.write(buf) }
-}
-
-pub struct UnixListener {
-    priv obj: ~RtioUnixListener,
-}
-
-impl UnixListener {
-
-    /// Creates a new listener, ready to receive incoming connections on the
-    /// specified socket. The server will be named by `path`.
-    ///
-    /// This listener will be closed when it falls out of scope.
-    ///
-    /// # Failure
-    ///
-    /// This function will raise on the `io_error` condition if the specified
-    /// path could not be bound.
-    ///
-    /// # Example
-    ///
-    ///     use std::rt::io::net::unix::UnixListener;
-    ///
-    ///     let server = Path("path/to/my/socket");
-    ///     let mut stream = UnixListener::bind(&server);
-    ///     for client in stream.incoming() {
-    ///         let mut client = client;
-    ///         client.write([1, 2, 3, 4]);
-    ///     }
-    ///
-    pub fn bind<P: ToCStr>(path: &P) -> Option<UnixListener> {
-        do with_local_io |io| {
-            match io.unix_bind(&path.to_c_str()) {
-                Ok(s) => Some(UnixListener{ obj: s }),
-                Err(ioerr) => {
-                    io_error::cond.raise(ioerr);
-                    None
-                }
-            }
-        }
-    }
-}
-
-impl Listener<UnixStream, UnixAcceptor> for UnixListener {
-    fn listen(self) -> Option<UnixAcceptor> {
-        match self.obj.listen() {
-            Ok(acceptor) => Some(UnixAcceptor { obj: acceptor }),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
-    }
-}
-
-pub struct UnixAcceptor {
-    priv obj: ~RtioUnixAcceptor,
-}
-
-impl Acceptor<UnixStream> for UnixAcceptor {
-    fn accept(&mut self) -> Option<UnixStream> {
-        match self.obj.accept() {
-            Ok(s) => Some(UnixStream::new(s)),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-                None
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use prelude::*;
-    use super::*;
-    use cell::Cell;
-    use rt::test::*;
-    use rt::io::*;
-    use rt::comm::oneshot;
-
-    fn smalltest(server: ~fn(UnixStream), client: ~fn(UnixStream)) {
-        let server = Cell::new(server);
-        let client = Cell::new(client);
-        do run_in_mt_newsched_task {
-            let server = Cell::new(server.take());
-            let client = Cell::new(client.take());
-            let path1 = next_test_unix();
-            let path2 = path1.clone();
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = UnixListener::bind(&path1).listen();
-                chan.take().send(());
-                server.take()(acceptor.accept().unwrap());
-            }
-
-            do spawntask {
-                port.take().recv();
-                client.take()(UnixStream::connect(&path2).unwrap());
-            }
-        }
-    }
-
-    #[test]
-    fn bind_error() {
-        do run_in_mt_newsched_task {
-            let mut called = false;
-            do io_error::cond.trap(|e| {
-                assert!(e.kind == PermissionDenied);
-                called = true;
-            }).inside {
-                let listener = UnixListener::bind(&("path/to/nowhere"));
-                assert!(listener.is_none());
-            }
-            assert!(called);
-        }
-    }
-
-    #[test]
-    fn connect_error() {
-        do run_in_mt_newsched_task {
-            let mut called = false;
-            do io_error::cond.trap(|e| {
-                assert_eq!(e.kind, OtherIoError);
-                called = true;
-            }).inside {
-                let stream = UnixStream::connect(&("path/to/nowhere"));
-                assert!(stream.is_none());
-            }
-            assert!(called);
-        }
-    }
-
-    #[test]
-    fn smoke() {
-        smalltest(|mut server| {
-            let mut buf = [0];
-            server.read(buf);
-            assert!(buf[0] == 99);
-        }, |mut client| {
-            client.write([99]);
-        })
-    }
-
-    #[test]
-    fn read_eof() {
-        smalltest(|mut server| {
-            let mut buf = [0];
-            assert!(server.read(buf).is_none());
-            assert!(server.read(buf).is_none());
-        }, |_client| {
-            // drop the client
-        })
-    }
-
-    #[test]
-    fn write_begone() {
-        smalltest(|mut server| {
-            let buf = [0];
-            let mut stop = false;
-            while !stop{
-                do io_error::cond.trap(|e| {
-                    assert!(e.kind == BrokenPipe || e.kind == NotConnected,
-                            "unknown error {:?}", e);
-                    stop = true;
-                }).inside {
-                    server.write(buf);
-                }
-            }
-        }, |_client| {
-            // drop the client
-        })
-    }
-
-    #[test]
-    fn accept_lots() {
-        do run_in_mt_newsched_task {
-            let times = 10;
-            let path1 = next_test_unix();
-            let path2 = path1.clone();
-            let (port, chan) = oneshot();
-            let port = Cell::new(port);
-            let chan = Cell::new(chan);
-
-            do spawntask {
-                let mut acceptor = UnixListener::bind(&path1).listen();
-                chan.take().send(());
-                do times.times {
-                    let mut client = acceptor.accept();
-                    let mut buf = [0];
-                    client.read(buf);
-                    assert_eq!(buf[0], 100);
-                }
-            }
-
-            do spawntask {
-                port.take().recv();
-                do times.times {
-                    let mut stream = UnixStream::connect(&path2);
-                    stream.write([100]);
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn path_exists() {
-        do run_in_mt_newsched_task {
-            let path = next_test_unix();
-            let _acceptor = UnixListener::bind(&path).listen();
-            assert!(path.exists());
-        }
-    }
-}
diff --git a/src/libstd/rt/io/option.rs b/src/libstd/rt/io/option.rs
deleted file mode 100644 (file)
index 5938252..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-// 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.
-
-//! Implementations of I/O traits for the Option type
-//!
-//! I/O constructors return option types to allow errors to be handled.
-//! These implementations allow e.g. `Option<File>` to be used
-//! as a `Reader` without unwrapping the option first.
-
-use option::*;
-use super::{Reader, Writer, Listener, Acceptor, Seek, SeekStyle};
-use super::{standard_error, PreviousIoError, io_error, IoError};
-
-fn prev_io_error() -> IoError {
-    standard_error(PreviousIoError)
-}
-
-impl<W: Writer> Writer for Option<W> {
-    fn write(&mut self, buf: &[u8]) {
-        match *self {
-            Some(ref mut writer) => writer.write(buf),
-            None => io_error::cond.raise(prev_io_error())
-        }
-    }
-
-    fn flush(&mut self) {
-        match *self {
-            Some(ref mut writer) => writer.flush(),
-            None => io_error::cond.raise(prev_io_error())
-        }
-    }
-}
-
-impl<R: Reader> Reader for Option<R> {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        match *self {
-            Some(ref mut reader) => reader.read(buf),
-            None => {
-                io_error::cond.raise(prev_io_error());
-                None
-            }
-        }
-    }
-
-    fn eof(&mut self) -> bool {
-        match *self {
-            Some(ref mut reader) => reader.eof(),
-            None => {
-                io_error::cond.raise(prev_io_error());
-                true
-            }
-        }
-    }
-}
-
-impl<S: Seek> Seek for Option<S> {
-    fn tell(&self) -> u64 {
-        match *self {
-            Some(ref seeker) => seeker.tell(),
-            None => {
-                io_error::cond.raise(prev_io_error());
-                0
-            }
-        }
-    }
-    fn seek(&mut self, pos: i64, style: SeekStyle) {
-        match *self {
-            Some(ref mut seeker) => seeker.seek(pos, style),
-            None => io_error::cond.raise(prev_io_error())
-        }
-    }
-}
-
-impl<T, A: Acceptor<T>, L: Listener<T, A>> Listener<T, A> for Option<L> {
-    fn listen(self) -> Option<A> {
-        match self {
-            Some(listener) => listener.listen(),
-            None => {
-                io_error::cond.raise(prev_io_error());
-                None
-            }
-        }
-    }
-}
-
-impl<T, A: Acceptor<T>> Acceptor<T> for Option<A> {
-    fn accept(&mut self) -> Option<T> {
-        match *self {
-            Some(ref mut acceptor) => acceptor.accept(),
-            None => {
-                io_error::cond.raise(prev_io_error());
-                None
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use option::*;
-    use super::super::mem::*;
-    use rt::test::*;
-    use super::super::{PreviousIoError, io_error};
-
-    #[test]
-    fn test_option_writer() {
-        do run_in_mt_newsched_task {
-            let mut writer: Option<MemWriter> = Some(MemWriter::new());
-            writer.write([0, 1, 2]);
-            writer.flush();
-            assert_eq!(writer.unwrap().inner(), ~[0, 1, 2]);
-        }
-    }
-
-    #[test]
-    fn test_option_writer_error() {
-        do run_in_mt_newsched_task {
-            let mut writer: Option<MemWriter> = None;
-
-            let mut called = false;
-            do io_error::cond.trap(|err| {
-                assert_eq!(err.kind, PreviousIoError);
-                called = true;
-            }).inside {
-                writer.write([0, 0, 0]);
-            }
-            assert!(called);
-
-            let mut called = false;
-            do io_error::cond.trap(|err| {
-                assert_eq!(err.kind, PreviousIoError);
-                called = true;
-            }).inside {
-                writer.flush();
-            }
-            assert!(called);
-        }
-    }
-
-    #[test]
-    fn test_option_reader() {
-        do run_in_mt_newsched_task {
-            let mut reader: Option<MemReader> = Some(MemReader::new(~[0, 1, 2, 3]));
-            let mut buf = [0, 0];
-            reader.read(buf);
-            assert_eq!(buf, [0, 1]);
-            assert!(!reader.eof());
-        }
-    }
-
-    #[test]
-    fn test_option_reader_error() {
-        let mut reader: Option<MemReader> = None;
-        let mut buf = [];
-
-        let mut called = false;
-        do io_error::cond.trap(|err| {
-            assert_eq!(err.kind, PreviousIoError);
-            called = true;
-        }).inside {
-            reader.read(buf);
-        }
-        assert!(called);
-
-        let mut called = false;
-        do io_error::cond.trap(|err| {
-            assert_eq!(err.kind, PreviousIoError);
-            called = true;
-        }).inside {
-            assert!(reader.eof());
-        }
-        assert!(called);
-    }
-}
diff --git a/src/libstd/rt/io/pipe.rs b/src/libstd/rt/io/pipe.rs
deleted file mode 100644 (file)
index fbbd5a8..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-// 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.
-
-//! Synchronous, in-memory pipes.
-//!
-//! Currently these aren't particularly useful, there only exists bindings
-//! enough so that pipes can be created to child processes.
-
-use prelude::*;
-use super::{Reader, Writer};
-use rt::io::{io_error, EndOfFile};
-use rt::io::native::file;
-use rt::rtio::{RtioPipe, with_local_io};
-
-pub struct PipeStream {
-    priv obj: ~RtioPipe,
-}
-
-impl PipeStream {
-    /// Consumes a file descriptor to return a pipe stream that will have
-    /// synchronous, but non-blocking reads/writes. This is useful if the file
-    /// descriptor is acquired via means other than the standard methods.
-    ///
-    /// This operation consumes ownership of the file descriptor and it will be
-    /// closed once the object is deallocated.
-    ///
-    /// # Example
-    ///
-    ///     use std::libc;
-    ///     use std::rt::io::pipe;
-    ///
-    ///     let mut pipe = PipeStream::open(libc::STDERR_FILENO);
-    ///     pipe.write(bytes!("Hello, stderr!"));
-    ///
-    /// # Failure
-    ///
-    /// If the pipe cannot be created, an error will be raised on the
-    /// `io_error` condition.
-    pub fn open(fd: file::fd_t) -> Option<PipeStream> {
-        do with_local_io |io| {
-            match io.pipe_open(fd) {
-                Ok(obj) => Some(PipeStream { obj: obj }),
-                Err(e) => {
-                    io_error::cond.raise(e);
-                    None
-                }
-            }
-        }
-    }
-
-    pub fn new(inner: ~RtioPipe) -> PipeStream {
-        PipeStream { obj: inner }
-    }
-}
-
-impl Reader for PipeStream {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        match self.obj.read(buf) {
-            Ok(read) => Some(read),
-            Err(ioerr) => {
-                // EOF is indicated by returning None
-                if ioerr.kind != EndOfFile {
-                    io_error::cond.raise(ioerr);
-                }
-                return None;
-            }
-        }
-    }
-
-    fn eof(&mut self) -> bool { false }
-}
-
-impl Writer for PipeStream {
-    fn write(&mut self, buf: &[u8]) {
-        match self.obj.write(buf) {
-            Ok(_) => (),
-            Err(ioerr) => {
-                io_error::cond.raise(ioerr);
-            }
-        }
-    }
-}
diff --git a/src/libstd/rt/io/process.rs b/src/libstd/rt/io/process.rs
deleted file mode 100644 (file)
index 6b21cde..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-// 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.
-
-//! Bindings for executing child processes
-
-use prelude::*;
-use cell::Cell;
-
-use libc;
-use rt::io;
-use rt::io::io_error;
-use rt::rtio::{RtioProcess, IoFactory, with_local_io};
-
-use fmt;
-
-// windows values don't matter as long as they're at least one of unix's
-// TERM/KILL/INT signals
-#[cfg(windows)] pub static PleaseExitSignal: int = 15;
-#[cfg(windows)] pub static MustDieSignal: int = 9;
-#[cfg(not(windows))] pub static PleaseExitSignal: int = libc::SIGTERM as int;
-#[cfg(not(windows))] pub static MustDieSignal: int = libc::SIGKILL as int;
-
-pub struct Process {
-    priv handle: ~RtioProcess,
-    io: ~[Option<io::PipeStream>],
-}
-
-/// This configuration describes how a new process should be spawned. This is
-/// translated to libuv's own configuration
-pub struct ProcessConfig<'self> {
-    /// Path to the program to run
-    program: &'self str,
-
-    /// Arguments to pass to the program (doesn't include the program itself)
-    args: &'self [~str],
-
-    /// Optional environment to specify for the program. If this is None, then
-    /// it will inherit the current process's environment.
-    env: Option<&'self [(~str, ~str)]>,
-
-    /// Optional working directory for the new process. If this is None, then
-    /// the current directory of the running process is inherited.
-    cwd: Option<&'self str>,
-
-    /// Any number of streams/file descriptors/pipes may be attached to this
-    /// process. This list enumerates the file descriptors and such for the
-    /// process to be spawned, and the file descriptors inherited will start at
-    /// 0 and go to the length of this array.
-    ///
-    /// Standard file descriptors are:
-    ///
-    ///     0 - stdin
-    ///     1 - stdout
-    ///     2 - stderr
-    io: &'self [StdioContainer]
-}
-
-/// Describes what to do with a standard io stream for a child process.
-pub enum StdioContainer {
-    /// This stream will be ignored. This is the equivalent of attaching the
-    /// stream to `/dev/null`
-    Ignored,
-
-    /// The specified file descriptor is inherited for the stream which it is
-    /// specified for.
-    InheritFd(libc::c_int),
-
-    /// Creates a pipe for the specified file descriptor which will be created
-    /// when the process is spawned.
-    ///
-    /// The first boolean argument is whether the pipe is readable, and the
-    /// second is whether it is writable. These properties are from the view of
-    /// the *child* process, not the parent process.
-    CreatePipe(bool /* readable */, bool /* writable */),
-}
-
-/// Describes the result of a process after it has terminated.
-#[deriving(Eq)]
-pub enum ProcessExit {
-    /// Normal termination with an exit status.
-    ExitStatus(int),
-
-    /// Termination by signal, with the signal number.
-    ExitSignal(int),
-}
-
-impl fmt::Default for ProcessExit {
-    /// Format a ProcessExit enum, to nicely present the information.
-    fn fmt(obj: &ProcessExit, f: &mut fmt::Formatter) {
-        match *obj {
-            ExitStatus(code) =>  write!(f.buf, "exit code: {}", code),
-            ExitSignal(code) =>  write!(f.buf, "signal: {}", code),
-        }
-    }
-}
-
-impl ProcessExit {
-    /// Was termination successful? Signal termination not considered a success,
-    /// and success is defined as a zero exit status.
-    pub fn success(&self) -> bool {
-        return self.matches_exit_status(0);
-    }
-
-    /// Checks whether this ProcessExit matches the given exit status.
-    /// Termination by signal will never match an exit code.
-    pub fn matches_exit_status(&self, wanted: int) -> bool {
-        *self == ExitStatus(wanted)
-    }
-}
-
-impl Process {
-    /// Creates a new pipe initialized, but not bound to any particular
-    /// source/destination
-    pub fn new(config: ProcessConfig) -> Option<Process> {
-        let config = Cell::new(config);
-        do with_local_io |io| {
-            match io.spawn(config.take()) {
-                Ok((p, io)) => Some(Process{
-                    handle: p,
-                    io: io.move_iter().map(|p|
-                        p.map(|p| io::PipeStream::new(p))
-                    ).collect()
-                }),
-                Err(ioerr) => {
-                    io_error::cond.raise(ioerr);
-                    None
-                }
-            }
-        }
-    }
-
-    /// Returns the process id of this child process
-    pub fn id(&self) -> libc::pid_t { self.handle.id() }
-
-    /// Sends the specified signal to the child process, returning whether the
-    /// signal could be delivered or not.
-    ///
-    /// Note that this is purely a wrapper around libuv's `uv_process_kill`
-    /// function.
-    ///
-    /// If the signal delivery fails, then the `io_error` condition is raised on
-    pub fn signal(&mut self, signal: int) {
-        match self.handle.kill(signal) {
-            Ok(()) => {}
-            Err(err) => {
-                io_error::cond.raise(err)
-            }
-        }
-    }
-
-    /// Wait for the child to exit completely, returning the status that it
-    /// exited with. This function will continue to have the same return value
-    /// after it has been called at least once.
-    pub fn wait(&mut self) -> ProcessExit { self.handle.wait() }
-}
-
-impl Drop for Process {
-    fn drop(&mut self) {
-        // Close all I/O before exiting to ensure that the child doesn't wait
-        // forever to print some text or something similar.
-        for _ in range(0, self.io.len()) {
-            self.io.pop();
-        }
-
-        self.wait();
-    }
-}
-
-// Tests for this module can be found in the rtio-processes run-pass test, along
-// with the justification for why it's not located here.
diff --git a/src/libstd/rt/io/signal.rs b/src/libstd/rt/io/signal.rs
deleted file mode 100644 (file)
index 3f013d5..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-// 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.
-
-/*!
-
-Signal handling
-
-This modules provides bindings to receive signals safely, built on top of the
-local I/O factory. There are a number of defined signals which can be caught,
-but not all signals will work across all platforms (windows doesn't have
-definitions for a number of signals.
-
-*/
-
-use container::{Map, MutableMap};
-use comm::{Port, SharedChan, stream};
-use hashmap;
-use option::{Some, None};
-use result::{Err, Ok};
-use rt::io::io_error;
-use rt::rtio::{IoFactory, RtioSignal, with_local_io};
-
-#[repr(int)]
-#[deriving(Eq, IterBytes)]
-pub enum Signum {
-    /// Equivalent to SIGBREAK, delivered when the user presses Ctrl-Break.
-    Break = 21i,
-    /// Equivalent to SIGHUP, delivered when the user closes the terminal
-    /// window. On delivery of HangUp, the program is given approximately
-    /// 10 seconds to perfom any cleanup. After that, Windows will
-    /// unconditionally terminate it.
-    HangUp = 1i,
-    /// Equivalent to SIGINT, delivered when the user presses Ctrl-c.
-    Interrupt = 2i,
-    /// Equivalent to SIGQUIT, delivered when the user presses Ctrl-\.
-    Quit = 3i,
-    /// Equivalent to SIGTSTP, delivered when the user presses Ctrl-z.
-    StopTemporarily = 20i,
-    /// Equivalent to SIGUSR1.
-    User1 = 10i,
-    /// Equivalent to SIGUSR2.
-    User2 = 12i,
-    /// Equivalent to SIGWINCH, delivered when the console has been resized.
-    /// WindowSizeChange may not be delivered in a timely manner; size change
-    /// will only be detected when the cursor is being moved.
-    WindowSizeChange = 28i,
-}
-
-/// Listener provides a port to listen for registered signals.
-///
-/// Listener automatically unregisters its handles once it is out of scope.
-/// However, clients can still unregister signums manually.
-///
-/// # Example
-///
-/// ```rust
-/// use std::rt::io::signal::{Listener, Interrupt};
-///
-/// let mut listener = Listener::new();
-/// listener.register(signal::Interrupt);
-///
-/// do spawn {
-///     loop {
-///         match listener.port.recv() {
-///             Interrupt => println("Got Interrupt'ed"),
-///             _ => (),
-///         }
-///     }
-/// }
-///
-/// ```
-pub struct Listener {
-    /// A map from signums to handles to keep the handles in memory
-    priv handles: hashmap::HashMap<Signum, ~RtioSignal>,
-    /// chan is where all the handles send signums, which are received by
-    /// the clients from port.
-    priv chan: SharedChan<Signum>,
-
-    /// Clients of Listener can `recv()` from this port. This is exposed to
-    /// allow selection over this port as well as manipulation of the port
-    /// directly.
-    port: Port<Signum>,
-}
-
-impl Listener {
-    /// Creates a new listener for signals. Once created, signals are bound via
-    /// the `register` method (otherwise nothing will ever be received)
-    pub fn new() -> Listener {
-        let (port, chan) = stream();
-        Listener {
-            chan: SharedChan::new(chan),
-            port: port,
-            handles: hashmap::HashMap::new(),
-        }
-    }
-
-    /// Listen for a signal, returning true when successfully registered for
-    /// signum. Signals can be received using `recv()`.
-    ///
-    /// Once a signal is registered, this listener will continue to receive
-    /// notifications of signals until it is unregistered. This occurs
-    /// regardless of the number of other listeners registered in other tasks
-    /// (or on this task).
-    ///
-    /// Signals are still received if there is no task actively waiting for
-    /// a signal, and a later call to `recv` will return the signal that was
-    /// received while no task was waiting on it.
-    ///
-    /// # Failure
-    ///
-    /// If this function fails to register a signal handler, then an error will
-    /// be raised on the `io_error` condition and the function will return
-    /// false.
-    pub fn register(&mut self, signum: Signum) -> bool {
-        if self.handles.contains_key(&signum) {
-            return true; // self is already listening to signum, so succeed
-        }
-        do with_local_io |io| {
-            match io.signal(signum, self.chan.clone()) {
-                Ok(w) => {
-                    self.handles.insert(signum, w);
-                    Some(())
-                },
-                Err(ioerr) => {
-                    io_error::cond.raise(ioerr);
-                    None
-                }
-            }
-        }.is_some()
-    }
-
-    /// Unregisters a signal. If this listener currently had a handler
-    /// registered for the signal, then it will stop receiving any more
-    /// notification about the signal. If the signal has already been received,
-    /// it may still be returned by `recv`.
-    pub fn unregister(&mut self, signum: Signum) {
-        self.handles.pop(&signum);
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use libc;
-    use rt::io::timer;
-    use super::{Listener, Interrupt};
-    use comm::{GenericPort, Peekable};
-
-    // kill is only available on Unixes
-    #[cfg(unix)]
-    fn sigint() {
-        unsafe {
-            libc::funcs::posix88::signal::kill(libc::getpid(), libc::SIGINT);
-        }
-    }
-
-    #[test] #[cfg(unix, not(target_os="android"))] // FIXME(#10378)
-    fn test_io_signal_smoketest() {
-        let mut signal = Listener::new();
-        signal.register(Interrupt);
-        sigint();
-        timer::sleep(10);
-        match signal.port.recv() {
-            Interrupt => (),
-            s => fail!("Expected Interrupt, got {:?}", s),
-        }
-    }
-
-    #[test] #[cfg(unix, not(target_os="android"))] // FIXME(#10378)
-    fn test_io_signal_two_signal_one_signum() {
-        let mut s1 = Listener::new();
-        let mut s2 = Listener::new();
-        s1.register(Interrupt);
-        s2.register(Interrupt);
-        sigint();
-        timer::sleep(10);
-        match s1.port.recv() {
-            Interrupt => (),
-            s => fail!("Expected Interrupt, got {:?}", s),
-        }
-        match s2.port.recv() {
-            Interrupt => (),
-            s => fail!("Expected Interrupt, got {:?}", s),
-        }
-    }
-
-    #[test] #[cfg(unix, not(target_os="android"))] // FIXME(#10378)
-    fn test_io_signal_unregister() {
-        let mut s1 = Listener::new();
-        let mut s2 = Listener::new();
-        s1.register(Interrupt);
-        s2.register(Interrupt);
-        s2.unregister(Interrupt);
-        sigint();
-        timer::sleep(10);
-        if s2.port.peek() {
-            fail!("Unexpected {:?}", s2.port.recv());
-        }
-    }
-
-    #[cfg(windows)]
-    #[test]
-    fn test_io_signal_invalid_signum() {
-        use rt::io;
-        use super::User1;
-        let mut s = Listener::new();
-        let mut called = false;
-        do io::io_error::cond.trap(|_| {
-            called = true;
-        }).inside {
-            if s.register(User1) {
-                fail!("Unexpected successful registry of signum {:?}", User1);
-            }
-        }
-        assert!(called);
-    }
-}
diff --git a/src/libstd/rt/io/stdio.rs b/src/libstd/rt/io/stdio.rs
deleted file mode 100644 (file)
index e829c77..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-// 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.
-
-/*!
-
-This modules provides bindings to the local event loop's TTY interface, using it
-to have synchronous, but non-blocking versions of stdio. These handles can be
-inspected for information about terminal dimensions or related information
-about the stream or terminal that it is attached to.
-
-# Example
-
-```rust
-use std::rt::io;
-
-let mut out = io::stdout();
-out.write(bytes!("Hello, world!"));
-```
-
-*/
-
-use fmt;
-use libc;
-use option::{Option, Some, None};
-use result::{Ok, Err};
-use rt::io::buffered::LineBufferedWriter;
-use rt::rtio::{IoFactory, RtioTTY, RtioFileStream, with_local_io,
-               CloseAsynchronously};
-use super::{Reader, Writer, io_error, IoError, OtherIoError,
-            standard_error, EndOfFile};
-
-// And so begins the tale of acquiring a uv handle to a stdio stream on all
-// platforms in all situations. Our story begins by splitting the world into two
-// categories, windows and unix. Then one day the creators of unix said let
-// there be redirection! And henceforth there was redirection away from the
-// console for standard I/O streams.
-//
-// After this day, the world split into four factions:
-//
-// 1. Unix with stdout on a terminal.
-// 2. Unix with stdout redirected.
-// 3. Windows with stdout on a terminal.
-// 4. Windows with stdout redirected.
-//
-// Many years passed, and then one day the nation of libuv decided to unify this
-// world. After months of toiling, uv created three ideas: TTY, Pipe, File.
-// These three ideas propagated throughout the lands and the four great factions
-// decided to settle among them.
-//
-// The groups of 1, 2, and 3 all worked very hard towards the idea of TTY. Upon
-// doing so, they even enhanced themselves further then their Pipe/File
-// brethren, becoming the dominant powers.
-//
-// The group of 4, however, decided to work independently. They abandoned the
-// common TTY belief throughout, and even abandoned the fledgling Pipe belief.
-// The members of the 4th faction decided to only align themselves with File.
-//
-// tl;dr; TTY works on everything but when windows stdout is redirected, in that
-//        case pipe also doesn't work, but magically file does!
-enum StdSource {
-    TTY(~RtioTTY),
-    File(~RtioFileStream),
-}
-
-fn src<T>(fd: libc::c_int, readable: bool, f: &fn(StdSource) -> T) -> T {
-    do with_local_io |io| {
-        let fd = unsafe { libc::dup(fd) };
-        match io.tty_open(fd, readable) {
-            Ok(tty) => Some(f(TTY(tty))),
-            Err(_) => {
-                // It's not really that desirable if these handles are closed
-                // synchronously, and because they're squirreled away in a task
-                // structure the destructors will be run when the task is
-                // attempted to get destroyed. This means that if we run a
-                // synchronous destructor we'll attempt to do some scheduling
-                // operations which will just result in sadness.
-                Some(f(File(io.fs_from_raw_fd(fd, CloseAsynchronously))))
-            }
-        }
-    }.unwrap()
-}
-
-/// Creates a new non-blocking handle to the stdin of the current process.
-///
-/// See `stdout()` for notes about this function.
-pub fn stdin() -> StdReader {
-    do src(libc::STDIN_FILENO, true) |src| { StdReader { inner: src } }
-}
-
-/// Creates a new non-blocking handle to the stdout of the current process.
-///
-/// Note that this is a fairly expensive operation in that at least one memory
-/// allocation is performed. Additionally, this must be called from a runtime
-/// task context because the stream returned will be a non-blocking object using
-/// the local scheduler to perform the I/O.
-pub fn stdout() -> StdWriter {
-    do src(libc::STDOUT_FILENO, false) |src| { StdWriter { inner: src } }
-}
-
-/// Creates a new non-blocking handle to the stderr of the current process.
-///
-/// See `stdout()` for notes about this function.
-pub fn stderr() -> StdWriter {
-    do src(libc::STDERR_FILENO, false) |src| { StdWriter { inner: src } }
-}
-
-// Helper to access the local task's stdout handle
-//
-// Note that this is not a safe function to expose because you can create an
-// aliased pointer very easily:
-//
-//  do with_task_stdout |io1| {
-//      do with_task_stdout |io2| {
-//          // io1 aliases io2
-//      }
-//  }
-fn with_task_stdout(f: &fn(&mut Writer)) {
-    use rt::local::Local;
-    use rt::task::Task;
-
-    unsafe {
-        // Logging may require scheduling operations, so we can't remove the
-        // task from TLS right now, hence the unsafe borrow. Sad.
-        let task: *mut Task = Local::unsafe_borrow();
-
-        match (*task).stdout_handle {
-            Some(ref mut handle) => f(*handle),
-            None => {
-                let handle = stdout();
-                let mut handle = ~LineBufferedWriter::new(handle) as ~Writer;
-                f(handle);
-                (*task).stdout_handle = Some(handle);
-            }
-        }
-    }
-}
-
-/// Flushes the local task's stdout handle.
-///
-/// By default, this stream is a line-buffering stream, so flushing may be
-/// necessary to ensure that all output is printed to the screen (if there are
-/// no newlines printed).
-///
-/// Note that logging macros do not use this stream. Using the logging macros
-/// will emit output to stderr, and while they are line buffered the log
-/// messages are always terminated in a newline (no need to flush).
-pub fn flush() {
-    do with_task_stdout |io| {
-        io.flush();
-    }
-}
-
-/// Prints a string to the stdout of the current process. No newline is emitted
-/// after the string is printed.
-pub fn print(s: &str) {
-    do with_task_stdout |io| {
-        io.write(s.as_bytes());
-    }
-}
-
-/// Prints a string as a line. to the stdout of the current process. A literal
-/// `\n` character is printed to the console after the string.
-pub fn println(s: &str) {
-    do with_task_stdout |io| {
-        io.write(s.as_bytes());
-        io.write(['\n' as u8]);
-    }
-}
-
-/// Similar to `print`, but takes a `fmt::Arguments` structure to be compatible
-/// with the `format_args!` macro.
-pub fn print_args(fmt: &fmt::Arguments) {
-    do with_task_stdout |io| {
-        fmt::write(io, fmt);
-    }
-}
-
-/// Similar to `println`, but takes a `fmt::Arguments` structure to be
-/// compatible with the `format_args!` macro.
-pub fn println_args(fmt: &fmt::Arguments) {
-    do with_task_stdout |io| {
-        fmt::writeln(io, fmt);
-    }
-}
-
-/// Representation of a reader of a standard input stream
-pub struct StdReader {
-    priv inner: StdSource
-}
-
-impl Reader for StdReader {
-    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
-        let ret = match self.inner {
-            TTY(ref mut tty) => tty.read(buf),
-            File(ref mut file) => file.read(buf).map(|i| i as uint),
-        };
-        match ret {
-            // When reading a piped stdin, libuv will return 0-length reads when
-            // stdin reaches EOF. For pretty much all other streams it will
-            // return an actual EOF error, but apparently for stdin it's a
-            // little different. Hence, here we convert a 0 length read to an
-            // end-of-file indicator so the caller knows to stop reading.
-            Ok(0) => {
-                io_error::cond.raise(standard_error(EndOfFile));
-                None
-            }
-            Ok(amt) => Some(amt as uint),
-            Err(e) => {
-                io_error::cond.raise(e);
-                None
-            }
-        }
-    }
-
-    fn eof(&mut self) -> bool { false }
-}
-
-/// Representation of a writer to a standard output stream
-pub struct StdWriter {
-    priv inner: StdSource
-}
-
-impl StdWriter {
-    /// Gets the size of this output window, if possible. This is typically used
-    /// when the writer is attached to something like a terminal, this is used
-    /// to fetch the dimensions of the terminal.
-    ///
-    /// If successful, returns Some((width, height)).
-    ///
-    /// # Failure
-    ///
-    /// This function will raise on the `io_error` condition if an error
-    /// happens.
-    pub fn winsize(&mut self) -> Option<(int, int)> {
-        match self.inner {
-            TTY(ref mut tty) => {
-                match tty.get_winsize() {
-                    Ok(p) => Some(p),
-                    Err(e) => {
-                        io_error::cond.raise(e);
-                        None
-                    }
-                }
-            }
-            File(*) => {
-                io_error::cond.raise(IoError {
-                    kind: OtherIoError,
-                    desc: "stream is not a tty",
-                    detail: None,
-                });
-                None
-            }
-        }
-    }
-
-    /// Controls whether this output stream is a "raw stream" or simply a normal
-    /// stream.
-    ///
-    /// # Failure
-    ///
-    /// This function will raise on the `io_error` condition if an error
-    /// happens.
-    pub fn set_raw(&mut self, raw: bool) {
-        match self.inner {
-            TTY(ref mut tty) => {
-                match tty.set_raw(raw) {
-                    Ok(()) => {},
-                    Err(e) => io_error::cond.raise(e),
-                }
-            }
-            File(*) => {
-                io_error::cond.raise(IoError {
-                    kind: OtherIoError,
-                    desc: "stream is not a tty",
-                    detail: None,
-                });
-            }
-        }
-    }
-
-    /// Returns whether this stream is attached to a TTY instance or not.
-    pub fn isatty(&self) -> bool {
-        match self.inner {
-            TTY(*) => true,
-            File(*) => false,
-        }
-    }
-}
-
-impl Writer for StdWriter {
-    fn write(&mut self, buf: &[u8]) {
-        let ret = match self.inner {
-            TTY(ref mut tty) => tty.write(buf),
-            File(ref mut file) => file.write(buf),
-        };
-        match ret {
-            Ok(()) => {}
-            Err(e) => io_error::cond.raise(e)
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn smoke() {
-        // Just make sure we can acquire handles
-        stdin();
-        stdout();
-        stderr();
-    }
-}
diff --git a/src/libstd/rt/io/timer.rs b/src/libstd/rt/io/timer.rs
deleted file mode 100644 (file)
index 48e0182..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-// 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.
-
-/*!
-
-Synchronous Timers
-
-This module exposes the functionality to create timers, block the current task,
-and create ports which will receive notifications after a period of time.
-
-# Example
-
-```rust
-
-use std::rt::io::Timer;
-
-let mut timer = Timer::new().unwrap();
-timer.sleep(10); // block the task for awhile
-
-let timeout = timer.oneshot(10);
-// do some work
-timeout.recv(); // wait for the timeout to expire
-
-let periodic = timer.periodic(10);
-loop {
-    periodic.recv();
-    // this loop is only executed once every 10ms
-}
-
-```
-
-*/
-
-use comm::{Port, PortOne};
-use option::{Option, Some, None};
-use result::{Ok, Err};
-use rt::io::io_error;
-use rt::rtio::{IoFactory, RtioTimer, with_local_io};
-
-pub struct Timer {
-    priv obj: ~RtioTimer
-}
-
-/// Sleep the current task for `msecs` milliseconds.
-pub fn sleep(msecs: u64) {
-    let mut timer = Timer::new().expect("timer::sleep: could not create a Timer");
-
-    timer.sleep(msecs)
-}
-
-impl Timer {
-    /// Creates a new timer which can be used to put the current task to sleep
-    /// for a number of milliseconds, or to possibly create channels which will
-    /// get notified after an amount of time has passed.
-    pub fn new() -> Option<Timer> {
-        do with_local_io |io| {
-            match io.timer_init() {
-                Ok(t) => Some(Timer { obj: t }),
-                Err(ioerr) => {
-                    rtdebug!("Timer::init: failed to init: {:?}", ioerr);
-                    io_error::cond.raise(ioerr);
-                    None
-                }
-            }
-
-        }
-    }
-
-    /// Blocks the current task for `msecs` milliseconds.
-    ///
-    /// Note that this function will cause any other ports for this timer to be
-    /// invalidated (the other end will be closed).
-    pub fn sleep(&mut self, msecs: u64) {
-        self.obj.sleep(msecs);
-    }
-
-    /// Creates a oneshot port which will have a notification sent when `msecs`
-    /// milliseconds has elapsed. This does *not* block the current task, but
-    /// instead returns immediately.
-    ///
-    /// Note that this invalidates any previous port which has been created by
-    /// this timer, and that the returned port will be invalidated once the
-    /// timer is destroyed (when it falls out of scope).
-    pub fn oneshot(&mut self, msecs: u64) -> PortOne<()> {
-        self.obj.oneshot(msecs)
-    }
-
-    /// Creates a port which will have a continuous stream of notifications
-    /// being sent every `msecs` milliseconds. This does *not* block the
-    /// current task, but instead returns immediately. The first notification
-    /// will not be received immediately, but rather after `msec` milliseconds
-    /// have passed.
-    ///
-    /// Note that this invalidates any previous port which has been created by
-    /// this timer, and that the returned port will be invalidated once the
-    /// timer is destroyed (when it falls out of scope).
-    pub fn periodic(&mut self, msecs: u64) -> Port<()> {
-        self.obj.period(msecs)
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use prelude::*;
-    use super::*;
-    use rt::test::*;
-
-    #[test]
-    fn test_io_timer_sleep_simple() {
-        do run_in_mt_newsched_task {
-            let mut timer = Timer::new().unwrap();
-            timer.sleep(1);
-        }
-    }
-
-    #[test]
-    fn test_io_timer_sleep_oneshot() {
-        do run_in_mt_newsched_task {
-            let mut timer = Timer::new().unwrap();
-            timer.oneshot(1).recv();
-        }
-    }
-
-    #[test]
-    fn test_io_timer_sleep_oneshot_forget() {
-        do run_in_mt_newsched_task {
-            let mut timer = Timer::new().unwrap();
-            timer.oneshot(100000000000);
-        }
-    }
-
-    #[test]
-    fn oneshot_twice() {
-        do run_in_mt_newsched_task {
-            let mut timer = Timer::new().unwrap();
-            let port1 = timer.oneshot(10000);
-            let port = timer.oneshot(1);
-            port.recv();
-            assert_eq!(port1.try_recv(), None);
-        }
-    }
-
-    #[test]
-    fn test_io_timer_oneshot_then_sleep() {
-        do run_in_mt_newsched_task {
-            let mut timer = Timer::new().unwrap();
-            let port = timer.oneshot(100000000000);
-            timer.sleep(1); // this should invalidate the port
-
-            assert_eq!(port.try_recv(), None);
-        }
-    }
-
-    #[test]
-    fn test_io_timer_sleep_periodic() {
-        do run_in_mt_newsched_task {
-            let mut timer = Timer::new().unwrap();
-            let port = timer.periodic(1);
-            port.recv();
-            port.recv();
-            port.recv();
-        }
-    }
-
-    #[test]
-    fn test_io_timer_sleep_periodic_forget() {
-        do run_in_mt_newsched_task {
-            let mut timer = Timer::new().unwrap();
-            timer.periodic(100000000000);
-        }
-    }
-
-    #[test]
-    fn test_io_timer_sleep_standalone() {
-        do run_in_mt_newsched_task {
-            sleep(1)
-        }
-    }
-}
index f346380ff7a479edeb9ba6617f6f706da1750e06..55a6280a1f4684d2ae8c39afead7bce6d45b5ef9 100644 (file)
@@ -12,9 +12,9 @@
 use from_str::from_str;
 use libc::exit;
 use option::{Some, None, Option};
-use rt::io;
-use rt::io::stdio::StdWriter;
-use rt::io::buffered::LineBufferedWriter;
+use io;
+use io::stdio::StdWriter;
+use io::buffered::LineBufferedWriter;
 use rt::crate_map::{ModEntry, CrateMap, iter_crate_map, get_crate_map};
 use str::StrSlice;
 use u32;
index f18b4dc4234ec9ba627d6dae2b255992baadaf83..c90aafff20cc43f8c1ded93ce24d896cf38faef5 100644 (file)
@@ -116,8 +116,10 @@ pub mod shouldnt_be_public {
 /// The coroutine task scheduler, built on the `io` event loop.
 pub mod sched;
 
-/// Synchronous I/O.
-pub mod io;
+#[cfg(stage0)]
+pub mod io {
+    pub use io::stdio;
+}
 
 /// The EventLoop and internal synchronous I/O interface.
 pub mod rtio;
index 9b1103b8a746bd7ec3810bc06f6a8295b63661d0..ca1fd413a5628d397a58e8cdae13e73bb6e308cc 100644 (file)
@@ -8,21 +8,21 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use c_str::CString;
+use comm::{SharedChan, PortOne, Port};
+use libc::c_int;
 use libc;
 use option::*;
+use path::Path;
 use result::*;
-use comm::{SharedChan, PortOne, Port};
-use libc::c_int;
-use c_str::CString;
 
-use ai = rt::io::net::addrinfo;
-use rt::io::IoError;
-use rt::io::signal::Signum;
-use super::io::process::{ProcessConfig, ProcessExit};
-use super::io::net::ip::{IpAddr, SocketAddr};
-use path::Path;
-use super::io::{SeekStyle};
-use super::io::{FileMode, FileAccess, FileStat, FilePermission};
+use ai = io::net::addrinfo;
+use io::IoError;
+use io::net::ip::{IpAddr, SocketAddr};
+use io::process::{ProcessConfig, ProcessExit};
+use io::signal::Signum;
+use io::{FileMode, FileAccess, FileStat, FilePermission};
+use io::{SeekStyle};
 
 pub trait Callback {
     fn call(&mut self);
@@ -78,7 +78,7 @@ pub enum CloseBehavior {
 pub fn with_local_io<T>(f: &fn(&mut IoFactory) -> Option<T>) -> Option<T> {
     use rt::sched::Scheduler;
     use rt::local::Local;
-    use rt::io::{io_error, standard_error, IoUnavailable};
+    use io::{io_error, standard_error, IoUnavailable};
 
     unsafe {
         let sched: *mut Scheduler = Local::unsafe_borrow();
index f4e5811acd31290d9acb8e2874287954698eb04d..26cd405efe2e4015eba4eace08e303b10a7508b5 100644 (file)
@@ -1133,7 +1133,7 @@ fn test_stress_schedule_task_states() {
 
     #[test]
     fn test_io_callback() {
-        use rt::io::timer;
+        use io::timer;
 
         // This is a regression test that when there are no schedulable tasks
         // in the work queue, but we are performing I/O, that once we do put
index 7620a4371c14bfc11bf4dd90630a30e51ab0a055..e73d15abb6c7684943195136a3e515f0d0439bca 100644 (file)
@@ -29,7 +29,7 @@
 use rt::context::Context;
 use rt::context;
 use rt::env;
-use rt::io::Writer;
+use io::Writer;
 use rt::kill::Death;
 use rt::local::Local;
 use rt::logging::StdErrLogger;
index 3db9c049eb2df6ecad9e0871c85d29585e99565c..19ab36a6ac4d97fb51c02256c43d58d2818deb41 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr};
+use io::net::ip::{SocketAddr, Ipv4Addr, Ipv6Addr};
 
 use cell::Cell;
 use clone::Clone;
index 50f73becef2b8b84f5ecdb17298e1954346aa24f..42546cb3c6a99448c5755c1b7bb9e233dc274d16 100644 (file)
@@ -68,8 +68,8 @@ pub fn default_sched_threads() -> uint {
 }
 
 pub fn dumb_println(args: &fmt::Arguments) {
-    use rt::io::native::stdio::stderr;
-    use rt::io::{Writer, io_error, ResourceUnavailable};
+    use io::native::stdio::stderr;
+    use io::{Writer, io_error, ResourceUnavailable};
     use rt::task::Task;
     use rt::local::Local;
 
index c9b33a14c527cbf0b454c7a53337b3f55722a773..3bc56d2653a21028f1835fb3b32c4284bfa70819 100644 (file)
 
 use cell::Cell;
 use comm::{stream, SharedChan};
+use io::Reader;
+use io::process::ProcessExit;
+use io::process;
+use io;
 use libc::{pid_t, c_int};
 use libc;
 use prelude::*;
-use rt::io::process;
-use rt::io::process::ProcessExit;
-use rt::io;
-use rt::io::Reader;
 use task;
 
 /**
@@ -335,8 +335,8 @@ mod tests {
     use str;
     use task::spawn;
     use unstable::running_on_valgrind;
-    use rt::io::native::file;
-    use rt::io::{Writer, Reader};
+    use io::native::file;
+    use io::{Writer, Reader};
 
     #[test]
     #[cfg(not(target_os="android"))] // FIXME(#10380)
index 8c78e34528bdec63928586c28717ee449a8e5018..8b424c53be0b8aa9513b571c7669ac5b144c2818 100644 (file)
@@ -358,8 +358,8 @@ pub trait ToBytes {
 
 impl<A:IterBytes> ToBytes for A {
     fn to_bytes(&self, lsb0: bool) -> ~[u8] {
-        use rt::io::mem;
-        use rt::io::Writer;
+        use io::mem;
+        use io::Writer;
 
         do mem::with_mem_writer |wr| {
             do self.iter_bytes(lsb0) |bytes| {
index 838ce4a630948590238cf2d40af7a223f3a60c59..0565399bdf4d692a2cf92868229ba7df4daaad5f 100644 (file)
@@ -11,7 +11,7 @@
 use codemap::{Pos, Span};
 use codemap;
 
-use std::rt::io;
+use std::io;
 use std::local_data;
 use extra::term;
 
index f8155ae2e6bc33242955de69bbc5ee4753286b91..b70cb59caaf3b19f8cd3780a3db286ccd95d9d7d 100644 (file)
@@ -945,10 +945,10 @@ macro_rules! writeln(($dst:expr, $($arg:tt)*) => (
         format_args!(|args| { ::std::fmt::writeln($dst, args) }, $($arg)*)
     ))
     macro_rules! print (
-        ($($arg:tt)*) => (format_args!(::std::rt::io::stdio::print_args, $($arg)*))
+        ($($arg:tt)*) => (format_args!(::std::io::stdio::print_args, $($arg)*))
     )
     macro_rules! println (
-        ($($arg:tt)*) => (format_args!(::std::rt::io::stdio::println_args, $($arg)*))
+        ($($arg:tt)*) => (format_args!(::std::io::stdio::println_args, $($arg)*))
     )
 
     macro_rules! local_data_key (
@@ -1436,7 +1436,7 @@ fn renaming () {
     }
 
     fn fake_print_crate(crate: &ast::Crate) {
-        let out = @mut std::rt::io::stderr() as @mut std::rt::io::Writer;
+        let out = @mut std::io::stderr() as @mut std::io::Writer;
         let s = pprust::rust_printer(out, get_ident_interner());
         pprust::print_crate_(s, crate);
     }
index 75b5ab81f9bb3324024c84cc3d9f76f8402b1357..5a37e0a5ab319bb27f825a078be99e45abf295cf 100644 (file)
@@ -19,8 +19,8 @@
 use parse::token::{get_ident_interner};
 use print::pprust;
 
-use std::rt::io;
-use std::rt::io::File;
+use std::io;
+use std::io::File;
 use std::str;
 
 // These macros all relate to the file system; they either return
index 38fd65836aaeccaca88cb07838021e9c7bb1da90..4d8a6e08d0d07e57924257f77fb495bc59fb1b81 100644 (file)
@@ -18,7 +18,7 @@
 use parse::token;
 use parse::token::{get_ident_interner};
 
-use std::rt::io;
+use std::io;
 use std::str;
 use std::uint;
 
index 672865aadcc2672123a45a47375f9b079b945bab..0e9a529f950b2d55820225777a978693e0db726e 100644 (file)
@@ -19,8 +19,8 @@
 use parse::lexer::reader;
 use parse::parser::Parser;
 
-use std::rt::io;
-use std::rt::io::File;
+use std::io;
+use std::io::File;
 use std::str;
 
 pub mod lexer;
@@ -332,9 +332,9 @@ mod test {
     use super::*;
     use extra::serialize::Encodable;
     use extra;
-    use std::rt::io;
-    use std::rt::io::Decorator;
-    use std::rt::io::mem::MemWriter;
+    use std::io;
+    use std::io::Decorator;
+    use std::io::mem::MemWriter;
     use std::str;
     use codemap::{Span, BytePos, Spanned};
     use opt_vec;
index 4801fa21fc4936043f6181a1769d50212e0113cc..9eae40e4c718431a2145cb60d95555fb91542fa4 100644 (file)
@@ -61,7 +61,7 @@
  * avoid combining it with other lines and making matters even worse.
  */
 
-use std::rt::io;
+use std::io;
 use std::vec;
 
 #[deriving(Clone, Eq)]
index ed8eb4b54271075c289394eb631a8301052dcfd5..9c4803474d9d2e4b37e3fb2913b8c2024237910e 100644 (file)
@@ -29,9 +29,9 @@
 
 use std::char;
 use std::str;
-use std::rt::io;
-use std::rt::io::Decorator;
-use std::rt::io::mem::MemWriter;
+use std::io;
+use std::io::Decorator;
+use std::io::mem::MemWriter;
 
 // The @ps is stored here to prevent recursive type.
 pub enum ann_node<'self> {
index 2c86fdfe6ad722d8c498a801d7ee9ba0b9b9f523..4f1e267257538607958f606ba288f1a986120106 100644 (file)
@@ -21,7 +21,7 @@
 use std::str;
 use std::util;
 use std::vec;
-use std::rt::io::File;
+use std::io::File;
 
 macro_rules! bench (
     ($argv:expr, $id:ident) => (maybe_run_test($argv, stringify!($id).to_owned(), $id))
@@ -70,7 +70,7 @@ fn shift_push() {
 }
 
 fn read_line() {
-    use std::rt::io::buffered::BufferedReader;
+    use std::io::buffered::BufferedReader;
 
     let mut path = Path::new(env!("CFG_SRC_DIR"));
     path.push("src/test/bench/shootout-k-nucleotide.data");
index d7d7e9a58f3ca1cce2b10ef18e207a26610ca4b1..098512e9549153b02d2fee1fb631ee49032f8182 100644 (file)
@@ -18,8 +18,8 @@
 extern mod extra;
 
 use std::int;
-use std::rt::io;
-use std::rt::io::File;
+use std::io;
+use std::io::File;
 use std::os;
 use std::rand::Rng;
 use std::rand;
index 25f24faede22274a9d051c11a5e9359ed877c87f..0937c71f91f4c0b5d180d75aab387b225b463ce4 100644 (file)
@@ -22,7 +22,7 @@
 use std::hashmap::HashMap;
 use std::option;
 use std::os;
-use std::rt::io;
+use std::io;
 use std::str;
 use std::task;
 use std::util;
@@ -153,10 +153,10 @@ fn make_sequence_processor(sz: uint,
 
 // given a FASTA file on stdin, process sequence THREE
 fn main() {
-    use std::rt::io::Reader;
-    use std::rt::io::native::stdio;
-    use std::rt::io::mem::MemReader;
-    use std::rt::io::buffered::BufferedReader;
+    use std::io::Reader;
+    use std::io::native::stdio;
+    use std::io::mem::MemReader;
+    use std::io::buffered::BufferedReader;
 
     let rdr = if os::getenv("RUST_BENCH").is_some() {
         let foo = include_bin!("shootout-k-nucleotide.data");
index d4f4a46af38b123d85118fbc7e0b58e61a7d9434..8b0b106b732f3dd4abdaef2fe39b2b2499c331b9 100644 (file)
@@ -14,9 +14,9 @@
 
 extern mod extra;
 
-use std::rt::io;
-use std::rt::io::stdio::StdReader;
-use std::rt::io::buffered::BufferedReader;
+use std::io;
+use std::io::stdio::StdReader;
+use std::io::buffered::BufferedReader;
 use std::os;
 use std::uint;
 use std::unstable::intrinsics::cttz16;
index e9cd860bd226eacc01894b6cd4f6f674a2b552a9..4a224fd52c9d99ff9fdd3153b58897bc52810906 100644 (file)
@@ -18,7 +18,7 @@
 use std::libc;
 use std::run;
 use std::str;
-use std::rt::io;
+use std::io;
 
 #[test]
 fn test_destroy_once() {
index 8d3ad26764281ee52d68784e491e94268f86b81e..5812800259b860bc8c5d9c30a678b6d0131f2dce 100644 (file)
@@ -17,8 +17,8 @@
 
 extern mod extra;
 
-use std::rt::io::mem::MemWriter;
-use std::rt::io::Decorator;
+use std::io::mem::MemWriter;
+use std::io::Decorator;
 use std::rand::{random, Rand};
 use extra::serialize::{Encodable, Decodable};
 use extra::ebml;
index 897ee9cb88b06609f5ff16ba611cbb7e927eb1a1..8e516f748ffd44f19998ede5d5deade316f737e3 100644 (file)
@@ -16,7 +16,7 @@
 use extra::tempfile::TempDir;
 use std::unstable::finally::Finally;
 use std::{os, unstable};
-use std::rt::io;
+use std::io;
 
 pub fn main() {
     fn mk_file(path: &str, directory: bool) {
index 75d11eddb1bc68a0fc80016c5fed0ed7c4231031..04958936fbe2de16faf3a44b7f4cae564fbe33b8 100644 (file)
 #[deny(warnings)];
 
 use std::fmt;
-use std::rt::io::Decorator;
-use std::rt::io::mem::MemWriter;
-use std::rt::io;
-use std::rt::io::Writer;
+use std::io::Decorator;
+use std::io::mem::MemWriter;
+use std::io;
+use std::io::Writer;
 use std::str;
 
 struct A;
index 5a3b177aadcd2786019f855fa80165b399f511a9..5208995a0c7cf1e555c018962dfa54405c5ce82d 100644 (file)
@@ -16,7 +16,7 @@
 
 extern mod extra;
 
-use std::rt::io;
+use std::io;
 use std::to_str;
 
 enum square {
index 86cef39abc81f5b023e25676789b57e6861d74ef..6fb66cd3b1580a2f49f750fb84616fc2ef90cb38 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::rt::io;
+use std::io;
 
 pub fn main() {
     let stdout = &mut io::stdout() as &mut io::Writer;
index 31ac2c46293188bb0adc271231286417ff9bbd0c..f9169618c2a3b3c41ecb68beaed91ceff2527a2d 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::rt::io;
+use std::io;
 
 fn foo(a: &mut io::Writer) {
     a.write([])
index bdadcbdb72958eec1c4998ec4bc405dc04f8f806..d20f2bfef3bad4e420ea4dede3b5876f1eb7ac5f 100644 (file)
@@ -17,8 +17,8 @@
 use extra::tempfile::TempDir;
 use std::os;
 use std::libc;
-use std::rt::io;
-use std::rt::io::fs;
+use std::io;
+use std::io::fs;
 
 fn rename_directory() {
     unsafe {
index 2228f284fc31335df985c6676011d8e28658d01b..00f565324ecda46b31faf6bd0f63638bd5434147 100644 (file)
@@ -23,9 +23,9 @@
 //
 // See #9341
 
-use std::rt::io;
-use std::rt::io::process;
-use std::rt::io::process::{Process, ProcessConfig, CreatePipe, Ignored};
+use std::io;
+use std::io::process;
+use std::io::process::{Process, ProcessConfig, CreatePipe, Ignored};
 use std::str;
 
 #[test]
index e3dc4dcaadb411f553559216580e840114e1df88..3773ff5b263b94bdfd265f51cb87dcd4378316f7 100644 (file)
@@ -11,7 +11,7 @@
 // xfail-fast
 
 use std::{os, run};
-use std::rt::io::process;
+use std::io::process;
 
 fn main() {
     let args = os::args();
index 9ce3d318064c98274be3da892ceb5af0ee821ebc..b186a6828106285ff19ce4f31d8a06a985392618 100644 (file)
@@ -13,7 +13,7 @@
 extern mod extra;
 
 use extra::tempfile;
-use std::rt::io::File;
+use std::io::File;
 
 pub fn main() {
     let dir = tempfile::TempDir::new_in(&Path::new("."), "").unwrap();
index 3a115ab29cf54635a06c541e6fc0fee7a3a22d34..0a2905099efd27a8ca6dd8fb6922c2e5fbd64a07 100644 (file)
@@ -24,8 +24,8 @@
 use std::os;
 use std::task;
 use std::cell::Cell;
-use std::rt::io;
-use std::rt::io::fs;
+use std::io;
+use std::io::fs;
 
 fn test_tempdir() {
     let path = {