about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2013-05-17 10:45:09 -0700
committerPatrick Walton <pcwalton@mimiga.net>2013-05-22 21:57:05 -0700
commit0c820d4123c754522b0655e9e74f692c55685bfa (patch)
tree7dbb86c30b451217b4e8f75173043744fe3255ff /src/libstd
parent565942b145efbf6c1d1f66db46423d721b55d32c (diff)
downloadrust-0c820d4123c754522b0655e9e74f692c55685bfa.tar.gz
rust-0c820d4123c754522b0655e9e74f692c55685bfa.zip
libstd: Rename libcore to libstd and libstd to libextra; update makefiles.
This only changes the directory names; it does not change the "real"
metadata names.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/arc.rs803
-rw-r--r--src/libstd/arena.rs314
-rw-r--r--src/libstd/at_vec.rs323
-rw-r--r--src/libstd/base64.rs247
-rw-r--r--src/libstd/bitv.rs1494
-rw-r--r--src/libstd/bool.rs153
-rw-r--r--src/libstd/c_vec.rs202
-rw-r--r--src/libstd/cast.rs160
-rw-r--r--src/libstd/cell.rs136
-rw-r--r--src/libstd/char.rs406
-rw-r--r--src/libstd/cleanup.rs253
-rw-r--r--src/libstd/clone.rs184
-rw-r--r--src/libstd/cmp.rs265
-rw-r--r--src/libstd/comm.rs808
-rw-r--r--src/libstd/condition.rs217
-rw-r--r--src/libstd/container.rs101
-rw-r--r--src/libstd/core.rc226
-rw-r--r--src/libstd/dbg.rs78
-rw-r--r--src/libstd/deque.rs329
-rw-r--r--src/libstd/dlist.rs981
-rw-r--r--src/libstd/ebml.rs957
-rw-r--r--src/libstd/either.rs256
-rw-r--r--src/libstd/fileinput.rs604
-rw-r--r--src/libstd/flate.rs107
-rw-r--r--src/libstd/flatpipes.rs962
-rw-r--r--src/libstd/from_str.rs (renamed from src/libstd/net.rs)18
-rw-r--r--src/libstd/fun_treemap.rs72
-rw-r--r--src/libstd/future.rs210
-rw-r--r--src/libstd/gc.rs371
-rw-r--r--src/libstd/getopts.rs1381
-rw-r--r--src/libstd/hash.rs557
-rw-r--r--src/libstd/hashmap.rs989
-rw-r--r--src/libstd/io.rs2105
-rw-r--r--src/libstd/io_util.rs60
-rw-r--r--src/libstd/iter.rs326
-rw-r--r--src/libstd/iterator.rs719
-rw-r--r--src/libstd/json.rs1958
-rw-r--r--src/libstd/kinds.rs53
-rw-r--r--src/libstd/libc.rs2054
-rw-r--r--src/libstd/list.rs270
-rw-r--r--src/libstd/local_data.rs226
-rw-r--r--src/libstd/logging.rs97
-rw-r--r--src/libstd/macros.rs53
-rw-r--r--src/libstd/managed.rs100
-rw-r--r--src/libstd/md4.rs141
-rw-r--r--src/libstd/net_ip.rs447
-rw-r--r--src/libstd/net_tcp.rs1970
-rw-r--r--src/libstd/net_url.rs1068
-rw-r--r--src/libstd/nil.rs50
-rw-r--r--src/libstd/num/bigint.rs2021
-rw-r--r--src/libstd/num/cmath.rs270
-rw-r--r--src/libstd/num/complex.rs309
-rw-r--r--src/libstd/num/f32.rs1250
-rw-r--r--src/libstd/num/f64.rs1295
-rw-r--r--src/libstd/num/float.rs1387
-rw-r--r--src/libstd/num/int-template.rs929
-rw-r--r--src/libstd/num/int-template/i16.rs41
-rw-r--r--src/libstd/num/int-template/i32.rs41
-rw-r--r--src/libstd/num/int-template/i64.rs41
-rw-r--r--src/libstd/num/int-template/i8.rs41
-rw-r--r--src/libstd/num/int-template/int.rs104
-rw-r--r--src/libstd/num/num.rs494
-rw-r--r--src/libstd/num/rational.rs531
-rw-r--r--src/libstd/num/strconv.rs673
-rw-r--r--src/libstd/num/uint-template.rs641
-rw-r--r--src/libstd/num/uint-template/u16.rs43
-rw-r--r--src/libstd/num/uint-template/u32.rs43
-rw-r--r--src/libstd/num/uint-template/u64.rs43
-rw-r--r--src/libstd/num/uint-template/u8.rs43
-rw-r--r--src/libstd/num/uint-template/uint.rs256
-rw-r--r--src/libstd/old_iter.rs348
-rw-r--r--src/libstd/ops.rs81
-rw-r--r--src/libstd/option.rs468
-rw-r--r--src/libstd/os.rs1670
-rw-r--r--src/libstd/owned.rs33
-rw-r--r--src/libstd/par.rs139
-rw-r--r--src/libstd/path.rs1200
-rw-r--r--src/libstd/pipes.rs916
-rw-r--r--src/libstd/prelude.rs111
-rw-r--r--src/libstd/priority_queue.rs320
-rw-r--r--src/libstd/ptr.rs561
-rw-r--r--src/libstd/rand.rs1092
-rw-r--r--src/libstd/rand/distributions.rs148
-rw-r--r--src/libstd/rand/ziggurat_tables.rs412
-rw-r--r--src/libstd/rc.rs368
-rw-r--r--src/libstd/reflect.rs500
-rw-r--r--src/libstd/repr.rs639
-rw-r--r--src/libstd/result.rs456
-rw-r--r--src/libstd/rl.rs88
-rw-r--r--src/libstd/rope.rs1430
-rw-r--r--src/libstd/rt/context.rs214
-rw-r--r--src/libstd/rt/env.rs49
-rw-r--r--src/libstd/rt/io/comm_adapters.rs58
-rw-r--r--src/libstd/rt/io/extensions.rs903
-rw-r--r--src/libstd/rt/io/file.rs79
-rw-r--r--src/libstd/rt/io/flate.rs121
-rw-r--r--src/libstd/rt/io/mem.rs221
-rw-r--r--src/libstd/rt/io/mod.rs504
-rw-r--r--src/libstd/rt/io/native/file.rs74
-rw-r--r--src/libstd/rt/io/net/http.rs29
-rw-r--r--src/libstd/rt/io/net/ip.rs14
-rw-r--r--src/libstd/rt/io/net/tcp.rs359
-rw-r--r--src/libstd/rt/io/net/udp.rs45
-rw-r--r--src/libstd/rt/io/net/unix.rs45
-rw-r--r--src/libstd/rt/io/option.rs153
-rw-r--r--src/libstd/rt/io/stdio.rs53
-rw-r--r--src/libstd/rt/io/support.rs42
-rw-r--r--src/libstd/rt/local_heap.rs80
-rw-r--r--src/libstd/rt/mod.rs243
-rw-r--r--src/libstd/rt/rtio.rs45
-rw-r--r--src/libstd/rt/stack.rs76
-rw-r--r--src/libstd/rt/task.rs230
-rw-r--r--src/libstd/rt/test.rs192
-rw-r--r--src/libstd/rt/thread.rs44
-rw-r--r--src/libstd/rt/thread_local_storage.rs100
-rw-r--r--src/libstd/rt/uv/file.rs48
-rw-r--r--src/libstd/rt/uv/mod.rs420
-rw-r--r--src/libstd/rt/uv/net.rs436
-rw-r--r--src/libstd/rt/uvio.rs459
-rw-r--r--src/libstd/rt/uvll.rs443
-rw-r--r--src/libstd/rt/work_queue.rs67
-rw-r--r--src/libstd/run.rs856
-rw-r--r--src/libstd/semver.rs394
-rw-r--r--src/libstd/serialize.rs907
-rw-r--r--src/libstd/sha1.rs414
-rw-r--r--src/libstd/smallintmap.rs516
-rw-r--r--src/libstd/sort.rs1221
-rw-r--r--src/libstd/stackwalk.rs81
-rw-r--r--src/libstd/stats.rs96
-rw-r--r--src/libstd/std.rc120
-rw-r--r--src/libstd/str.rs4036
-rw-r--r--src/libstd/str/ascii.rs287
-rw-r--r--src/libstd/sync.rs1351
-rw-r--r--src/libstd/sys.rs352
-rw-r--r--src/libstd/task/local_data_priv.rs235
-rw-r--r--src/libstd/task/mod.rs1189
-rw-r--r--src/libstd/task/rt.rs71
-rw-r--r--src/libstd/task/spawn.rs791
-rw-r--r--src/libstd/task_pool.rs104
-rw-r--r--src/libstd/tempfile.rs116
-rw-r--r--src/libstd/term.rs77
-rw-r--r--src/libstd/test.rs966
-rw-r--r--src/libstd/time.rs1268
-rw-r--r--src/libstd/timer.rs292
-rw-r--r--src/libstd/to_bytes.rs354
-rw-r--r--src/libstd/to_str.rs240
-rw-r--r--src/libstd/treemap.rs1240
-rw-r--r--src/libstd/trie.rs548
-rw-r--r--src/libstd/tuple.rs439
-rw-r--r--src/libstd/unicode.rs2830
-rw-r--r--src/libstd/unstable/at_exit.rs100
-rw-r--r--src/libstd/unstable/exchange_alloc.rs83
-rw-r--r--src/libstd/unstable/extfmt.rs690
-rw-r--r--src/libstd/unstable/finally.rs139
-rw-r--r--src/libstd/unstable/global.rs281
-rw-r--r--src/libstd/unstable/intrinsics.rs211
-rw-r--r--src/libstd/unstable/lang.rs420
-rw-r--r--src/libstd/unstable/mod.rs77
-rw-r--r--src/libstd/unstable/simd.rs43
-rw-r--r--src/libstd/unstable/sync.rs261
-rw-r--r--src/libstd/unstable/weak_task.rs211
-rw-r--r--src/libstd/util.rs190
-rw-r--r--src/libstd/uv.rs38
-rw-r--r--src/libstd/uv_global_loop.rs232
-rw-r--r--src/libstd/uv_iotask.rs305
-rw-r--r--src/libstd/uv_ll.rs1910
-rw-r--r--src/libstd/vec.rs4615
-rw-r--r--src/libstd/workcache.rs422
168 files changed, 52668 insertions, 32134 deletions
diff --git a/src/libstd/arc.rs b/src/libstd/arc.rs
deleted file mode 100644
index 9c7db35f6f2..00000000000
--- a/src/libstd/arc.rs
+++ /dev/null
@@ -1,803 +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.
-
-/*!
- * Concurrency-enabled mechanisms for sharing mutable and/or immutable state
- * between tasks.
- *
- * # Example
- *
- * In this example, a large vector of floats is shared between several tasks.
- * With simple pipes, without ARC, a copy would have to be made for each task.
- *
- * ~~~
- * extern mod std;
- * use std::arc;
- * let numbers=vec::from_fn(100, |ind| (ind as float)*rand::random());
- * let shared_numbers=arc::ARC(numbers);
- *
- *   for 10.times {
- *       let (port, chan)  = stream();
- *       chan.send(shared_numbers.clone());
- *
- *       do spawn {
- *           let shared_numbers=port.recv();
- *           let local_numbers=shared_numbers.get();
- *
- *           // Work with the local numbers
- *       }
- *   }
- * ~~~
- */
-
-use sync;
-use sync::{Mutex, mutex_with_condvars, RWlock, rwlock_with_condvars};
-
-use core::cast;
-use core::unstable::sync::UnsafeAtomicRcBox;
-use core::ptr;
-use core::task;
-
-/// As sync::condvar, a mechanism for unlock-and-descheduling and signaling.
-pub struct Condvar<'self> {
-    is_mutex: bool,
-    failed: &'self mut bool,
-    cond: &'self sync::Condvar<'self>
-}
-
-pub impl<'self> Condvar<'self> {
-    /// Atomically exit the associated ARC and block until a signal is sent.
-    #[inline(always)]
-    fn wait(&self) { self.wait_on(0) }
-
-    /**
-     * Atomically exit the associated ARC and block on a specified condvar
-     * until a signal is sent on that same condvar (as sync::cond.wait_on).
-     *
-     * wait() is equivalent to wait_on(0).
-     */
-    #[inline(always)]
-    fn wait_on(&self, condvar_id: uint) {
-        assert!(!*self.failed);
-        self.cond.wait_on(condvar_id);
-        // This is why we need to wrap sync::condvar.
-        check_poison(self.is_mutex, *self.failed);
-    }
-
-    /// Wake up a blocked task. Returns false if there was no blocked task.
-    #[inline(always)]
-    fn signal(&self) -> bool { self.signal_on(0) }
-
-    /**
-     * Wake up a blocked task on a specified condvar (as
-     * sync::cond.signal_on). Returns false if there was no blocked task.
-     */
-    #[inline(always)]
-    fn signal_on(&self, condvar_id: uint) -> bool {
-        assert!(!*self.failed);
-        self.cond.signal_on(condvar_id)
-    }
-
-    /// Wake up all blocked tasks. Returns the number of tasks woken.
-    #[inline(always)]
-    fn broadcast(&self) -> uint { self.broadcast_on(0) }
-
-    /**
-     * Wake up all blocked tasks on a specified condvar (as
-     * sync::cond.broadcast_on). Returns Returns the number of tasks woken.
-     */
-    #[inline(always)]
-    fn broadcast_on(&self, condvar_id: uint) -> uint {
-        assert!(!*self.failed);
-        self.cond.broadcast_on(condvar_id)
-    }
-}
-
-/****************************************************************************
- * Immutable ARC
- ****************************************************************************/
-
-/// An atomically reference counted wrapper for shared immutable state.
-struct ARC<T> { x: UnsafeAtomicRcBox<T> }
-
-/// Create an atomically reference counted wrapper.
-pub fn ARC<T:Const + Owned>(data: T) -> ARC<T> {
-    ARC { x: UnsafeAtomicRcBox::new(data) }
-}
-
-/**
- * Access the underlying data in an atomically reference counted
- * wrapper.
- */
-pub fn get<'a, T:Const + Owned>(rc: &'a ARC<T>) -> &'a T {
-    rc.get()
-}
-
-impl<T:Const+Owned> ARC<T> {
-    pub fn get<'a>(&'a self) -> &'a T {
-        unsafe { &*self.x.get_immut() }
-    }
-}
-/**
- * Duplicate an atomically reference counted wrapper.
- *
- * The resulting two `arc` objects will point to the same underlying data
- * object. However, one of the `arc` objects can be sent to another task,
- * allowing them to share the underlying data.
- */
-pub fn clone<T:Const + Owned>(rc: &ARC<T>) -> ARC<T> {
-    ARC { x: rc.x.clone() }
-}
-
-impl<T:Const + Owned> Clone for ARC<T> {
-    fn clone(&self) -> ARC<T> {
-        clone(self)
-    }
-}
-
-/****************************************************************************
- * Mutex protected ARC (unsafe)
- ****************************************************************************/
-
-#[doc(hidden)]
-struct MutexARCInner<T> { lock: Mutex, failed: bool, data: T }
-/// An ARC with mutable data protected by a blocking mutex.
-struct MutexARC<T> { x: UnsafeAtomicRcBox<MutexARCInner<T>> }
-
-/// Create a mutex-protected ARC with the supplied data.
-pub fn MutexARC<T:Owned>(user_data: T) -> MutexARC<T> {
-    mutex_arc_with_condvars(user_data, 1)
-}
-/**
- * Create a mutex-protected ARC with the supplied data and a specified number
- * of condvars (as sync::mutex_with_condvars).
- */
-pub fn mutex_arc_with_condvars<T:Owned>(user_data: T,
-                                    num_condvars: uint) -> MutexARC<T> {
-    let data =
-        MutexARCInner { lock: mutex_with_condvars(num_condvars),
-                          failed: false, data: user_data };
-    MutexARC { x: UnsafeAtomicRcBox::new(data) }
-}
-
-impl<T:Owned> Clone for MutexARC<T> {
-    /// Duplicate a mutex-protected ARC, as arc::clone.
-    fn clone(&self) -> MutexARC<T> {
-        // NB: Cloning the underlying mutex is not necessary. Its reference
-        // count would be exactly the same as the shared state's.
-        MutexARC { x: self.x.clone() }
-    }
-}
-
-pub impl<T:Owned> MutexARC<T> {
-
-    /**
-     * Access the underlying mutable data with mutual exclusion from other
-     * tasks. The argument closure will be run with the mutex locked; all
-     * other tasks wishing to access the data will block until the closure
-     * finishes running.
-     *
-     * The reason this function is 'unsafe' is because it is possible to
-     * construct a circular reference among multiple ARCs by mutating the
-     * underlying data. This creates potential for deadlock, but worse, this
-     * will guarantee a memory leak of all involved ARCs. Using mutex ARCs
-     * inside of other ARCs is safe in absence of circular references.
-     *
-     * If you wish to nest mutex_arcs, one strategy for ensuring safety at
-     * runtime is to add a "nesting level counter" inside the stored data, and
-     * when traversing the arcs, assert that they monotonically decrease.
-     *
-     * # Failure
-     *
-     * Failing while inside the ARC will unlock the ARC while unwinding, so
-     * that other tasks won't block forever. It will also poison the ARC:
-     * any tasks that subsequently try to access it (including those already
-     * blocked on the mutex) will also fail immediately.
-     */
-    #[inline(always)]
-    unsafe fn access<U>(&self, blk: &fn(x: &mut T) -> U) -> U {
-        let state = self.x.get();
-        // Borrowck would complain about this if the function were
-        // not already unsafe. See borrow_rwlock, far below.
-        do (&(*state).lock).lock {
-            check_poison(true, (*state).failed);
-            let _z = PoisonOnFail(&mut (*state).failed);
-            blk(&mut (*state).data)
-        }
-    }
-
-    /// As access(), but with a condvar, as sync::mutex.lock_cond().
-    #[inline(always)]
-    unsafe fn access_cond<'x, 'c, U>(
-        &self,
-        blk: &fn(x: &'x mut T, c: &'c Condvar) -> U) -> U
-    {
-        let state = self.x.get();
-        do (&(*state).lock).lock_cond |cond| {
-            check_poison(true, (*state).failed);
-            let _z = PoisonOnFail(&mut (*state).failed);
-            blk(&mut (*state).data,
-                &Condvar {is_mutex: true,
-                          failed: &mut (*state).failed,
-                          cond: cond })
-        }
-    }
-}
-
-// Common code for {mutex.access,rwlock.write}{,_cond}.
-#[inline(always)]
-#[doc(hidden)]
-fn check_poison(is_mutex: bool, failed: bool) {
-    if failed {
-        if is_mutex {
-            fail!("Poisoned MutexARC - another task failed inside!");
-        } else {
-            fail!("Poisoned rw_arc - another task failed inside!");
-        }
-    }
-}
-
-#[doc(hidden)]
-struct PoisonOnFail {
-    failed: *mut bool,
-}
-
-impl Drop for PoisonOnFail {
-    fn finalize(&self) {
-        unsafe {
-            /* assert!(!*self.failed);
-               -- might be false in case of cond.wait() */
-            if task::failing() {
-                *self.failed = true;
-            }
-        }
-    }
-}
-
-fn PoisonOnFail<'r>(failed: &'r mut bool) -> PoisonOnFail {
-    PoisonOnFail {
-        failed: ptr::to_mut_unsafe_ptr(failed)
-    }
-}
-
-/****************************************************************************
- * R/W lock protected ARC
- ****************************************************************************/
-
-#[doc(hidden)]
-struct RWARCInner<T> { lock: RWlock, failed: bool, data: T }
-/**
- * A dual-mode ARC protected by a reader-writer lock. The data can be accessed
- * mutably or immutably, and immutably-accessing tasks may run concurrently.
- *
- * Unlike mutex_arcs, rw_arcs are safe, because they cannot be nested.
- */
-#[mutable]
-struct RWARC<T> {
-    x: UnsafeAtomicRcBox<RWARCInner<T>>,
-    cant_nest: ()
-}
-
-/// Create a reader/writer ARC with the supplied data.
-pub fn RWARC<T:Const + Owned>(user_data: T) -> RWARC<T> {
-    rw_arc_with_condvars(user_data, 1)
-}
-/**
- * Create a reader/writer ARC with the supplied data and a specified number
- * of condvars (as sync::rwlock_with_condvars).
- */
-pub fn rw_arc_with_condvars<T:Const + Owned>(
-    user_data: T,
-    num_condvars: uint) -> RWARC<T>
-{
-    let data =
-        RWARCInner { lock: rwlock_with_condvars(num_condvars),
-                     failed: false, data: user_data };
-    RWARC { x: UnsafeAtomicRcBox::new(data), cant_nest: () }
-}
-
-pub impl<T:Const + Owned> RWARC<T> {
-    /// Duplicate a rwlock-protected ARC, as arc::clone.
-    fn clone(&self) -> RWARC<T> {
-        RWARC { x: self.x.clone(),
-                cant_nest: () }
-    }
-
-}
-
-pub impl<T:Const + Owned> RWARC<T> {
-    /**
-     * Access the underlying data mutably. Locks the rwlock in write mode;
-     * other readers and writers will block.
-     *
-     * # Failure
-     *
-     * Failing while inside the ARC will unlock the ARC while unwinding, so
-     * that other tasks won't block forever. As MutexARC.access, it will also
-     * poison the ARC, so subsequent readers and writers will both also fail.
-     */
-    #[inline(always)]
-    fn write<U>(&self, blk: &fn(x: &mut T) -> U) -> U {
-        unsafe {
-            let state = self.x.get();
-            do (*borrow_rwlock(state)).write {
-                check_poison(false, (*state).failed);
-                let _z = PoisonOnFail(&mut (*state).failed);
-                blk(&mut (*state).data)
-            }
-        }
-    }
-    /// As write(), but with a condvar, as sync::rwlock.write_cond().
-    #[inline(always)]
-    fn write_cond<'x, 'c, U>(&self,
-                             blk: &fn(x: &'x mut T, c: &'c Condvar) -> U)
-                          -> U {
-        unsafe {
-            let state = self.x.get();
-            do (*borrow_rwlock(state)).write_cond |cond| {
-                check_poison(false, (*state).failed);
-                let _z = PoisonOnFail(&mut (*state).failed);
-                blk(&mut (*state).data,
-                    &Condvar {is_mutex: false,
-                              failed: &mut (*state).failed,
-                              cond: cond})
-            }
-        }
-    }
-    /**
-     * Access the underlying data immutably. May run concurrently with other
-     * reading tasks.
-     *
-     * # Failure
-     *
-     * Failing will unlock the ARC while unwinding. However, unlike all other
-     * access modes, this will not poison the ARC.
-     */
-    fn read<U>(&self, blk: &fn(x: &T) -> U) -> U {
-        let state = self.x.get();
-        unsafe {
-            do (*state).lock.read {
-                check_poison(false, (*state).failed);
-                blk(&(*state).data)
-            }
-        }
-    }
-
-    /**
-     * As write(), but with the ability to atomically 'downgrade' the lock.
-     * See sync::rwlock.write_downgrade(). The RWWriteMode token must be used
-     * to obtain the &mut T, and can be transformed into a RWReadMode token by
-     * calling downgrade(), after which a &T can be obtained instead.
-     * ~~~
-     * do arc.write_downgrade |write_mode| {
-     *     do (&write_mode).write_cond |state, condvar| {
-     *         ... exclusive access with mutable state ...
-     *     }
-     *     let read_mode = arc.downgrade(write_mode);
-     *     do (&read_mode).read |state| {
-     *         ... shared access with immutable state ...
-     *     }
-     * }
-     * ~~~
-     */
-    fn write_downgrade<U>(&self, blk: &fn(v: RWWriteMode<T>) -> U) -> U {
-        unsafe {
-            let state = self.x.get();
-            do (*borrow_rwlock(state)).write_downgrade |write_mode| {
-                check_poison(false, (*state).failed);
-                blk(RWWriteMode {
-                    data: &mut (*state).data,
-                    token: write_mode,
-                    poison: PoisonOnFail(&mut (*state).failed)
-                })
-            }
-        }
-    }
-
-    /// To be called inside of the write_downgrade block.
-    fn downgrade<'a>(&self, token: RWWriteMode<'a, T>) -> RWReadMode<'a, T> {
-        unsafe {
-            // The rwlock should assert that the token belongs to us for us.
-            let state = self.x.get();
-            let RWWriteMode {
-                data: data,
-                token: t,
-                poison: _poison
-            } = token;
-            // Let readers in
-            let new_token = (*state).lock.downgrade(t);
-            // Whatever region the input reference had, it will be safe to use
-            // the same region for the output reference. (The only 'unsafe' part
-            // of this cast is removing the mutability.)
-            let new_data = cast::transmute_immut(data);
-            // Downgrade ensured the token belonged to us. Just a sanity check.
-            assert!(ptr::ref_eq(&(*state).data, new_data));
-            // Produce new token
-            RWReadMode {
-                data: new_data,
-                token: new_token,
-            }
-        }
-    }
-}
-
-// Borrowck rightly complains about immutably aliasing the rwlock in order to
-// lock it. This wraps the unsafety, with the justification that the 'lock'
-// field is never overwritten; only 'failed' and 'data'.
-#[doc(hidden)]
-fn borrow_rwlock<T:Const + Owned>(state: *const RWARCInner<T>) -> *RWlock {
-    unsafe { cast::transmute(&const (*state).lock) }
-}
-
-/// The "write permission" token used for RWARC.write_downgrade().
-pub struct RWWriteMode<'self, T> {
-    data: &'self mut T,
-    token: sync::RWlockWriteMode<'self>,
-    poison: PoisonOnFail,
-}
-
-/// The "read permission" token used for RWARC.write_downgrade().
-pub struct RWReadMode<'self, T> {
-    data: &'self T,
-    token: sync::RWlockReadMode<'self>,
-}
-
-pub impl<'self, T:Const + Owned> RWWriteMode<'self, T> {
-    /// Access the pre-downgrade RWARC in write mode.
-    fn write<U>(&mut self, blk: &fn(x: &mut T) -> U) -> U {
-        match *self {
-            RWWriteMode {
-                data: &ref mut data,
-                token: ref token,
-                poison: _
-            } => {
-                do token.write {
-                    blk(data)
-                }
-            }
-        }
-    }
-    /// Access the pre-downgrade RWARC in write mode with a condvar.
-    fn write_cond<'x, 'c, U>(&mut self,
-                             blk: &fn(x: &'x mut T, c: &'c Condvar) -> U)
-                          -> U {
-        match *self {
-            RWWriteMode {
-                data: &ref mut data,
-                token: ref token,
-                poison: ref poison
-            } => {
-                do token.write_cond |cond| {
-                    unsafe {
-                        let cvar = Condvar {
-                            is_mutex: false,
-                            failed: &mut *poison.failed,
-                            cond: cond
-                        };
-                        blk(data, &cvar)
-                    }
-                }
-            }
-        }
-    }
-}
-
-pub impl<'self, T:Const + Owned> RWReadMode<'self, T> {
-    /// Access the post-downgrade rwlock in read mode.
-    fn read<U>(&self, blk: &fn(x: &T) -> U) -> U {
-        match *self {
-            RWReadMode {
-                data: data,
-                token: ref token
-            } => {
-                do token.read { blk(data) }
-            }
-        }
-    }
-}
-
-/****************************************************************************
- * Tests
- ****************************************************************************/
-
-#[cfg(test)]
-mod tests {
-
-    use arc::*;
-    use arc;
-
-    use core::cell::Cell;
-    use core::task;
-
-    #[test]
-    fn manually_share_arc() {
-        let v = ~[1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-        let arc_v = arc::ARC(v);
-
-        let (p, c) = comm::stream();
-
-        do task::spawn() || {
-            let p = comm::PortSet::new();
-            c.send(p.chan());
-
-            let arc_v = p.recv();
-
-            let v = copy *arc::get::<~[int]>(&arc_v);
-            assert_eq!(v[3], 4);
-        };
-
-        let c = p.recv();
-        c.send(arc::clone(&arc_v));
-
-        assert_eq!((*arc::get(&arc_v))[2], 3);
-        assert_eq!(arc_v.get()[4], 5);
-
-        info!(arc_v);
-    }
-
-    #[test]
-    fn test_mutex_arc_condvar() {
-        let arc = ~MutexARC(false);
-        let arc2 = ~arc.clone();
-        let (p,c) = comm::oneshot();
-        let (c,p) = (Cell(c), Cell(p));
-        do task::spawn || {
-            // wait until parent gets in
-            comm::recv_one(p.take());
-            do arc2.access_cond |state, cond| {
-                *state = true;
-                cond.signal();
-            }
-        }
-        do arc.access_cond |state, cond| {
-            comm::send_one(c.take(), ());
-            assert!(!*state);
-            while !*state {
-                cond.wait();
-            }
-        }
-    }
-    #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_arc_condvar_poison() {
-        let arc = ~MutexARC(1);
-        let arc2 = ~arc.clone();
-        let (p, c) = comm::stream();
-
-        do task::spawn_unlinked || {
-            let _ = p.recv();
-            do arc2.access_cond |one, cond| {
-                cond.signal();
-                // Parent should fail when it wakes up.
-                assert_eq!(*one, 0);
-            }
-        }
-
-        do arc.access_cond |one, cond| {
-            c.send(());
-            while *one == 1 {
-                cond.wait();
-            }
-        }
-    }
-    #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_mutex_arc_poison() {
-        let arc = ~MutexARC(1);
-        let arc2 = ~arc.clone();
-        do task::try || {
-            do arc2.access |one| {
-                assert_eq!(*one, 2);
-            }
-        };
-        do arc.access |one| {
-            assert_eq!(*one, 1);
-        }
-    }
-    #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_rw_arc_poison_wr() {
-        let arc = ~RWARC(1);
-        let arc2 = (*arc).clone();
-        do task::try || {
-            do arc2.write |one| {
-                assert_eq!(*one, 2);
-            }
-        };
-        do arc.read |one| {
-            assert_eq!(*one, 1);
-        }
-    }
-    #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_rw_arc_poison_ww() {
-        let arc = ~RWARC(1);
-        let arc2 = (*arc).clone();
-        do task::try || {
-            do arc2.write |one| {
-                assert_eq!(*one, 2);
-            }
-        };
-        do arc.write |one| {
-            assert_eq!(*one, 1);
-        }
-    }
-    #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_rw_arc_poison_dw() {
-        let arc = ~RWARC(1);
-        let arc2 = (*arc).clone();
-        do task::try || {
-            do arc2.write_downgrade |mut write_mode| {
-                do write_mode.write |one| {
-                    assert_eq!(*one, 2);
-                }
-            }
-        };
-        do arc.write |one| {
-            assert_eq!(*one, 1);
-        }
-    }
-    #[test] #[ignore(cfg(windows))]
-    fn test_rw_arc_no_poison_rr() {
-        let arc = ~RWARC(1);
-        let arc2 = (*arc).clone();
-        do task::try || {
-            do arc2.read |one| {
-                assert_eq!(*one, 2);
-            }
-        };
-        do arc.read |one| {
-            assert_eq!(*one, 1);
-        }
-    }
-    #[test] #[ignore(cfg(windows))]
-    fn test_rw_arc_no_poison_rw() {
-        let arc = ~RWARC(1);
-        let arc2 = (*arc).clone();
-        do task::try || {
-            do arc2.read |one| {
-                assert_eq!(*one, 2);
-            }
-        };
-        do arc.write |one| {
-            assert_eq!(*one, 1);
-        }
-    }
-    #[test] #[ignore(cfg(windows))]
-    fn test_rw_arc_no_poison_dr() {
-        let arc = ~RWARC(1);
-        let arc2 = (*arc).clone();
-        do task::try || {
-            do arc2.write_downgrade |write_mode| {
-                let read_mode = arc2.downgrade(write_mode);
-                do (&read_mode).read |one| {
-                    assert_eq!(*one, 2);
-                }
-            }
-        };
-        do arc.write |one| {
-            assert_eq!(*one, 1);
-        }
-    }
-    #[test]
-    fn test_rw_arc() {
-        let arc = ~RWARC(0);
-        let arc2 = (*arc).clone();
-        let (p,c) = comm::stream();
-
-        do task::spawn || {
-            do arc2.write |num| {
-                for 10.times {
-                    let tmp = *num;
-                    *num = -1;
-                    task::yield();
-                    *num = tmp + 1;
-                }
-                c.send(());
-            }
-        }
-
-        // Readers try to catch the writer in the act
-        let mut children = ~[];
-        for 5.times {
-            let arc3 = (*arc).clone();
-            let mut builder = task::task();
-            builder.future_result(|r| children.push(r));
-            do builder.spawn {
-                do arc3.read |num| {
-                    assert!(*num >= 0);
-                }
-            }
-        }
-
-        // Wait for children to pass their asserts
-        for children.each |r| {
-            r.recv();
-        }
-
-        // Wait for writer to finish
-        p.recv();
-        do arc.read |num| {
-            assert_eq!(*num, 10);
-        }
-    }
-    #[test]
-    fn test_rw_downgrade() {
-        // (1) A downgrader gets in write mode and does cond.wait.
-        // (2) A writer gets in write mode, sets state to 42, and does signal.
-        // (3) Downgrader wakes, sets state to 31337.
-        // (4) tells writer and all other readers to contend as it downgrades.
-        // (5) Writer attempts to set state back to 42, while downgraded task
-        //     and all reader tasks assert that it's 31337.
-        let arc = ~RWARC(0);
-
-        // Reader tasks
-        let mut reader_convos = ~[];
-        for 10.times {
-            let ((rp1,rc1),(rp2,rc2)) = (comm::stream(),comm::stream());
-            reader_convos.push((rc1, rp2));
-            let arcn = (*arc).clone();
-            do task::spawn || {
-                rp1.recv(); // wait for downgrader to give go-ahead
-                do arcn.read |state| {
-                    assert_eq!(*state, 31337);
-                    rc2.send(());
-                }
-            }
-        }
-
-        // Writer task
-        let arc2 = (*arc).clone();
-        let ((wp1,wc1),(wp2,wc2)) = (comm::stream(),comm::stream());
-        do task::spawn || {
-            wp1.recv();
-            do arc2.write_cond |state, cond| {
-                assert_eq!(*state, 0);
-                *state = 42;
-                cond.signal();
-            }
-            wp1.recv();
-            do arc2.write |state| {
-                // This shouldn't happen until after the downgrade read
-                // section, and all other readers, finish.
-                assert_eq!(*state, 31337);
-                *state = 42;
-            }
-            wc2.send(());
-        }
-
-        // Downgrader (us)
-        do arc.write_downgrade |mut write_mode| {
-            do write_mode.write_cond |state, cond| {
-                wc1.send(()); // send to another writer who will wake us up
-                while *state == 0 {
-                    cond.wait();
-                }
-                assert_eq!(*state, 42);
-                *state = 31337;
-                // send to other readers
-                for reader_convos.each |x| {
-                    match *x {
-                        (ref rc, _) => rc.send(()),
-                    }
-                }
-            }
-            let read_mode = arc.downgrade(write_mode);
-            do (&read_mode).read |state| {
-                // complete handshake with other readers
-                for reader_convos.each |x| {
-                    match *x {
-                        (_, ref rp) => rp.recv(),
-                    }
-                }
-                wc1.send(()); // tell writer to try again
-                assert_eq!(*state, 31337);
-            }
-        }
-
-        wp2.recv(); // complete handshake with writer
-    }
-}
diff --git a/src/libstd/arena.rs b/src/libstd/arena.rs
deleted file mode 100644
index a087a16caa2..00000000000
--- a/src/libstd/arena.rs
+++ /dev/null
@@ -1,314 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Dynamic arenas.
-
-// Arenas are used to quickly allocate objects that share a
-// lifetime. The arena uses ~[u8] vectors as a backing store to
-// allocate objects from. For each allocated object, the arena stores
-// a pointer to the type descriptor followed by the
-// object. (Potentially with alignment padding after each of them.)
-// When the arena is destroyed, it iterates through all of its chunks,
-// and uses the tydesc information to trace through the objects,
-// calling the destructors on them.
-// One subtle point that needs to be addressed is how to handle
-// failures while running the user provided initializer function. It
-// is important to not run the destructor on uninitialized objects, but
-// how to detect them is somewhat subtle. Since alloc() can be invoked
-// recursively, it is not sufficient to simply exclude the most recent
-// object. To solve this without requiring extra space, we use the low
-// order bit of the tydesc pointer to encode whether the object it
-// describes has been fully initialized.
-
-// As an optimization, objects with destructors are stored in
-// different chunks than objects without destructors. This reduces
-// overhead when initializing plain-old-data and means we don't need
-// to waste time running the destructors of POD.
-
-use list::{MutList, MutCons, MutNil};
-
-use core::at_vec;
-use core::cast::{transmute, transmute_mut_region};
-use core::cast;
-use core::libc::size_t;
-use core::ptr;
-use core::sys::TypeDesc;
-use core::sys;
-use core::uint;
-use core::vec;
-use core::unstable::intrinsics;
-
-pub mod rustrt {
-    use core::libc::size_t;
-    use core::sys::TypeDesc;
-
-    pub extern {
-        #[rust_stack]
-        unsafe fn rust_call_tydesc_glue(root: *u8,
-                                        tydesc: *TypeDesc,
-                                        field: size_t);
-    }
-}
-
-// This probably belongs somewhere else. Needs to be kept in sync with
-// changes to glue...
-static tydesc_drop_glue_index: size_t = 3 as size_t;
-
-// The way arena uses arrays is really deeply awful. The arrays are
-// allocated, and have capacities reserved, but the fill for the array
-// will always stay at 0.
-struct Chunk {
-    data: @[u8],
-    fill: uint,
-    is_pod: bool,
-}
-
-pub struct Arena {
-    // The head is separated out from the list as a unbenchmarked
-    // microoptimization, to avoid needing to case on the list to
-    // access the head.
-    priv head: Chunk,
-    priv pod_head: Chunk,
-    priv chunks: @mut MutList<Chunk>,
-}
-
-#[unsafe_destructor]
-impl Drop for Arena {
-    fn finalize(&self) {
-        unsafe {
-            destroy_chunk(&self.head);
-            for self.chunks.each |chunk| {
-                if !chunk.is_pod {
-                    destroy_chunk(chunk);
-                }
-            }
-        }
-    }
-}
-
-fn chunk(size: uint, is_pod: bool) -> Chunk {
-    let mut v: @[u8] = @[];
-    unsafe { at_vec::raw::reserve(&mut v, size); }
-    Chunk {
-        data: unsafe { cast::transmute(v) },
-        fill: 0u,
-        is_pod: is_pod,
-    }
-}
-
-pub fn arena_with_size(initial_size: uint) -> Arena {
-    Arena {
-        head: chunk(initial_size, false),
-        pod_head: chunk(initial_size, true),
-        chunks: @mut MutNil,
-    }
-}
-
-pub fn Arena() -> Arena {
-    arena_with_size(32u)
-}
-
-#[inline(always)]
-fn round_up_to(base: uint, align: uint) -> uint {
-    (base + (align - 1)) & !(align - 1)
-}
-
-// Walk down a chunk, running the destructors for any objects stored
-// in it.
-unsafe fn destroy_chunk(chunk: &Chunk) {
-    let mut idx = 0;
-    let buf = vec::raw::to_ptr(chunk.data);
-    let fill = chunk.fill;
-
-    while idx < fill {
-        let tydesc_data: *uint = transmute(ptr::offset(buf, idx));
-        let (tydesc, is_done) = un_bitpack_tydesc_ptr(*tydesc_data);
-        let size = (*tydesc).size, align = (*tydesc).align;
-
-        let after_tydesc = idx + sys::size_of::<*TypeDesc>();
-
-        let start = round_up_to(after_tydesc, align);
-
-        //debug!("freeing object: idx = %u, size = %u, align = %u, done = %b",
-        //       start, size, align, is_done);
-        if is_done {
-            rustrt::rust_call_tydesc_glue(
-                ptr::offset(buf, start), tydesc, tydesc_drop_glue_index);
-        }
-
-        // Find where the next tydesc lives
-        idx = round_up_to(start + size, sys::pref_align_of::<*TypeDesc>());
-    }
-}
-
-// We encode whether the object a tydesc describes has been
-// initialized in the arena in the low bit of the tydesc pointer. This
-// is necessary in order to properly do cleanup if a failure occurs
-// during an initializer.
-#[inline(always)]
-unsafe fn bitpack_tydesc_ptr(p: *TypeDesc, is_done: bool) -> uint {
-    let p_bits: uint = transmute(p);
-    p_bits | (is_done as uint)
-}
-#[inline(always)]
-unsafe fn un_bitpack_tydesc_ptr(p: uint) -> (*TypeDesc, bool) {
-    (transmute(p & !1), p & 1 == 1)
-}
-
-pub impl Arena {
-    // Functions for the POD part of the arena
-    priv fn alloc_pod_grow(&mut self, n_bytes: uint, align: uint) -> *u8 {
-        // Allocate a new chunk.
-        let chunk_size = at_vec::capacity(self.pod_head.data);
-        let new_min_chunk_size = uint::max(n_bytes, chunk_size);
-        self.chunks = @mut MutCons(copy self.pod_head, self.chunks);
-        self.pod_head =
-            chunk(uint::next_power_of_two(new_min_chunk_size + 1u), true);
-
-        return self.alloc_pod_inner(n_bytes, align);
-    }
-
-    #[inline(always)]
-    priv fn alloc_pod_inner(&mut self, n_bytes: uint, align: uint) -> *u8 {
-        unsafe {
-            // XXX: Borrow check
-            let head = transmute_mut_region(&mut self.pod_head);
-
-            let start = round_up_to(head.fill, align);
-            let end = start + n_bytes;
-            if end > at_vec::capacity(head.data) {
-                return self.alloc_pod_grow(n_bytes, align);
-            }
-            head.fill = end;
-
-            //debug!("idx = %u, size = %u, align = %u, fill = %u",
-            //       start, n_bytes, align, head.fill);
-
-            ptr::offset(vec::raw::to_ptr(head.data), start)
-        }
-    }
-
-    #[inline(always)]
-    priv fn alloc_pod<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T {
-        unsafe {
-            let tydesc = sys::get_type_desc::<T>();
-            let ptr = self.alloc_pod_inner((*tydesc).size, (*tydesc).align);
-            let ptr: *mut T = transmute(ptr);
-            intrinsics::move_val_init(&mut (*ptr), op());
-            return transmute(ptr);
-        }
-    }
-
-    // Functions for the non-POD part of the arena
-    priv fn alloc_nonpod_grow(&mut self, n_bytes: uint, align: uint)
-                             -> (*u8, *u8) {
-        // Allocate a new chunk.
-        let chunk_size = at_vec::capacity(self.head.data);
-        let new_min_chunk_size = uint::max(n_bytes, chunk_size);
-        self.chunks = @mut MutCons(copy self.head, self.chunks);
-        self.head =
-            chunk(uint::next_power_of_two(new_min_chunk_size + 1u), false);
-
-        return self.alloc_nonpod_inner(n_bytes, align);
-    }
-
-    #[inline(always)]
-    priv fn alloc_nonpod_inner(&mut self, n_bytes: uint, align: uint)
-                               -> (*u8, *u8) {
-        unsafe {
-            let head = transmute_mut_region(&mut self.head);
-
-            let tydesc_start = head.fill;
-            let after_tydesc = head.fill + sys::size_of::<*TypeDesc>();
-            let start = round_up_to(after_tydesc, align);
-            let end = start + n_bytes;
-            if end > at_vec::capacity(head.data) {
-                return self.alloc_nonpod_grow(n_bytes, align);
-            }
-            head.fill = round_up_to(end, sys::pref_align_of::<*TypeDesc>());
-
-            //debug!("idx = %u, size = %u, align = %u, fill = %u",
-            //       start, n_bytes, align, head.fill);
-
-            let buf = vec::raw::to_ptr(head.data);
-            return (ptr::offset(buf, tydesc_start), ptr::offset(buf, start));
-        }
-    }
-
-    #[inline(always)]
-    priv fn alloc_nonpod<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T {
-        unsafe {
-            let tydesc = sys::get_type_desc::<T>();
-            let (ty_ptr, ptr) =
-                self.alloc_nonpod_inner((*tydesc).size, (*tydesc).align);
-            let ty_ptr: *mut uint = transmute(ty_ptr);
-            let ptr: *mut T = transmute(ptr);
-            // Write in our tydesc along with a bit indicating that it
-            // has *not* been initialized yet.
-            *ty_ptr = transmute(tydesc);
-            // Actually initialize it
-            intrinsics::move_val_init(&mut(*ptr), op());
-            // Now that we are done, update the tydesc to indicate that
-            // the object is there.
-            *ty_ptr = bitpack_tydesc_ptr(tydesc, true);
-
-            return transmute(ptr);
-        }
-    }
-
-    // The external interface
-    #[inline(always)]
-    fn alloc<'a, T>(&'a mut self, op: &fn() -> T) -> &'a T {
-        unsafe {
-            // XXX: Borrow check
-            let this = transmute_mut_region(self);
-            if !intrinsics::needs_drop::<T>() {
-                return this.alloc_pod(op);
-            }
-            // XXX: Borrow check
-            let this = transmute_mut_region(self);
-            this.alloc_nonpod(op)
-        }
-    }
-}
-
-#[test]
-fn test_arena_destructors() {
-    let mut arena = Arena();
-    for uint::range(0, 10) |i| {
-        // Arena allocate something with drop glue to make sure it
-        // doesn't leak.
-        do arena.alloc { @i };
-        // Allocate something with funny size and alignment, to keep
-        // things interesting.
-        do arena.alloc { [0u8, 1u8, 2u8] };
-    }
-}
-
-#[test]
-#[should_fail]
-#[ignore(cfg(windows))]
-fn test_arena_destructors_fail() {
-    let mut arena = Arena();
-    // Put some stuff in the arena.
-    for uint::range(0, 10) |i| {
-        // Arena allocate something with drop glue to make sure it
-        // doesn't leak.
-        do arena.alloc { @i };
-        // Allocate something with funny size and alignment, to keep
-        // things interesting.
-        do arena.alloc { [0u8, 1u8, 2u8] };
-    }
-    // Now, fail while allocating
-    do arena.alloc::<@int> {
-        // Now fail.
-        fail!();
-    };
-}
diff --git a/src/libstd/at_vec.rs b/src/libstd/at_vec.rs
new file mode 100644
index 00000000000..44c55563ac5
--- /dev/null
+++ b/src/libstd/at_vec.rs
@@ -0,0 +1,323 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Managed vectors
+
+use cast::transmute;
+use container::Container;
+use kinds::Copy;
+use old_iter;
+use old_iter::BaseIter;
+use option::Option;
+use sys;
+use uint;
+use vec;
+
+/// Code for dealing with @-vectors. This is pretty incomplete, and
+/// contains a bunch of duplication from the code for ~-vectors.
+
+pub mod rustrt {
+    use libc;
+    use sys;
+    use vec;
+
+    #[abi = "cdecl"]
+    #[link_name = "rustrt"]
+    pub extern {
+        pub unsafe fn vec_reserve_shared_actual(t: *sys::TypeDesc,
+                                                v: **vec::raw::VecRepr,
+                                                n: libc::size_t);
+    }
+}
+
+/// Returns the number of elements the vector can hold without reallocating
+#[inline(always)]
+pub fn capacity<T>(v: @[T]) -> uint {
+    unsafe {
+        let repr: **raw::VecRepr = transmute(&v);
+        (**repr).unboxed.alloc / sys::size_of::<T>()
+    }
+}
+
+/**
+ * Builds a vector by calling a provided function with an argument
+ * function that pushes an element to the back of a vector.
+ * This version takes an initial size for the vector.
+ *
+ * # Arguments
+ *
+ * * size - An initial size of the vector to reserve
+ * * builder - A function that will construct the vector. It receives
+ *             as an argument a function that will push an element
+ *             onto the vector being constructed.
+ */
+#[inline(always)]
+pub fn build_sized<A>(size: uint, builder: &fn(push: &fn(v: A))) -> @[A] {
+    let mut vec: @[A] = @[];
+    unsafe { raw::reserve(&mut vec, size); }
+    builder(|x| unsafe { raw::push(&mut vec, x) });
+    return unsafe { transmute(vec) };
+}
+
+/**
+ * Builds a vector by calling a provided function with an argument
+ * function that pushes an element to the back of a vector.
+ *
+ * # Arguments
+ *
+ * * builder - A function that will construct the vector. It receives
+ *             as an argument a function that will push an element
+ *             onto the vector being constructed.
+ */
+#[inline(always)]
+pub fn build<A>(builder: &fn(push: &fn(v: A))) -> @[A] {
+    build_sized(4, builder)
+}
+
+/**
+ * Builds a vector by calling a provided function with an argument
+ * function that pushes an element to the back of a vector.
+ * This version takes an initial size for the vector.
+ *
+ * # Arguments
+ *
+ * * size - An option, maybe containing initial size of the vector to reserve
+ * * builder - A function that will construct the vector. It receives
+ *             as an argument a function that will push an element
+ *             onto the vector being constructed.
+ */
+#[inline(always)]
+pub fn build_sized_opt<A>(size: Option<uint>,
+                          builder: &fn(push: &fn(v: A)))
+                       -> @[A] {
+    build_sized(size.get_or_default(4), builder)
+}
+
+// Appending
+#[inline(always)]
+pub fn append<T:Copy>(lhs: @[T], rhs: &const [T]) -> @[T] {
+    do build_sized(lhs.len() + rhs.len()) |push| {
+        for lhs.each |x| { push(*x); }
+        for uint::range(0, rhs.len()) |i| { push(rhs[i]); }
+    }
+}
+
+
+/// Apply a function to each element of a vector and return the results
+pub fn map<T, U>(v: &[T], f: &fn(x: &T) -> U) -> @[U] {
+    do build_sized(v.len()) |push| {
+        for v.each |elem| {
+            push(f(elem));
+        }
+    }
+}
+
+/**
+ * Creates and initializes an immutable vector.
+ *
+ * Creates an immutable vector of size `n_elts` and initializes the elements
+ * to the value returned by the function `op`.
+ */
+pub fn from_fn<T>(n_elts: uint, op: old_iter::InitOp<T>) -> @[T] {
+    do build_sized(n_elts) |push| {
+        let mut i: uint = 0u;
+        while i < n_elts { push(op(i)); i += 1u; }
+    }
+}
+
+/**
+ * Creates and initializes an immutable vector.
+ *
+ * Creates an immutable vector of size `n_elts` and initializes the elements
+ * to the value `t`.
+ */
+pub fn from_elem<T:Copy>(n_elts: uint, t: T) -> @[T] {
+    do build_sized(n_elts) |push| {
+        let mut i: uint = 0u;
+        while i < n_elts { push(copy t); i += 1u; }
+    }
+}
+
+/**
+ * Creates and initializes an immutable managed vector by moving all the
+ * elements from an owned vector.
+ */
+pub fn to_managed_consume<T>(v: ~[T]) -> @[T] {
+    let mut av = @[];
+    unsafe {
+        raw::reserve(&mut av, v.len());
+        do vec::consume(v) |_i, x| {
+            raw::push(&mut av, x);
+        }
+        transmute(av)
+    }
+}
+
+/**
+ * Creates and initializes an immutable managed vector by copying all the
+ * elements of a slice.
+ */
+pub fn to_managed<T:Copy>(v: &[T]) -> @[T] {
+    from_fn(v.len(), |i| v[i])
+}
+
+#[cfg(not(test))]
+pub mod traits {
+    use at_vec::append;
+    use kinds::Copy;
+    use ops::Add;
+
+    impl<'self,T:Copy> Add<&'self const [T],@[T]> for @[T] {
+        #[inline(always)]
+        fn add(&self, rhs: & &'self const [T]) -> @[T] {
+            append(*self, (*rhs))
+        }
+    }
+}
+
+#[cfg(test)]
+pub mod traits {}
+
+pub mod raw {
+    use at_vec::{capacity, rustrt};
+    use cast::{transmute, transmute_copy};
+    use libc;
+    use ptr;
+    use sys;
+    use uint;
+    use unstable::intrinsics::{move_val_init};
+    use vec;
+
+    pub type VecRepr = vec::raw::VecRepr;
+    pub type SliceRepr = vec::raw::SliceRepr;
+
+    /**
+     * Sets the length of a vector
+     *
+     * This will explicitly set the size of the vector, without actually
+     * modifing its buffers, so it is up to the caller to ensure that
+     * the vector is actually the specified size.
+     */
+    #[inline(always)]
+    pub unsafe fn set_len<T>(v: @[T], new_len: uint) {
+        let repr: **mut VecRepr = transmute(&v);
+        (**repr).unboxed.fill = new_len * sys::size_of::<T>();
+    }
+
+    #[inline(always)]
+    pub unsafe fn push<T>(v: &mut @[T], initval: T) {
+        let repr: **VecRepr = transmute_copy(&v);
+        let fill = (**repr).unboxed.fill;
+        if (**repr).unboxed.alloc > fill {
+            push_fast(v, initval);
+        } else {
+            push_slow(v, initval);
+        }
+    }
+
+    #[inline(always)] // really pretty please
+    pub unsafe fn push_fast<T>(v: &mut @[T], initval: T) {
+        let repr: **mut VecRepr = ::cast::transmute(v);
+        let fill = (**repr).unboxed.fill;
+        (**repr).unboxed.fill += sys::size_of::<T>();
+        let p = &((**repr).unboxed.data);
+        let p = ptr::offset(p, fill) as *mut T;
+        move_val_init(&mut(*p), initval);
+    }
+
+    pub unsafe fn push_slow<T>(v: &mut @[T], initval: T) {
+        reserve_at_least(&mut *v, v.len() + 1u);
+        push_fast(v, initval);
+    }
+
+    /**
+     * Reserves capacity for exactly `n` elements in the given vector.
+     *
+     * If the capacity for `v` is already equal to or greater than the
+     * requested capacity, then no action is taken.
+     *
+     * # Arguments
+     *
+     * * v - A vector
+     * * n - The number of elements to reserve space for
+     */
+    pub unsafe fn reserve<T>(v: &mut @[T], n: uint) {
+        // Only make the (slow) call into the runtime if we have to
+        if capacity(*v) < n {
+            let ptr: **VecRepr = transmute(v);
+            rustrt::vec_reserve_shared_actual(sys::get_type_desc::<T>(),
+                                              ptr, n as libc::size_t);
+        }
+    }
+
+    /**
+     * Reserves capacity for at least `n` elements in the given vector.
+     *
+     * This function will over-allocate in order to amortize the
+     * allocation costs in scenarios where the caller may need to
+     * repeatedly reserve additional space.
+     *
+     * If the capacity for `v` is already equal to or greater than the
+     * requested capacity, then no action is taken.
+     *
+     * # Arguments
+     *
+     * * v - A vector
+     * * n - The number of elements to reserve space for
+     */
+    pub unsafe fn reserve_at_least<T>(v: &mut @[T], n: uint) {
+        reserve(v, uint::next_power_of_two(n));
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use prelude::*;
+
+    #[test]
+    fn test() {
+        // Some code that could use that, then:
+        fn seq_range(lo: uint, hi: uint) -> @[uint] {
+            do build |push| {
+                for uint::range(lo, hi) |i| {
+                    push(i);
+                }
+            }
+        }
+
+        assert_eq!(seq_range(10, 15), @[10, 11, 12, 13, 14]);
+        assert_eq!(from_fn(5, |x| x+1), @[1, 2, 3, 4, 5]);
+        assert_eq!(from_elem(5, 3.14), @[3.14, 3.14, 3.14, 3.14, 3.14]);
+    }
+
+    #[test]
+    fn append_test() {
+        assert_eq!(@[1,2,3] + @[4,5,6], @[1,2,3,4,5,6]);
+    }
+
+    #[test]
+    fn test_to_managed_consume() {
+        assert_eq!(to_managed_consume::<int>(~[]), @[]);
+        assert_eq!(to_managed_consume(~[true]), @[true]);
+        assert_eq!(to_managed_consume(~[1, 2, 3, 4, 5]), @[1, 2, 3, 4, 5]);
+        assert_eq!(to_managed_consume(~[~"abc", ~"123"]), @[~"abc", ~"123"]);
+        assert_eq!(to_managed_consume(~[~[42]]), @[~[42]]);
+    }
+
+    #[test]
+    fn test_to_managed() {
+        assert_eq!(to_managed::<int>([]), @[]);
+        assert_eq!(to_managed([true]), @[true]);
+        assert_eq!(to_managed([1, 2, 3, 4, 5]), @[1, 2, 3, 4, 5]);
+        assert_eq!(to_managed([@"abc", @"123"]), @[@"abc", @"123"]);
+        assert_eq!(to_managed([@[42]]), @[@[42]]);
+    }
+}
diff --git a/src/libstd/base64.rs b/src/libstd/base64.rs
deleted file mode 100644
index a820862ef4c..00000000000
--- a/src/libstd/base64.rs
+++ /dev/null
@@ -1,247 +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.
-
-//! Base64 binary-to-text encoding
-
-pub trait ToBase64 {
-    fn to_base64(&self) -> ~str;
-}
-
-static CHARS: [char, ..64] = [
-    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
-    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
-    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
-    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
-    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
-];
-
-impl<'self> ToBase64 for &'self [u8] {
-    /**
-     * Turn a vector of `u8` bytes into a base64 string.
-     *
-     * *Example*:
-     *
-     * ~~~~
-     * extern mod std;
-     * use std::base64::ToBase64;
-     *
-     * fn main () {
-     *     let str = [52,32].to_base64();
-     *     println(fmt!("%s", str));
-     * }
-     * ~~~~
-     */
-    fn to_base64(&self) -> ~str {
-        let mut s = ~"";
-        let len = self.len();
-        str::reserve(&mut s, ((len + 3u) / 4u) * 3u);
-
-        let mut i = 0u;
-
-        while i < len - (len % 3u) {
-            let n = (self[i] as uint) << 16u |
-                    (self[i + 1u] as uint) << 8u |
-                    (self[i + 2u] as uint);
-
-            // This 24-bit number gets separated into four 6-bit numbers.
-            str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
-            str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
-            str::push_char(&mut s, CHARS[(n >> 6u) & 63u]);
-            str::push_char(&mut s, CHARS[n & 63u]);
-
-            i += 3u;
-        }
-
-        // Heh, would be cool if we knew this was exhaustive
-        // (the dream of bounded integer types)
-        match len % 3 {
-          0 => (),
-          1 => {
-            let n = (self[i] as uint) << 16u;
-            str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
-            str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
-            str::push_char(&mut s, '=');
-            str::push_char(&mut s, '=');
-          }
-          2 => {
-            let n = (self[i] as uint) << 16u |
-                (self[i + 1u] as uint) << 8u;
-            str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
-            str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
-            str::push_char(&mut s, CHARS[(n >> 6u) & 63u]);
-            str::push_char(&mut s, '=');
-          }
-          _ => fail!("Algebra is broken, please alert the math police")
-        }
-        s
-    }
-}
-
-impl<'self> ToBase64 for &'self str {
-    /**
-     * Convert any string (literal, `@`, `&`, or `~`) to base64 encoding.
-     *
-     *
-     * *Example*:
-     *
-     * ~~~~
-     * extern mod std;
-     * use std::base64::ToBase64;
-     *
-     * fn main () {
-     *     let str = "Hello, World".to_base64();
-     *     println(fmt!("%s",str));
-     * }
-     * ~~~~
-     *
-     */
-    fn to_base64(&self) -> ~str {
-        str::to_bytes(*self).to_base64()
-    }
-}
-
-pub trait FromBase64 {
-    fn from_base64(&self) -> ~[u8];
-}
-
-impl FromBase64 for ~[u8] {
-    /**
-     * Convert base64 `u8` vector into u8 byte values.
-     * Every 4 encoded characters is converted into 3 octets, modulo padding.
-     *
-     * *Example*:
-     *
-     * ~~~~
-     * extern mod std;
-     * use std::base64::ToBase64;
-     * use std::base64::FromBase64;
-     *
-     * fn main () {
-     *     let str = [52,32].to_base64();
-     *     println(fmt!("%s", str));
-     *     let bytes = str.from_base64();
-     *     println(fmt!("%?",bytes));
-     * }
-     * ~~~~
-     */
-    fn from_base64(&self) -> ~[u8] {
-        if self.len() % 4u != 0u { fail!("invalid base64 length"); }
-
-        let len = self.len();
-        let mut padding = 0u;
-
-        if len != 0u {
-            if self[len - 1u] == '=' as u8 { padding += 1u; }
-            if self[len - 2u] == '=' as u8 { padding += 1u; }
-        }
-
-        let mut r = vec::with_capacity((len / 4u) * 3u - padding);
-
-        let mut i = 0u;
-        while i < len {
-            let mut n = 0u;
-
-            for 4u.times {
-                let ch = self[i] as char;
-                n <<= 6u;
-
-                match ch {
-                    'A'..'Z' => n |= (ch as uint) - 0x41,
-                    'a'..'z' => n |= (ch as uint) - 0x47,
-                    '0'..'9' => n |= (ch as uint) + 0x04,
-                    '+'      => n |= 0x3E,
-                    '/'      => n |= 0x3F,
-                    '='      => {
-                        match len - i {
-                            1u => {
-                                r.push(((n >> 16u) & 0xFFu) as u8);
-                                r.push(((n >> 8u ) & 0xFFu) as u8);
-                                return copy r;
-                            }
-                            2u => {
-                                r.push(((n >> 10u) & 0xFFu) as u8);
-                                return copy r;
-                            }
-                            _ => fail!("invalid base64 padding")
-                        }
-                    }
-                    _ => fail!("invalid base64 character")
-                }
-
-                i += 1u;
-            };
-
-            r.push(((n >> 16u) & 0xFFu) as u8);
-            r.push(((n >> 8u ) & 0xFFu) as u8);
-            r.push(((n       ) & 0xFFu) as u8);
-        }
-        r
-    }
-}
-
-impl FromBase64 for ~str {
-    /**
-     * Convert any base64 encoded string (literal, `@`, `&`, or `~`)
-     * to the byte values it encodes.
-     *
-     * You can use the `from_bytes` function in `core::str`
-     * to turn a `[u8]` into a string with characters corresponding to those values.
-     *
-     * *Example*:
-     *
-     * This converts a string literal to base64 and back.
-     *
-     * ~~~~
-     * extern mod std;
-     * use std::base64::ToBase64;
-     * use std::base64::FromBase64;
-     * use core::str;
-     *
-     * fn main () {
-     *     let hello_str = "Hello, World".to_base64();
-     *     println(fmt!("%s",hello_str));
-     *     let bytes = hello_str.from_base64();
-     *     println(fmt!("%?",bytes));
-     *     let result_str = str::from_bytes(bytes);
-     *     println(fmt!("%s",result_str));
-     * }
-     * ~~~~
-     */
-    fn from_base64(&self) -> ~[u8] {
-        str::to_bytes(*self).from_base64()
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use core::str;
-
-    #[test]
-    fn test_to_base64() {
-        assert_eq!((~"").to_base64(), ~"");
-        assert!((~"f").to_base64()      == ~"Zg==");
-        assert_eq!((~"fo").to_base64(), ~"Zm8=");
-        assert_eq!((~"foo").to_base64(), ~"Zm9v");
-        assert!((~"foob").to_base64()   == ~"Zm9vYg==");
-        assert_eq!((~"fooba").to_base64(), ~"Zm9vYmE=");
-        assert_eq!((~"foobar").to_base64(), ~"Zm9vYmFy");
-    }
-
-    #[test]
-    fn test_from_base64() {
-        assert_eq!((~"").from_base64(), str::to_bytes(~""));
-        assert!((~"Zg==").from_base64() == str::to_bytes(~"f"));
-        assert_eq!((~"Zm8=").from_base64(), str::to_bytes(~"fo"));
-        assert_eq!((~"Zm9v").from_base64(), str::to_bytes(~"foo"));
-        assert!((~"Zm9vYg==").from_base64() == str::to_bytes(~"foob"));
-        assert_eq!((~"Zm9vYmE=").from_base64(), str::to_bytes(~"fooba"))
-        assert_eq!((~"Zm9vYmFy").from_base64(), str::to_bytes(~"foobar"));
-    }
-}
diff --git a/src/libstd/bitv.rs b/src/libstd/bitv.rs
deleted file mode 100644
index 9d22107931e..00000000000
--- a/src/libstd/bitv.rs
+++ /dev/null
@@ -1,1494 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use core::vec::from_elem;
-
-struct SmallBitv {
-    /// only the lowest nbits of this value are used. the rest is undefined.
-    bits: uint
-}
-
-/// a mask that has a 1 for each defined bit in a small_bitv, assuming n bits
-#[inline(always)]
-fn small_mask(nbits: uint) -> uint {
-    (1 << nbits) - 1
-}
-
-pub impl SmallBitv {
-    fn new(bits: uint) -> SmallBitv {
-        SmallBitv {bits: bits}
-    }
-
-    #[inline(always)]
-    fn bits_op(&mut self, right_bits: uint, nbits: uint,
-               f: &fn(uint, uint) -> uint) -> bool {
-        let mask = small_mask(nbits);
-        let old_b: uint = self.bits;
-        let new_b = f(old_b, right_bits);
-        self.bits = new_b;
-        mask & old_b != mask & new_b
-    }
-
-    #[inline(always)]
-    fn union(&mut self, s: &SmallBitv, nbits: uint) -> bool {
-        self.bits_op(s.bits, nbits, |u1, u2| u1 | u2)
-    }
-
-    #[inline(always)]
-    fn intersect(&mut self, s: &SmallBitv, nbits: uint) -> bool {
-        self.bits_op(s.bits, nbits, |u1, u2| u1 & u2)
-    }
-
-    #[inline(always)]
-    fn become(&mut self, s: &SmallBitv, nbits: uint) -> bool {
-        self.bits_op(s.bits, nbits, |_u1, u2| u2)
-    }
-
-    #[inline(always)]
-    fn difference(&mut self, s: &SmallBitv, nbits: uint) -> bool {
-        self.bits_op(s.bits, nbits, |u1, u2| u1 & !u2)
-    }
-
-    #[inline(always)]
-    fn get(&self, i: uint) -> bool {
-        (self.bits & (1 << i)) != 0
-    }
-
-    #[inline(always)]
-    fn set(&mut self, i: uint, x: bool) {
-        if x {
-            self.bits |= 1<<i;
-        }
-        else {
-            self.bits &= !(1<<i as uint);
-        }
-    }
-
-    #[inline(always)]
-    fn equals(&self, b: &SmallBitv, nbits: uint) -> bool {
-        let mask = small_mask(nbits);
-        mask & self.bits == mask & b.bits
-    }
-
-    #[inline(always)]
-    fn clear(&mut self) { self.bits = 0; }
-
-    #[inline(always)]
-    fn set_all(&mut self) { self.bits = !0; }
-
-    #[inline(always)]
-    fn is_true(&self, nbits: uint) -> bool {
-        small_mask(nbits) & !self.bits == 0
-    }
-
-    #[inline(always)]
-    fn is_false(&self, nbits: uint) -> bool {
-        small_mask(nbits) & self.bits == 0
-    }
-
-    #[inline(always)]
-    fn invert(&mut self) { self.bits = !self.bits; }
-
-}
-
-struct BigBitv {
-    storage: ~[uint]
-}
-
-/**
- * a mask that has a 1 for each defined bit in the nth element of a big_bitv,
- * assuming n bits.
- */
-#[inline(always)]
-fn big_mask(nbits: uint, elem: uint) -> uint {
-    let rmd = nbits % uint::bits;
-    let nelems = nbits/uint::bits + if rmd == 0 {0} else {1};
-
-    if elem < nelems - 1 || rmd == 0 {
-        !0
-    } else {
-        (1 << rmd) - 1
-    }
-}
-
-pub impl BigBitv {
-    fn new(storage: ~[uint]) -> BigBitv {
-        BigBitv {storage: storage}
-    }
-
-    #[inline(always)]
-    fn process(&mut self, b: &BigBitv, nbits: uint,
-               op: &fn(uint, uint) -> uint) -> bool {
-        let len = b.storage.len();
-        assert_eq!(self.storage.len(), len);
-        let mut changed = false;
-        for uint::range(0, len) |i| {
-            let mask = big_mask(nbits, i);
-            let w0 = self.storage[i] & mask;
-            let w1 = b.storage[i] & mask;
-            let w = op(w0, w1) & mask;
-            if w0 != w {
-                changed = true;
-                self.storage[i] = w;
-            }
-        }
-        changed
-    }
-
-    #[inline(always)]
-    fn each_storage(&mut self, op: &fn(v: &mut uint) -> bool) -> bool {
-        uint::range(0, self.storage.len(), |i| op(&mut self.storage[i]))
-    }
-
-    #[inline(always)]
-    fn invert(&mut self) { for self.each_storage |w| { *w = !*w } }
-
-    #[inline(always)]
-    fn union(&mut self, b: &BigBitv, nbits: uint) -> bool {
-        self.process(b, nbits, |w1, w2| w1 | w2)
-    }
-
-    #[inline(always)]
-    fn intersect(&mut self, b: &BigBitv, nbits: uint) -> bool {
-        self.process(b, nbits, |w1, w2| w1 & w2)
-    }
-
-    #[inline(always)]
-    fn become(&mut self, b: &BigBitv, nbits: uint) -> bool {
-        self.process(b, nbits, |_, w| w)
-    }
-
-    #[inline(always)]
-    fn difference(&mut self, b: &BigBitv, nbits: uint) -> bool {
-        self.process(b, nbits, |w1, w2| w1 & !w2)
-    }
-
-    #[inline(always)]
-    fn get(&self, i: uint) -> bool {
-        let w = i / uint::bits;
-        let b = i % uint::bits;
-        let x = 1 & self.storage[w] >> b;
-        x == 1
-    }
-
-    #[inline(always)]
-    fn set(&mut self, i: uint, x: bool) {
-        let w = i / uint::bits;
-        let b = i % uint::bits;
-        let flag = 1 << b;
-        self.storage[w] = if x { self.storage[w] | flag }
-                          else { self.storage[w] & !flag };
-    }
-
-    #[inline(always)]
-    fn equals(&self, b: &BigBitv, nbits: uint) -> bool {
-        let len = b.storage.len();
-        for uint::iterate(0, len) |i| {
-            let mask = big_mask(nbits, i);
-            if mask & self.storage[i] != mask & b.storage[i] {
-                return false;
-            }
-        }
-        return true;
-    }
-
-}
-
-enum BitvVariant { Big(~BigBitv), Small(~SmallBitv) }
-
-enum Op {Union, Intersect, Assign, Difference}
-
-// The bitvector type
-pub struct Bitv {
-    rep: BitvVariant,
-    nbits: uint
-}
-
-fn die() -> ! {
-    fail!("Tried to do operation on bit vectors with different sizes");
-}
-
-priv impl Bitv {
-
-    #[inline(always)]
-    fn do_op(&mut self, op: Op, other: &Bitv) -> bool {
-        if self.nbits != other.nbits {
-            die();
-        }
-        match self.rep {
-          Small(ref mut s) => match other.rep {
-            Small(ref s1) => match op {
-              Union      => s.union(*s1,      self.nbits),
-              Intersect  => s.intersect(*s1,  self.nbits),
-              Assign     => s.become(*s1,     self.nbits),
-              Difference => s.difference(*s1, self.nbits)
-            },
-            Big(_) => die()
-          },
-          Big(ref mut s) => match other.rep {
-            Small(_) => die(),
-            Big(ref s1) => match op {
-              Union      => s.union(*s1,      self.nbits),
-              Intersect  => s.intersect(*s1,  self.nbits),
-              Assign     => s.become(*s1,     self.nbits),
-              Difference => s.difference(*s1, self.nbits)
-            }
-          }
-        }
-    }
-
-}
-
-pub impl Bitv {
-    fn new(nbits: uint, init: bool) -> Bitv {
-        let rep = if nbits <= uint::bits {
-            Small(~SmallBitv::new(if init {!0} else {0}))
-        }
-        else {
-            let nelems = nbits/uint::bits +
-                         if nbits % uint::bits == 0 {0} else {1};
-            let elem = if init {!0} else {0};
-            let s = from_elem(nelems, elem);
-            Big(~BigBitv::new(s))
-        };
-        Bitv {rep: rep, nbits: nbits}
-    }
-
-    /**
-     * Calculates the union of two bitvectors
-     *
-     * Sets `self` to the union of `self` and `v1`. Both bitvectors must be
-     * the same length. Returns 'true' if `self` changed.
-    */
-    #[inline(always)]
-    fn union(&mut self, v1: &Bitv) -> bool { self.do_op(Union, v1) }
-
-    /**
-     * Calculates the intersection of two bitvectors
-     *
-     * Sets `self` to the intersection of `self` and `v1`. Both bitvectors
-     * must be the same length. Returns 'true' if `self` changed.
-    */
-    #[inline(always)]
-    fn intersect(&mut self, v1: &Bitv) -> bool { self.do_op(Intersect, v1) }
-
-    /**
-     * Assigns the value of `v1` to `self`
-     *
-     * Both bitvectors must be the same length. Returns `true` if `self` was
-     * changed
-     */
-    #[inline(always)]
-    fn assign(&mut self, v: &Bitv) -> bool { self.do_op(Assign, v) }
-
-    /// Retrieve the value at index `i`
-    #[inline(always)]
-    fn get(&self, i: uint) -> bool {
-       assert!((i < self.nbits));
-       match self.rep {
-         Big(ref b)   => b.get(i),
-         Small(ref s) => s.get(i)
-       }
-    }
-
-    /**
-     * Set the value of a bit at a given index
-     *
-     * `i` must be less than the length of the bitvector.
-     */
-    #[inline(always)]
-    fn set(&mut self, i: uint, x: bool) {
-      assert!((i < self.nbits));
-      match self.rep {
-        Big(ref mut b)   => b.set(i, x),
-        Small(ref mut s) => s.set(i, x)
-      }
-    }
-
-    /**
-     * Compares two bitvectors
-     *
-     * Both bitvectors must be the same length. Returns `true` if both
-     * bitvectors contain identical elements.
-     */
-    #[inline(always)]
-    fn equal(&self, v1: &Bitv) -> bool {
-      if self.nbits != v1.nbits { return false; }
-      match self.rep {
-        Small(ref b) => match v1.rep {
-          Small(ref b1) => b.equals(*b1, self.nbits),
-          _ => false
-        },
-        Big(ref s) => match v1.rep {
-          Big(ref s1) => s.equals(*s1, self.nbits),
-          Small(_) => return false
-        }
-      }
-    }
-
-    /// Set all bits to 0
-    #[inline(always)]
-    fn clear(&mut self) {
-        match self.rep {
-          Small(ref mut b) => b.clear(),
-          Big(ref mut s) => for s.each_storage() |w| { *w = 0u }
-        }
-    }
-
-    /// Set all bits to 1
-    #[inline(always)]
-    fn set_all(&mut self) {
-      match self.rep {
-        Small(ref mut b) => b.set_all(),
-        Big(ref mut s) => for s.each_storage() |w| { *w = !0u } }
-    }
-
-    /// Invert all bits
-    #[inline(always)]
-    fn invert(&mut self) {
-      match self.rep {
-        Small(ref mut b) => b.invert(),
-        Big(ref mut s) => for s.each_storage() |w| { *w = !*w } }
-    }
-
-    /**
-     * Calculate the difference between two bitvectors
-     *
-     * Sets each element of `v0` to the value of that element minus the
-     * element of `v1` at the same index. Both bitvectors must be the same
-     * length.
-     *
-     * Returns `true` if `v0` was changed.
-     */
-    #[inline(always)]
-    fn difference(&mut self, v: &Bitv) -> bool { self.do_op(Difference, v) }
-
-    /// Returns true if all bits are 1
-    #[inline(always)]
-    fn is_true(&self) -> bool {
-      match self.rep {
-        Small(ref b) => b.is_true(self.nbits),
-        _ => {
-          for self.each() |i| { if !i { return false; } }
-          true
-        }
-      }
-    }
-
-    #[inline(always)]
-    fn each(&self, f: &fn(bool) -> bool) -> bool {
-        let mut i = 0;
-        while i < self.nbits {
-            if !f(self.get(i)) { return false; }
-            i += 1;
-        }
-        return true;
-    }
-
-    /// Returns true if all bits are 0
-    fn is_false(&self) -> bool {
-      match self.rep {
-        Small(ref b) => b.is_false(self.nbits),
-        Big(_) => {
-          for self.each() |i| { if i { return false; } }
-          true
-        }
-      }
-    }
-
-    fn init_to_vec(&self, i: uint) -> uint {
-      return if self.get(i) { 1 } else { 0 };
-    }
-
-    /**
-     * Converts `self` to a vector of uint with the same length.
-     *
-     * Each uint in the resulting vector has either value 0u or 1u.
-     */
-    fn to_vec(&self) -> ~[uint] {
-        vec::from_fn(self.nbits, |x| self.init_to_vec(x))
-    }
-
-    /**
-     * Organise the bits into bytes, such that the first bit in the
-     * bitv becomes the high-order bit of the first byte. If the
-     * size of the bitv is not a multiple of 8 then trailing bits
-     * will be filled-in with false/0
-     */
-    fn to_bytes(&self) -> ~[u8] {
-
-        fn bit (bitv: &Bitv, byte: uint, bit: uint) -> u8 {
-            let offset = byte * 8 + bit;
-            if offset >= bitv.nbits {
-                0
-            } else {
-                bitv[offset] as u8 << (7 - bit)
-            }
-        }
-
-        let len = self.nbits/8 +
-                  if self.nbits % 8 == 0 { 0 } else { 1 };
-        vec::from_fn(len, |i|
-            bit(self, i, 0) |
-            bit(self, i, 1) |
-            bit(self, i, 2) |
-            bit(self, i, 3) |
-            bit(self, i, 4) |
-            bit(self, i, 5) |
-            bit(self, i, 6) |
-            bit(self, i, 7)
-        )
-    }
-
-    /**
-     * Transform self into a [bool] by turning each bit into a bool
-     */
-    fn to_bools(&self) -> ~[bool] {
-        vec::from_fn(self.nbits, |i| self[i])
-    }
-
-    /**
-     * Converts `self` to a string.
-     *
-     * The resulting string has the same length as `self`, and each
-     * character is either '0' or '1'.
-     */
-     fn to_str(&self) -> ~str {
-       let mut rs = ~"";
-       for self.each() |i| { if i { rs += ~"1"; } else { rs += ~"0"; } };
-       rs
-     }
-
-
-    /**
-     * Compare a bitvector to a vector of uint
-     *
-     * The uint vector is expected to only contain the values 0u and 1u. Both
-     * the bitvector and vector must have the same length
-     */
-    fn eq_vec(&self, v: ~[uint]) -> bool {
-        assert_eq!(self.nbits, v.len());
-        let mut i = 0;
-        while i < self.nbits {
-            let w0 = self.get(i);
-            let w1 = v[i];
-            if !w0 && w1 != 0u || w0 && w1 == 0u { return false; }
-            i = i + 1;
-        }
-        true
-    }
-
-    fn ones(&self, f: &fn(uint) -> bool) -> bool {
-        uint::range(0, self.nbits, |i| !self.get(i) || f(i))
-    }
-
-}
-
-impl Clone for Bitv {
-    /// Makes a copy of a bitvector
-    #[inline(always)]
-    fn clone(&self) -> Bitv {
-        match self.rep {
-          Small(ref b) => {
-            Bitv{nbits: self.nbits, rep: Small(~SmallBitv{bits: b.bits})}
-          }
-          Big(ref b) => {
-            let mut st = from_elem(self.nbits / uint::bits + 1, 0);
-            let len = st.len();
-            for uint::range(0, len) |i| { st[i] = b.storage[i]; };
-            Bitv{nbits: self.nbits, rep: Big(~BigBitv{storage: st})}
-          }
-        }
-    }
-
-}
-
-/**
- * Transform a byte-vector into a bitv. Each byte becomes 8 bits,
- * with the most significant bits of each byte coming first. Each
- * bit becomes true if equal to 1 or false if equal to 0.
- */
-pub fn from_bytes(bytes: &[u8]) -> Bitv {
-    from_fn(bytes.len() * 8, |i| {
-        let b = bytes[i / 8] as uint;
-        let offset = i % 8;
-        b >> (7 - offset) & 1 == 1
-    })
-}
-
-/**
- * Transform a [bool] into a bitv by converting each bool into a bit.
- */
-pub fn from_bools(bools: &[bool]) -> Bitv {
-    from_fn(bools.len(), |i| bools[i])
-}
-
-/**
- * Create a bitv of the specified length where the value at each
- * index is f(index).
- */
-pub fn from_fn(len: uint, f: &fn(index: uint) -> bool) -> Bitv {
-    let mut bitv = Bitv::new(len, false);
-    for uint::range(0, len) |i| {
-        bitv.set(i, f(i));
-    }
-    bitv
-}
-
-impl ops::Index<uint,bool> for Bitv {
-    fn index(&self, i: &uint) -> bool {
-        self.get(*i)
-    }
-}
-
-#[inline(always)]
-fn iterate_bits(base: uint, bits: uint, f: &fn(uint) -> bool) -> bool {
-    if bits == 0 {
-        return true;
-    }
-    for uint::range(0, uint::bits) |i| {
-        if bits & (1 << i) != 0 {
-            if !f(base + i) {
-                return false;
-            }
-        }
-    }
-    return true;
-}
-
-/// An implementation of a set using a bit vector as an underlying
-/// representation for holding numerical elements.
-///
-/// It should also be noted that the amount of storage necessary for holding a
-/// set of objects is proportional to the maximum of the objects when viewed
-/// as a uint.
-pub struct BitvSet {
-    priv size: uint,
-
-    // In theory this is a Bitv instead of always a BigBitv, but knowing that
-    // there's an array of storage makes our lives a whole lot easier when
-    // performing union/intersection/etc operations
-    priv bitv: BigBitv
-}
-
-pub impl BitvSet {
-    /// Creates a new bit vector set with initially no contents
-    fn new() -> BitvSet {
-        BitvSet{ size: 0, bitv: BigBitv::new(~[0]) }
-    }
-
-    /// Creates a new bit vector set from the given bit vector
-    fn from_bitv(bitv: Bitv) -> BitvSet {
-        let mut size = 0;
-        for bitv.ones |_| {
-            size += 1;
-        }
-        let Bitv{rep, _} = bitv;
-        match rep {
-            Big(~b) => BitvSet{ size: size, bitv: b },
-            Small(~SmallBitv{bits}) =>
-                BitvSet{ size: size, bitv: BigBitv{ storage: ~[bits] } },
-        }
-    }
-
-    /// Returns the capacity in bits for this bit vector. Inserting any
-    /// element less than this amount will not trigger a resizing.
-    fn capacity(&self) -> uint { self.bitv.storage.len() * uint::bits }
-
-    /// Consumes this set to return the underlying bit vector
-    fn unwrap(self) -> Bitv {
-        let cap = self.capacity();
-        let BitvSet{bitv, _} = self;
-        return Bitv{ nbits:cap, rep: Big(~bitv) };
-    }
-
-    #[inline(always)]
-    priv fn other_op(&mut self, other: &BitvSet, f: &fn(uint, uint) -> uint) {
-        fn nbits(mut w: uint) -> uint {
-            let mut bits = 0;
-            for uint::bits.times {
-                if w == 0 {
-                    break;
-                }
-                bits += w & 1;
-                w >>= 1;
-            }
-            return bits;
-        }
-        if self.capacity() < other.capacity() {
-            self.bitv.storage.grow(other.capacity() / uint::bits, &0);
-        }
-        for other.bitv.storage.eachi |i, &w| {
-            let old = self.bitv.storage[i];
-            let new = f(old, w);
-            self.bitv.storage[i] = new;
-            self.size += nbits(new) - nbits(old);
-        }
-    }
-
-    /// Union in-place with the specified other bit vector
-    fn union_with(&mut self, other: &BitvSet) {
-        self.other_op(other, |w1, w2| w1 | w2);
-    }
-
-    /// Intersect in-place with the specified other bit vector
-    fn intersect_with(&mut self, other: &BitvSet) {
-        self.other_op(other, |w1, w2| w1 & w2);
-    }
-
-    /// Difference in-place with the specified other bit vector
-    fn difference_with(&mut self, other: &BitvSet) {
-        self.other_op(other, |w1, w2| w1 & !w2);
-    }
-
-    /// Symmetric difference in-place with the specified other bit vector
-    fn symmetric_difference_with(&mut self, other: &BitvSet) {
-        self.other_op(other, |w1, w2| w1 ^ w2);
-    }
-}
-
-impl BaseIter<uint> for BitvSet {
-    fn size_hint(&self) -> Option<uint> { Some(self.len()) }
-
-    fn each(&self, blk: &fn(v: &uint) -> bool) -> bool {
-        for self.bitv.storage.eachi |i, &w| {
-            if !iterate_bits(i * uint::bits, w, |b| blk(&b)) {
-                return false;
-            }
-        }
-        return true;
-    }
-}
-
-impl cmp::Eq for BitvSet {
-    fn eq(&self, other: &BitvSet) -> bool {
-        if self.size != other.size {
-            return false;
-        }
-        for self.each_common(other) |_, w1, w2| {
-            if w1 != w2 {
-                return false;
-            }
-        }
-        for self.each_outlier(other) |_, _, w| {
-            if w != 0 {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    fn ne(&self, other: &BitvSet) -> bool { !self.eq(other) }
-}
-
-impl Container for BitvSet {
-    fn len(&const self) -> uint { self.size }
-    fn is_empty(&const self) -> bool { self.size == 0 }
-}
-
-impl Mutable for BitvSet {
-    fn clear(&mut self) {
-        for self.bitv.each_storage |w| { *w = 0; }
-        self.size = 0;
-    }
-}
-
-impl Set<uint> for BitvSet {
-    fn contains(&self, value: &uint) -> bool {
-        *value < self.bitv.storage.len() * uint::bits && self.bitv.get(*value)
-    }
-
-    fn insert(&mut self, value: uint) -> bool {
-        if self.contains(&value) {
-            return false;
-        }
-        let nbits = self.capacity();
-        if value >= nbits {
-            let newsize = uint::max(value, nbits * 2) / uint::bits + 1;
-            assert!(newsize > self.bitv.storage.len());
-            self.bitv.storage.grow(newsize, &0);
-        }
-        self.size += 1;
-        self.bitv.set(value, true);
-        return true;
-    }
-
-    fn remove(&mut self, value: &uint) -> bool {
-        if !self.contains(value) {
-            return false;
-        }
-        self.size -= 1;
-        self.bitv.set(*value, false);
-
-        // Attempt to truncate our storage
-        let mut i = self.bitv.storage.len();
-        while i > 1 && self.bitv.storage[i - 1] == 0 {
-            i -= 1;
-        }
-        self.bitv.storage.truncate(i);
-
-        return true;
-    }
-
-    fn is_disjoint(&self, other: &BitvSet) -> bool {
-        for self.intersection(other) |_| {
-            return false;
-        }
-        return true;
-    }
-
-    fn is_subset(&self, other: &BitvSet) -> bool {
-        for self.each_common(other) |_, w1, w2| {
-            if w1 & w2 != w1 {
-                return false;
-            }
-        }
-        /* If anything is not ours, then everything is not ours so we're
-           definitely a subset in that case. Otherwise if there's any stray
-           ones that 'other' doesn't have, we're not a subset. */
-        for self.each_outlier(other) |mine, _, w| {
-            if !mine {
-                return true;
-            } else if w != 0 {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    fn is_superset(&self, other: &BitvSet) -> bool {
-        other.is_subset(self)
-    }
-
-    fn difference(&self, other: &BitvSet, f: &fn(&uint) -> bool) -> bool {
-        for self.each_common(other) |i, w1, w2| {
-            if !iterate_bits(i, w1 & !w2, |b| f(&b)) {
-                return false;
-            }
-        }
-        /* everything we have that they don't also shows up */
-        self.each_outlier(other, |mine, i, w|
-            !mine || iterate_bits(i, w, |b| f(&b))
-        )
-    }
-
-    fn symmetric_difference(&self, other: &BitvSet,
-                            f: &fn(&uint) -> bool) -> bool {
-        for self.each_common(other) |i, w1, w2| {
-            if !iterate_bits(i, w1 ^ w2, |b| f(&b)) {
-                return false;
-            }
-        }
-        self.each_outlier(other, |_, i, w| iterate_bits(i, w, |b| f(&b)))
-    }
-
-    fn intersection(&self, other: &BitvSet, f: &fn(&uint) -> bool) -> bool {
-        self.each_common(other, |i, w1, w2| iterate_bits(i, w1 & w2, |b| f(&b)))
-    }
-
-    fn union(&self, other: &BitvSet, f: &fn(&uint) -> bool) -> bool {
-        for self.each_common(other) |i, w1, w2| {
-            if !iterate_bits(i, w1 | w2, |b| f(&b)) {
-                return false;
-            }
-        }
-        self.each_outlier(other, |_, i, w| iterate_bits(i, w, |b| f(&b)))
-    }
-}
-
-priv impl BitvSet {
-    /// Visits each of the words that the two bit vectors (self and other)
-    /// both have in common. The three yielded arguments are (bit location,
-    /// w1, w2) where the bit location is the number of bits offset so far,
-    /// and w1/w2 are the words coming from the two vectors self, other.
-    fn each_common(&self, other: &BitvSet,
-                   f: &fn(uint, uint, uint) -> bool) -> bool {
-        let min = uint::min(self.bitv.storage.len(),
-                            other.bitv.storage.len());
-        self.bitv.storage.slice(0, min).eachi(|i, &w| {
-            f(i * uint::bits, w, other.bitv.storage[i])
-        })
-    }
-
-    /// Visits each word in self or other that extends beyond the other. This
-    /// will only iterate through one of the vectors, and it only iterates
-    /// over the portion that doesn't overlap with the other one.
-    ///
-    /// The yielded arguments are a bool, the bit offset, and a word. The bool
-    /// is true if the word comes from 'self', and false if it comes from
-    /// 'other'.
-    fn each_outlier(&self, other: &BitvSet,
-                    f: &fn(bool, uint, uint) -> bool) -> bool {
-        let len1 = self.bitv.storage.len();
-        let len2 = other.bitv.storage.len();
-        let min = uint::min(len1, len2);
-
-        /* only one of these loops will execute and that's the point */
-        for self.bitv.storage.slice(min, len1).eachi |i, &w| {
-            if !f(true, (i + min) * uint::bits, w) {
-                return false;
-            }
-        }
-        for other.bitv.storage.slice(min, len2).eachi |i, &w| {
-            if !f(false, (i + min) * uint::bits, w) {
-                return false;
-            }
-        }
-        return true;
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use std::test::BenchHarness;
-
-    use bitv::*;
-    use bitv;
-
-    use core::uint;
-    use core::vec;
-    use core::rand;
-    use core::rand::Rng;
-
-    static bench_bits : uint = 1 << 14;
-
-    #[test]
-    fn test_to_str() {
-        let zerolen = Bitv::new(0u, false);
-        assert_eq!(zerolen.to_str(), ~"");
-
-        let eightbits = Bitv::new(8u, false);
-        assert_eq!(eightbits.to_str(), ~"00000000");
-    }
-
-    #[test]
-    fn test_0_elements() {
-        let mut act;
-        let exp;
-        act = Bitv::new(0u, false);
-        exp = vec::from_elem::<uint>(0u, 0u);
-        assert!(act.eq_vec(exp));
-    }
-
-    #[test]
-    fn test_1_element() {
-        let mut act;
-        act = Bitv::new(1u, false);
-        assert!(act.eq_vec(~[0u]));
-        act = Bitv::new(1u, true);
-        assert!(act.eq_vec(~[1u]));
-    }
-
-    #[test]
-    fn test_2_elements() {
-        let mut b = bitv::Bitv::new(2, false);
-        b.set(0, true);
-        b.set(1, false);
-        assert_eq!(b.to_str(), ~"10");
-    }
-
-    #[test]
-    fn test_10_elements() {
-        let mut act;
-        // all 0
-
-        act = Bitv::new(10u, false);
-        assert!((act.eq_vec(~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u])));
-        // all 1
-
-        act = Bitv::new(10u, true);
-        assert!((act.eq_vec(~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u])));
-        // mixed
-
-        act = Bitv::new(10u, false);
-        act.set(0u, true);
-        act.set(1u, true);
-        act.set(2u, true);
-        act.set(3u, true);
-        act.set(4u, true);
-        assert!((act.eq_vec(~[1u, 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u, 0u])));
-        // mixed
-
-        act = Bitv::new(10u, false);
-        act.set(5u, true);
-        act.set(6u, true);
-        act.set(7u, true);
-        act.set(8u, true);
-        act.set(9u, true);
-        assert!((act.eq_vec(~[0u, 0u, 0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u])));
-        // mixed
-
-        act = Bitv::new(10u, false);
-        act.set(0u, true);
-        act.set(3u, true);
-        act.set(6u, true);
-        act.set(9u, true);
-        assert!((act.eq_vec(~[1u, 0u, 0u, 1u, 0u, 0u, 1u, 0u, 0u, 1u])));
-    }
-
-    #[test]
-    fn test_31_elements() {
-        let mut act;
-        // all 0
-
-        act = Bitv::new(31u, false);
-        assert!(act.eq_vec(
-                       ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u]));
-        // all 1
-
-        act = Bitv::new(31u, true);
-        assert!(act.eq_vec(
-                       ~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
-                        1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
-                        1u, 1u, 1u, 1u, 1u]));
-        // mixed
-
-        act = Bitv::new(31u, false);
-        act.set(0u, true);
-        act.set(1u, true);
-        act.set(2u, true);
-        act.set(3u, true);
-        act.set(4u, true);
-        act.set(5u, true);
-        act.set(6u, true);
-        act.set(7u, true);
-        assert!(act.eq_vec(
-                       ~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u]));
-        // mixed
-
-        act = Bitv::new(31u, false);
-        act.set(16u, true);
-        act.set(17u, true);
-        act.set(18u, true);
-        act.set(19u, true);
-        act.set(20u, true);
-        act.set(21u, true);
-        act.set(22u, true);
-        act.set(23u, true);
-        assert!(act.eq_vec(
-                       ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u]));
-        // mixed
-
-        act = Bitv::new(31u, false);
-        act.set(24u, true);
-        act.set(25u, true);
-        act.set(26u, true);
-        act.set(27u, true);
-        act.set(28u, true);
-        act.set(29u, true);
-        act.set(30u, true);
-        assert!(act.eq_vec(
-                       ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u,
-                        1u, 1u, 1u, 1u, 1u]));
-        // mixed
-
-        act = Bitv::new(31u, false);
-        act.set(3u, true);
-        act.set(17u, true);
-        act.set(30u, true);
-        assert!(act.eq_vec(
-                       ~[0u, 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 1u]));
-    }
-
-    #[test]
-    fn test_32_elements() {
-        let mut act;
-        // all 0
-
-        act = Bitv::new(32u, false);
-        assert!(act.eq_vec(
-                       ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u]));
-        // all 1
-
-        act = Bitv::new(32u, true);
-        assert!(act.eq_vec(
-                       ~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
-                        1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
-                        1u, 1u, 1u, 1u, 1u, 1u]));
-        // mixed
-
-        act = Bitv::new(32u, false);
-        act.set(0u, true);
-        act.set(1u, true);
-        act.set(2u, true);
-        act.set(3u, true);
-        act.set(4u, true);
-        act.set(5u, true);
-        act.set(6u, true);
-        act.set(7u, true);
-        assert!(act.eq_vec(
-                       ~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u]));
-        // mixed
-
-        act = Bitv::new(32u, false);
-        act.set(16u, true);
-        act.set(17u, true);
-        act.set(18u, true);
-        act.set(19u, true);
-        act.set(20u, true);
-        act.set(21u, true);
-        act.set(22u, true);
-        act.set(23u, true);
-        assert!(act.eq_vec(
-                       ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u]));
-        // mixed
-
-        act = Bitv::new(32u, false);
-        act.set(24u, true);
-        act.set(25u, true);
-        act.set(26u, true);
-        act.set(27u, true);
-        act.set(28u, true);
-        act.set(29u, true);
-        act.set(30u, true);
-        act.set(31u, true);
-        assert!(act.eq_vec(
-                       ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u,
-                        1u, 1u, 1u, 1u, 1u, 1u]));
-        // mixed
-
-        act = Bitv::new(32u, false);
-        act.set(3u, true);
-        act.set(17u, true);
-        act.set(30u, true);
-        act.set(31u, true);
-        assert!(act.eq_vec(
-                       ~[0u, 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 1u, 1u]));
-    }
-
-    #[test]
-    fn test_33_elements() {
-        let mut act;
-        // all 0
-
-        act = Bitv::new(33u, false);
-        assert!(act.eq_vec(
-                       ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u, 0u]));
-        // all 1
-
-        act = Bitv::new(33u, true);
-        assert!(act.eq_vec(
-                       ~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
-                        1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u,
-                        1u, 1u, 1u, 1u, 1u, 1u, 1u]));
-        // mixed
-
-        act = Bitv::new(33u, false);
-        act.set(0u, true);
-        act.set(1u, true);
-        act.set(2u, true);
-        act.set(3u, true);
-        act.set(4u, true);
-        act.set(5u, true);
-        act.set(6u, true);
-        act.set(7u, true);
-        assert!(act.eq_vec(
-                       ~[1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u, 0u]));
-        // mixed
-
-        act = Bitv::new(33u, false);
-        act.set(16u, true);
-        act.set(17u, true);
-        act.set(18u, true);
-        act.set(19u, true);
-        act.set(20u, true);
-        act.set(21u, true);
-        act.set(22u, true);
-        act.set(23u, true);
-        assert!(act.eq_vec(
-                       ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 1u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u, 0u]));
-        // mixed
-
-        act = Bitv::new(33u, false);
-        act.set(24u, true);
-        act.set(25u, true);
-        act.set(26u, true);
-        act.set(27u, true);
-        act.set(28u, true);
-        act.set(29u, true);
-        act.set(30u, true);
-        act.set(31u, true);
-        assert!(act.eq_vec(
-                       ~[0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 1u, 1u,
-                        1u, 1u, 1u, 1u, 1u, 1u, 0u]));
-        // mixed
-
-        act = Bitv::new(33u, false);
-        act.set(3u, true);
-        act.set(17u, true);
-        act.set(30u, true);
-        act.set(31u, true);
-        act.set(32u, true);
-        assert!(act.eq_vec(
-                       ~[0u, 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u,
-                        0u, 0u, 0u, 0u, 1u, 1u, 1u]));
-    }
-
-    #[test]
-    fn test_equal_differing_sizes() {
-        let v0 = Bitv::new(10u, false);
-        let v1 = Bitv::new(11u, false);
-        assert!(!v0.equal(&v1));
-    }
-
-    #[test]
-    fn test_equal_greatly_differing_sizes() {
-        let v0 = Bitv::new(10u, false);
-        let v1 = Bitv::new(110u, false);
-        assert!(!v0.equal(&v1));
-    }
-
-    #[test]
-    fn test_equal_sneaky_small() {
-        let mut a = bitv::Bitv::new(1, false);
-        a.set(0, true);
-
-        let mut b = bitv::Bitv::new(1, true);
-        b.set(0, true);
-
-        assert!(a.equal(&b));
-    }
-
-    #[test]
-    fn test_equal_sneaky_big() {
-        let mut a = bitv::Bitv::new(100, false);
-        for uint::range(0, 100) |i| {
-            a.set(i, true);
-        }
-
-        let mut b = bitv::Bitv::new(100, true);
-        for uint::range(0, 100) |i| {
-            b.set(i, true);
-        }
-
-        assert!(a.equal(&b));
-    }
-
-    #[test]
-    fn test_from_bytes() {
-        let bitv = from_bytes([0b10110110, 0b00000000, 0b11111111]);
-        let str = ~"10110110" + ~"00000000" + ~"11111111";
-        assert_eq!(bitv.to_str(), str);
-    }
-
-    #[test]
-    fn test_to_bytes() {
-        let mut bv = Bitv::new(3, true);
-        bv.set(1, false);
-        assert_eq!(bv.to_bytes(), ~[0b10100000]);
-
-        let mut bv = Bitv::new(9, false);
-        bv.set(2, true);
-        bv.set(8, true);
-        assert_eq!(bv.to_bytes(), ~[0b00100000, 0b10000000]);
-    }
-
-    #[test]
-    fn test_from_bools() {
-        assert!(from_bools([true, false, true, true]).to_str() ==
-            ~"1011");
-    }
-
-    #[test]
-    fn test_to_bools() {
-        let bools = ~[false, false, true, false, false, true, true, false];
-        assert_eq!(from_bytes([0b00100110]).to_bools(), bools);
-    }
-
-    #[test]
-    fn test_small_difference() {
-        let mut b1 = Bitv::new(3, false);
-        let mut b2 = Bitv::new(3, false);
-        b1.set(0, true);
-        b1.set(1, true);
-        b2.set(1, true);
-        b2.set(2, true);
-        assert!(b1.difference(&b2));
-        assert!(b1[0]);
-        assert!(!b1[1]);
-        assert!(!b1[2]);
-    }
-
-    #[test]
-    fn test_big_difference() {
-        let mut b1 = Bitv::new(100, false);
-        let mut b2 = Bitv::new(100, false);
-        b1.set(0, true);
-        b1.set(40, true);
-        b2.set(40, true);
-        b2.set(80, true);
-        assert!(b1.difference(&b2));
-        assert!(b1[0]);
-        assert!(!b1[40]);
-        assert!(!b1[80]);
-    }
-
-    #[test]
-    fn test_small_clear() {
-        let mut b = Bitv::new(14, true);
-        b.clear();
-        for b.ones |i| {
-            fail!("found 1 at %?", i);
-        }
-    }
-
-    #[test]
-    fn test_big_clear() {
-        let mut b = Bitv::new(140, true);
-        b.clear();
-        for b.ones |i| {
-            fail!("found 1 at %?", i);
-        }
-    }
-
-    #[test]
-    fn test_bitv_set_basic() {
-        let mut b = BitvSet::new();
-        assert!(b.insert(3));
-        assert!(!b.insert(3));
-        assert!(b.contains(&3));
-        assert!(b.insert(400));
-        assert!(!b.insert(400));
-        assert!(b.contains(&400));
-        assert_eq!(b.len(), 2);
-    }
-
-    #[test]
-    fn test_bitv_set_intersection() {
-        let mut a = BitvSet::new();
-        let mut b = BitvSet::new();
-
-        assert!(a.insert(11));
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(77));
-        assert!(a.insert(103));
-        assert!(a.insert(5));
-
-        assert!(b.insert(2));
-        assert!(b.insert(11));
-        assert!(b.insert(77));
-        assert!(b.insert(5));
-        assert!(b.insert(3));
-
-        let mut i = 0;
-        let expected = [3, 5, 11, 77];
-        for a.intersection(&b) |x| {
-            assert_eq!(*x, expected[i]);
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_bitv_set_difference() {
-        let mut a = BitvSet::new();
-        let mut b = BitvSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(200));
-        assert!(a.insert(500));
-
-        assert!(b.insert(3));
-        assert!(b.insert(200));
-
-        let mut i = 0;
-        let expected = [1, 5, 500];
-        for a.difference(&b) |x| {
-            assert_eq!(*x, expected[i]);
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_bitv_set_symmetric_difference() {
-        let mut a = BitvSet::new();
-        let mut b = BitvSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-
-        assert!(b.insert(3));
-        assert!(b.insert(9));
-        assert!(b.insert(14));
-        assert!(b.insert(220));
-
-        let mut i = 0;
-        let expected = [1, 5, 11, 14, 220];
-        for a.symmetric_difference(&b) |x| {
-            assert_eq!(*x, expected[i]);
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_bitv_set_union() {
-        let mut a = BitvSet::new();
-        let mut b = BitvSet::new();
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-        assert!(a.insert(160));
-        assert!(a.insert(19));
-        assert!(a.insert(24));
-
-        assert!(b.insert(1));
-        assert!(b.insert(5));
-        assert!(b.insert(9));
-        assert!(b.insert(13));
-        assert!(b.insert(19));
-
-        let mut i = 0;
-        let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160];
-        for a.union(&b) |x| {
-            assert_eq!(*x, expected[i]);
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_bitv_remove() {
-        let mut a = BitvSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.remove(&1));
-
-        assert!(a.insert(100));
-        assert!(a.remove(&100));
-
-        assert!(a.insert(1000));
-        assert!(a.remove(&1000));
-        assert_eq!(a.capacity(), uint::bits);
-    }
-
-    fn rng() -> rand::IsaacRng {
-        let seed = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
-        rand::IsaacRng::new_seeded(seed)
-    }
-
-    #[bench]
-    fn bench_uint_small(b: &mut BenchHarness) {
-        let mut r = rng();
-        let mut bitv = 0 as uint;
-        do b.iter {
-            bitv |= (1 << ((r.next() as uint) % uint::bits));
-        }
-    }
-
-    #[bench]
-    fn bench_small_bitv_small(b: &mut BenchHarness) {
-        let mut r = rng();
-        let mut bitv = SmallBitv::new(uint::bits);
-        do b.iter {
-            bitv.set((r.next() as uint) % uint::bits, true);
-        }
-    }
-
-    #[bench]
-    fn bench_big_bitv_small(b: &mut BenchHarness) {
-        let mut r = rng();
-        let mut bitv = BigBitv::new(~[0]);
-        do b.iter {
-            bitv.set((r.next() as uint) % uint::bits, true);
-        }
-    }
-
-    #[bench]
-    fn bench_big_bitv_big(b: &mut BenchHarness) {
-        let mut r = rng();
-        let mut storage = ~[];
-        storage.grow(bench_bits / uint::bits, &0);
-        let mut bitv = BigBitv::new(storage);
-        do b.iter {
-            bitv.set((r.next() as uint) % bench_bits, true);
-        }
-    }
-
-    #[bench]
-    fn bench_bitv_big(b: &mut BenchHarness) {
-        let mut r = rng();
-        let mut bitv = Bitv::new(bench_bits, false);
-        do b.iter {
-            bitv.set((r.next() as uint) % bench_bits, true);
-        }
-    }
-
-    #[bench]
-    fn bench_bitv_small(b: &mut BenchHarness) {
-        let mut r = rng();
-        let mut bitv = Bitv::new(uint::bits, false);
-        do b.iter {
-            bitv.set((r.next() as uint) % uint::bits, true);
-        }
-    }
-
-    #[bench]
-    fn bench_bitv_set_small(b: &mut BenchHarness) {
-        let mut r = rng();
-        let mut bitv = BitvSet::new();
-        do b.iter {
-            bitv.insert((r.next() as uint) % uint::bits);
-        }
-    }
-
-    #[bench]
-    fn bench_bitv_set_big(b: &mut BenchHarness) {
-        let mut r = rng();
-        let mut bitv = BitvSet::new();
-        do b.iter {
-            bitv.insert((r.next() as uint) % bench_bits);
-        }
-    }
-
-    #[bench]
-    fn bench_bitv_big_union(b: &mut BenchHarness) {
-        let mut b1 = Bitv::new(bench_bits, false);
-        let mut b2 = Bitv::new(bench_bits, false);
-        do b.iter {
-            b1.union(&b2);
-        }
-    }
-}
diff --git a/src/libstd/bool.rs b/src/libstd/bool.rs
new file mode 100644
index 00000000000..5ab7f838a57
--- /dev/null
+++ b/src/libstd/bool.rs
@@ -0,0 +1,153 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Boolean logic
+
+#[cfg(not(test))]
+use cmp::{Eq, Ord, TotalOrd, Ordering};
+use option::{None, Option, Some};
+use from_str::FromStr;
+
+/// Negation / inverse
+pub fn not(v: bool) -> bool { !v }
+
+/// Conjunction
+pub fn and(a: bool, b: bool) -> bool { a && b }
+
+/// Disjunction
+pub fn or(a: bool, b: bool) -> bool { a || b }
+
+/**
+ * Exclusive or
+ *
+ * Identical to `or(and(a, not(b)), and(not(a), b))`
+ */
+pub fn xor(a: bool, b: bool) -> bool { (a && !b) || (!a && b) }
+
+/// Implication in the logic, i.e. from `a` follows `b`
+pub fn implies(a: bool, b: bool) -> bool { !a || b }
+
+/// true if truth values `a` and `b` are indistinguishable in the logic
+pub fn eq(a: bool, b: bool) -> bool { a == b }
+
+/// true if truth values `a` and `b` are distinguishable in the logic
+pub fn ne(a: bool, b: bool) -> bool { a != b }
+
+/// true if `v` represents truth in the logic
+pub fn is_true(v: bool) -> bool { v }
+
+/// true if `v` represents falsehood in the logic
+pub fn is_false(v: bool) -> bool { !v }
+
+/// Parse logic value from `s`
+impl FromStr for bool {
+    fn from_str(s: &str) -> Option<bool> {
+        match s {
+            "true"  => Some(true),
+            "false" => Some(false),
+            _       => None,
+        }
+    }
+}
+
+/// Convert `v` into a string
+pub fn to_str(v: bool) -> ~str { if v { ~"true" } else { ~"false" } }
+
+/**
+ * Iterates over all truth values by passing them to `blk` in an unspecified
+ * order
+ */
+pub fn all_values(blk: &fn(v: bool)) {
+    blk(true);
+    blk(false);
+}
+
+/// converts truth value to an 8 bit byte
+#[inline(always)]
+pub fn to_bit(v: bool) -> u8 { if v { 1u8 } else { 0u8 } }
+
+#[cfg(not(test))]
+impl Ord for bool {
+    #[inline(always)]
+    fn lt(&self, other: &bool) -> bool { to_bit(*self) < to_bit(*other) }
+    #[inline(always)]
+    fn le(&self, other: &bool) -> bool { to_bit(*self) <= to_bit(*other) }
+    #[inline(always)]
+    fn gt(&self, other: &bool) -> bool { to_bit(*self) > to_bit(*other) }
+    #[inline(always)]
+    fn ge(&self, other: &bool) -> bool { to_bit(*self) >= to_bit(*other) }
+}
+
+#[cfg(not(test))]
+impl TotalOrd for bool {
+    #[inline(always)]
+    fn cmp(&self, other: &bool) -> Ordering { to_bit(*self).cmp(&to_bit(*other)) }
+}
+
+#[cfg(not(test))]
+impl Eq for bool {
+    #[inline(always)]
+    fn eq(&self, other: &bool) -> bool { (*self) == (*other) }
+    #[inline(always)]
+    fn ne(&self, other: &bool) -> bool { (*self) != (*other) }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use prelude::*;
+
+    #[test]
+    fn test_bool_from_str() {
+        do all_values |v| {
+            assert!(Some(v) == FromStr::from_str(to_str(v)))
+        }
+    }
+
+    #[test]
+    fn test_bool_to_str() {
+        assert_eq!(to_str(false), ~"false");
+        assert_eq!(to_str(true), ~"true");
+    }
+
+    #[test]
+    fn test_bool_to_bit() {
+        do all_values |v| {
+            assert_eq!(to_bit(v), if is_true(v) { 1u8 } else { 0u8 });
+        }
+    }
+
+    #[test]
+    fn test_bool_ord() {
+        assert!(true > false);
+        assert!(!(false > true));
+
+        assert!(false < true);
+        assert!(!(true < false));
+
+        assert!(false <= false);
+        assert!(false >= false);
+        assert!(true <= true);
+        assert!(true >= true);
+
+        assert!(false <= true);
+        assert!(!(false >= true));
+        assert!(true >= false);
+        assert!(!(true <= false));
+    }
+
+    #[test]
+    fn test_bool_totalord() {
+        assert_eq!(true.cmp(&true), Equal);
+        assert_eq!(false.cmp(&false), Equal);
+        assert_eq!(true.cmp(&false), Greater);
+        assert_eq!(false.cmp(&true), Less);
+    }
+}
diff --git a/src/libstd/c_vec.rs b/src/libstd/c_vec.rs
deleted file mode 100644
index e463e597188..00000000000
--- a/src/libstd/c_vec.rs
+++ /dev/null
@@ -1,202 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
- * Library to interface with chunks of memory allocated in C.
- *
- * It is often desirable to safely interface with memory allocated from C,
- * encapsulating the unsafety into allocation and destruction time.  Indeed,
- * allocating memory externally is currently the only way to give Rust shared
- * mut state with C programs that keep their own references; vectors are
- * unsuitable because they could be reallocated or moved at any time, and
- * importing C memory into a vector takes a one-time snapshot of the memory.
- *
- * This module simplifies the usage of such external blocks of memory.  Memory
- * is encapsulated into an opaque object after creation; the lifecycle of the
- * memory can be optionally managed by Rust, if an appropriate destructor
- * closure is provided.  Safety is ensured by bounds-checking accesses, which
- * are marshalled through get and set functions.
- *
- * There are three unsafe functions: the two introduction forms, and the
- * pointer elimination form.  The introduction forms are unsafe for the
- * obvious reason (they act on a pointer that cannot be checked inside the
- * method), but the elimination form is somewhat more subtle in its unsafety.
- * By using a pointer taken from a c_vec::t without keeping a reference to the
- * c_vec::t itself around, the CVec could be garbage collected, and the
- * memory within could be destroyed.  There are legitimate uses for the
- * pointer elimination form -- for instance, to pass memory back into C -- but
- * great care must be taken to ensure that a reference to the c_vec::t is
- * still held if needed.
- */
-
-/**
- * The type representing a foreign chunk of memory
- *
- */
-pub struct CVec<T> {
-    priv base: *mut T,
-    priv len: uint,
-    priv rsrc: @DtorRes
-}
-
-struct DtorRes {
-  dtor: Option<@fn()>,
-}
-
-#[unsafe_destructor]
-impl Drop for DtorRes {
-    fn finalize(&self) {
-        match self.dtor {
-            option::None => (),
-            option::Some(f) => f()
-        }
-    }
-}
-
-fn DtorRes(dtor: Option<@fn()>) -> DtorRes {
-    DtorRes {
-        dtor: dtor
-    }
-}
-
-/*
- Section: Introduction forms
- */
-
-/**
- * Create a `CVec` from a foreign buffer with a given length.
- *
- * # Arguments
- *
- * * base - A foreign pointer to a buffer
- * * len - The number of elements in the buffer
- */
-pub unsafe fn CVec<T>(base: *mut T, len: uint) -> CVec<T> {
-    return CVec{
-        base: base,
-        len: len,
-        rsrc: @DtorRes(option::None)
-    };
-}
-
-/**
- * Create a `CVec` from a foreign buffer, with a given length,
- * and a function to run upon destruction.
- *
- * # Arguments
- *
- * * base - A foreign pointer to a buffer
- * * len - The number of elements in the buffer
- * * dtor - A function to run when the value is destructed, useful
- *          for freeing the buffer, etc.
- */
-pub unsafe fn c_vec_with_dtor<T>(base: *mut T, len: uint, dtor: @fn())
-  -> CVec<T> {
-    return CVec{
-        base: base,
-        len: len,
-        rsrc: @DtorRes(option::Some(dtor))
-    };
-}
-
-/*
- Section: Operations
- */
-
-/**
- * Retrieves an element at a given index
- *
- * Fails if `ofs` is greater or equal to the length of the vector
- */
-pub fn get<T:Copy>(t: CVec<T>, ofs: uint) -> T {
-    assert!(ofs < len(t));
-    return unsafe { *ptr::mut_offset(t.base, ofs) };
-}
-
-/**
- * Sets the value of an element at a given index
- *
- * Fails if `ofs` is greater or equal to the length of the vector
- */
-pub fn set<T:Copy>(t: CVec<T>, ofs: uint, v: T) {
-    assert!(ofs < len(t));
-    unsafe { *ptr::mut_offset(t.base, ofs) = v };
-}
-
-/*
- Section: Elimination forms
- */
-
-/// Returns the length of the vector
-pub fn len<T>(t: CVec<T>) -> uint { t.len }
-
-/// Returns a pointer to the first element of the vector
-pub unsafe fn ptr<T>(t: CVec<T>) -> *mut T { t.base }
-
-#[cfg(test)]
-mod tests {
-
-    use c_vec::*;
-
-    use core::libc::*;
-    use core::libc;
-
-    fn malloc(n: size_t) -> CVec<u8> {
-        unsafe {
-            let mem = libc::malloc(n);
-
-            assert!(mem as int != 0);
-
-            return c_vec_with_dtor(mem as *mut u8, n as uint,
-                                   || unsafe { free(mem) });
-        }
-    }
-
-    #[test]
-    fn test_basic() {
-        let cv = malloc(16u as size_t);
-
-        set(cv, 3u, 8u8);
-        set(cv, 4u, 9u8);
-        assert_eq!(get(cv, 3u), 8u8);
-        assert_eq!(get(cv, 4u), 9u8);
-        assert_eq!(len(cv), 16u);
-    }
-
-    #[test]
-    #[should_fail]
-    #[ignore(cfg(windows))]
-    fn test_overrun_get() {
-        let cv = malloc(16u as size_t);
-
-        get(cv, 17u);
-    }
-
-    #[test]
-    #[should_fail]
-    #[ignore(cfg(windows))]
-    fn test_overrun_set() {
-        let cv = malloc(16u as size_t);
-
-        set(cv, 17u, 0u8);
-    }
-
-    #[test]
-    fn test_and_I_mean_it() {
-        let cv = malloc(16u as size_t);
-        let p = unsafe { ptr(cv) };
-
-        set(cv, 0u, 32u8);
-        set(cv, 1u, 33u8);
-        assert_eq!(unsafe { *p }, 32u8);
-        set(cv, 2u, 34u8); /* safety */
-    }
-
-}
diff --git a/src/libstd/cast.rs b/src/libstd/cast.rs
new file mode 100644
index 00000000000..e3336e24a6e
--- /dev/null
+++ b/src/libstd/cast.rs
@@ -0,0 +1,160 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Unsafe casting functions
+
+use sys;
+use unstable;
+use unstable::intrinsics;
+
+/// Casts the value at `src` to U. The two types must have the same length.
+pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
+    let mut dest: U = intrinsics::init();
+    {
+        let dest_ptr: *mut u8 = transmute(&mut dest);
+        let src_ptr: *u8 = transmute(src);
+        intrinsics::memmove64(dest_ptr,
+                              src_ptr,
+                              sys::size_of::<U>() as u64);
+    }
+    dest
+}
+
+/**
+ * Move a thing into the void
+ *
+ * The forget function will take ownership of the provided value but neglect
+ * to run any required cleanup or memory-management operations on it. This
+ * can be used for various acts of magick, particularly when using
+ * reinterpret_cast on pointer types.
+ */
+#[inline(always)]
+pub unsafe fn forget<T>(thing: T) { intrinsics::forget(thing); }
+
+/**
+ * Force-increment the reference count on a shared box. If used
+ * carelessly, this can leak the box. Use this in conjunction with transmute
+ * and/or reinterpret_cast when such calls would otherwise scramble a box's
+ * reference count
+ */
+pub unsafe fn bump_box_refcount<T>(t: @T) { forget(t); }
+
+/**
+ * Transform a value of one type into a value of another type.
+ * Both types must have the same size and alignment.
+ *
+ * # Example
+ *
+ *     assert!(transmute("L") == ~[76u8, 0u8]);
+ */
+#[inline(always)]
+pub unsafe fn transmute<L, G>(thing: L) -> G {
+    intrinsics::transmute(thing)
+}
+
+/// Coerce an immutable reference to be mutable.
+#[inline(always)]
+pub unsafe fn transmute_mut<'a,T>(ptr: &'a T) -> &'a mut T { transmute(ptr) }
+
+/// Coerce a mutable reference to be immutable.
+#[inline(always)]
+pub unsafe fn transmute_immut<'a,T>(ptr: &'a mut T) -> &'a T {
+    transmute(ptr)
+}
+
+/// Coerce a borrowed pointer to have an arbitrary associated region.
+#[inline(always)]
+pub unsafe fn transmute_region<'a,'b,T>(ptr: &'a T) -> &'b T {
+    transmute(ptr)
+}
+
+/// Coerce an immutable reference to be mutable.
+#[inline(always)]
+pub unsafe fn transmute_mut_unsafe<T>(ptr: *const T) -> *mut T {
+    transmute(ptr)
+}
+
+/// Coerce an immutable reference to be mutable.
+#[inline(always)]
+pub unsafe fn transmute_immut_unsafe<T>(ptr: *const T) -> *T {
+    transmute(ptr)
+}
+
+/// Coerce a borrowed mutable pointer to have an arbitrary associated region.
+#[inline(always)]
+pub unsafe fn transmute_mut_region<'a,'b,T>(ptr: &'a mut T) -> &'b mut T {
+    transmute(ptr)
+}
+
+/// Transforms lifetime of the second pointer to match the first.
+#[inline(always)]
+pub unsafe fn copy_lifetime<'a,S,T>(_ptr: &'a S, ptr: &T) -> &'a T {
+    transmute_region(ptr)
+}
+
+/// Transforms lifetime of the second pointer to match the first.
+#[inline(always)]
+pub unsafe fn copy_mut_lifetime<'a,S,T>(_ptr: &'a mut S, ptr: &mut T) -> &'a mut T {
+    transmute_mut_region(ptr)
+}
+
+/// Transforms lifetime of the second pointer to match the first.
+#[inline(always)]
+pub unsafe fn copy_lifetime_vec<'a,S,T>(_ptr: &'a [S], ptr: &T) -> &'a T {
+    transmute_region(ptr)
+}
+
+
+/****************************************************************************
+ * Tests
+ ****************************************************************************/
+
+#[cfg(test)]
+mod tests {
+    use cast::{bump_box_refcount, transmute};
+
+    #[test]
+    fn test_transmute_copy() {
+        assert_eq!(1u, unsafe { ::cast::transmute_copy(&1) });
+    }
+
+    #[test]
+    fn test_bump_box_refcount() {
+        unsafe {
+            let box = @~"box box box";       // refcount 1
+            bump_box_refcount(box);         // refcount 2
+            let ptr: *int = transmute(box); // refcount 2
+            let _box1: @~str = ::cast::transmute_copy(&ptr);
+            let _box2: @~str = ::cast::transmute_copy(&ptr);
+            assert!(*_box1 == ~"box box box");
+            assert!(*_box2 == ~"box box box");
+            // Will destroy _box1 and _box2. Without the bump, this would
+            // use-after-free. With too many bumps, it would leak.
+        }
+    }
+
+    #[test]
+    fn test_transmute() {
+        use managed::raw::BoxRepr;
+        unsafe {
+            let x = @100u8;
+            let x: *BoxRepr = transmute(x);
+            assert!((*x).data == 100);
+            let _x: @int = transmute(x);
+        }
+    }
+
+    #[test]
+    fn test_transmute2() {
+        unsafe {
+            assert_eq!(~[76u8, 0u8], transmute(~"L"));
+        }
+    }
+}
diff --git a/src/libstd/cell.rs b/src/libstd/cell.rs
new file mode 100644
index 00000000000..b707e3bbb9e
--- /dev/null
+++ b/src/libstd/cell.rs
@@ -0,0 +1,136 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! A mutable, nullable memory location
+
+use cast::transmute_mut;
+use prelude::*;
+use util::replace;
+
+/*
+A dynamic, mutable location.
+
+Similar to a mutable option type, but friendlier.
+*/
+
+#[mutable]
+#[deriving(Clone)]
+pub struct Cell<T> {
+    priv value: Option<T>
+}
+
+impl<T: DeepClone> DeepClone for Cell<T> {
+    fn deep_clone(&self) -> Cell<T> {
+        Cell{value: self.value.deep_clone()}
+    }
+}
+
+impl<T:cmp::Eq> cmp::Eq for Cell<T> {
+    fn eq(&self, other: &Cell<T>) -> bool {
+        (self.value) == (other.value)
+    }
+    fn ne(&self, other: &Cell<T>) -> bool { !self.eq(other) }
+}
+
+/// Creates a new full cell with the given value.
+pub fn Cell<T>(value: T) -> Cell<T> {
+    Cell { value: Some(value) }
+}
+
+pub fn empty_cell<T>() -> Cell<T> {
+    Cell { value: None }
+}
+
+pub impl<T> Cell<T> {
+    /// Yields the value, failing if the cell is empty.
+    fn take(&self) -> T {
+        let this = unsafe { transmute_mut(self) };
+        if this.is_empty() {
+            fail!("attempt to take an empty cell");
+        }
+
+        replace(&mut this.value, None).unwrap()
+    }
+
+    /// Returns the value, failing if the cell is full.
+    fn put_back(&self, value: T) {
+        let this = unsafe { transmute_mut(self) };
+        if !this.is_empty() {
+            fail!("attempt to put a value back into a full cell");
+        }
+        this.value = Some(value);
+    }
+
+    /// Returns true if the cell is empty and false if the cell is full.
+    fn is_empty(&self) -> bool {
+        self.value.is_none()
+    }
+
+    // Calls a closure with a reference to the value.
+    fn with_ref<R>(&self, op: &fn(v: &T) -> R) -> R {
+        let v = self.take();
+        let r = op(&v);
+        self.put_back(v);
+        r
+    }
+
+    // Calls a closure with a mutable reference to the value.
+    fn with_mut_ref<R>(&self, op: &fn(v: &mut T) -> R) -> R {
+        let mut v = self.take();
+        let r = op(&mut v);
+        self.put_back(v);
+        r
+    }
+}
+
+#[test]
+fn test_basic() {
+    let value_cell = Cell(~10);
+    assert!(!value_cell.is_empty());
+    let value = value_cell.take();
+    assert!(value == ~10);
+    assert!(value_cell.is_empty());
+    value_cell.put_back(value);
+    assert!(!value_cell.is_empty());
+}
+
+#[test]
+#[should_fail]
+#[ignore(cfg(windows))]
+fn test_take_empty() {
+    let value_cell = empty_cell::<~int>();
+    value_cell.take();
+}
+
+#[test]
+#[should_fail]
+#[ignore(cfg(windows))]
+fn test_put_back_non_empty() {
+    let value_cell = Cell(~10);
+    value_cell.put_back(~20);
+}
+
+#[test]
+fn test_with_ref() {
+    let good = 6;
+    let c = Cell(~[1, 2, 3, 4, 5, 6]);
+    let l = do c.with_ref() |v| { v.len() };
+    assert_eq!(l, good);
+}
+
+#[test]
+fn test_with_mut_ref() {
+    let good = ~[1, 2, 3];
+    let v = ~[1, 2];
+    let c = Cell(v);
+    do c.with_mut_ref() |v| { v.push(3); }
+    let v = c.take();
+    assert_eq!(v, good);
+}
diff --git a/src/libstd/char.rs b/src/libstd/char.rs
new file mode 100644
index 00000000000..bd70f59212d
--- /dev/null
+++ b/src/libstd/char.rs
@@ -0,0 +1,406 @@
+// 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.
+
+//! Utilities for manipulating the char type
+
+use option::{None, Option, Some};
+use str;
+use str::{StrSlice, OwnedStr};
+use u32;
+use uint;
+use unicode::{derived_property, general_category};
+
+#[cfg(not(test))]
+use cmp::{Eq, Ord};
+
+/*
+    Lu  Uppercase_Letter        an uppercase letter
+    Ll  Lowercase_Letter        a lowercase letter
+    Lt  Titlecase_Letter        a digraphic character, with first part uppercase
+    Lm  Modifier_Letter         a modifier letter
+    Lo  Other_Letter            other letters, including syllables and ideographs
+    Mn  Nonspacing_Mark         a nonspacing combining mark (zero advance width)
+    Mc  Spacing_Mark            a spacing combining mark (positive advance width)
+    Me  Enclosing_Mark          an enclosing combining mark
+    Nd  Decimal_Number          a decimal digit
+    Nl  Letter_Number           a letterlike numeric character
+    No  Other_Number            a numeric character of other type
+    Pc  Connector_Punctuation   a connecting punctuation mark, like a tie
+    Pd  Dash_Punctuation        a dash or hyphen punctuation mark
+    Ps  Open_Punctuation        an opening punctuation mark (of a pair)
+    Pe  Close_Punctuation       a closing punctuation mark (of a pair)
+    Pi  Initial_Punctuation     an initial quotation mark
+    Pf  Final_Punctuation       a final quotation mark
+    Po  Other_Punctuation       a punctuation mark of other type
+    Sm  Math_Symbol             a symbol of primarily mathematical use
+    Sc  Currency_Symbol         a currency sign
+    Sk  Modifier_Symbol         a non-letterlike modifier symbol
+    So  Other_Symbol            a symbol of other type
+    Zs  Space_Separator         a space character (of various non-zero widths)
+    Zl  Line_Separator          U+2028 LINE SEPARATOR only
+    Zp  Paragraph_Separator     U+2029 PARAGRAPH SEPARATOR only
+    Cc  Control                 a C0 or C1 control code
+    Cf  Format                  a format control character
+    Cs  Surrogate               a surrogate code point
+    Co  Private_Use             a private-use character
+    Cn  Unassigned              a reserved unassigned code point or a noncharacter
+*/
+
+pub fn is_alphabetic(c: char) -> bool   { derived_property::Alphabetic(c) }
+pub fn is_XID_start(c: char) -> bool    { derived_property::XID_Start(c) }
+pub fn is_XID_continue(c: char) -> bool { derived_property::XID_Continue(c) }
+
+///
+/// Indicates whether a character is in lower case, defined
+/// in terms of the Unicode General Category 'Ll'
+///
+#[inline(always)]
+pub fn is_lowercase(c: char) -> bool { general_category::Ll(c) }
+
+///
+/// Indicates whether a character is in upper case, defined
+/// in terms of the Unicode General Category 'Lu'.
+///
+#[inline(always)]
+pub fn is_uppercase(c: char) -> bool { general_category::Lu(c) }
+
+///
+/// Indicates whether a character is whitespace. Whitespace is defined in
+/// terms of the Unicode General Categories 'Zs', 'Zl', 'Zp'
+/// additional 'Cc'-category control codes in the range [0x09, 0x0d]
+///
+#[inline(always)]
+pub fn is_whitespace(c: char) -> bool {
+    ('\x09' <= c && c <= '\x0d')
+        || general_category::Zs(c)
+        || general_category::Zl(c)
+        || general_category::Zp(c)
+}
+
+///
+/// Indicates whether a character is alphanumeric. Alphanumericness is
+/// defined in terms of the Unicode General Categories 'Nd', 'Nl', 'No'
+/// and the Derived Core Property 'Alphabetic'.
+///
+#[inline(always)]
+pub fn is_alphanumeric(c: char) -> bool {
+    derived_property::Alphabetic(c)
+        || general_category::Nd(c)
+        || general_category::Nl(c)
+        || general_category::No(c)
+}
+
+/// Indicates whether the character is numeric (Nd, Nl, or No)
+#[inline(always)]
+pub fn is_digit(c: char) -> bool {
+    general_category::Nd(c)
+        || general_category::Nl(c)
+        || general_category::No(c)
+}
+
+///
+/// Checks if a character parses as a numeric digit in the given radix.
+/// Compared to `is_digit()`, this function only recognizes the
+/// characters `0-9`, `a-z` and `A-Z`.
+///
+/// # Return value
+///
+/// Returns `true` if `c` is a valid digit under `radix`, and `false`
+/// otherwise.
+///
+/// # Failure
+///
+/// Fails if given a `radix` > 36.
+///
+/// # Note
+///
+/// This just wraps `to_digit()`.
+///
+#[inline(always)]
+pub fn is_digit_radix(c: char, radix: uint) -> bool {
+    match to_digit(c, radix) {
+        Some(_) => true,
+        None    => false,
+    }
+}
+
+///
+/// Convert a char to the corresponding digit.
+///
+/// # Return value
+///
+/// If `c` is between '0' and '9', the corresponding value
+/// between 0 and 9. If `c` is 'a' or 'A', 10. If `c` is
+/// 'b' or 'B', 11, etc. Returns none if the char does not
+/// refer to a digit in the given radix.
+///
+/// # Failure
+///
+/// Fails if given a `radix` outside the range `[0..36]`.
+///
+#[inline]
+pub fn to_digit(c: char, radix: uint) -> Option<uint> {
+    if radix > 36 {
+        fail!("to_digit: radix %? is to high (maximum 36)", radix);
+    }
+    let val = match c {
+      '0' .. '9' => c as uint - ('0' as uint),
+      'a' .. 'z' => c as uint + 10u - ('a' as uint),
+      'A' .. 'Z' => c as uint + 10u - ('A' as uint),
+      _ => return None,
+    };
+    if val < radix { Some(val) }
+    else { None }
+}
+
+///
+/// Converts a number to the character representing it.
+///
+/// # Return value
+///
+/// Returns `Some(char)` if `num` represents one digit under `radix`,
+/// using one character of `0-9` or `a-z`, or `None` if it doesn't.
+///
+/// # Failure
+///
+/// Fails if given an `radix` > 36.
+///
+#[inline]
+pub fn from_digit(num: uint, radix: uint) -> Option<char> {
+    if radix > 36 {
+        fail!("from_digit: radix %? is to high (maximum 36)", num);
+    }
+    if num < radix {
+        if num < 10 {
+            Some(('0' as uint + num) as char)
+        } else {
+            Some(('a' as uint + num - 10u) as char)
+        }
+    } else {
+        None
+    }
+}
+
+///
+/// Return the hexadecimal unicode escape of a char.
+///
+/// The rules are as follows:
+///
+/// - chars in [0,0xff] get 2-digit escapes: `\\xNN`
+/// - chars in [0x100,0xffff] get 4-digit escapes: `\\uNNNN`
+/// - chars above 0x10000 get 8-digit escapes: `\\UNNNNNNNN`
+///
+pub fn escape_unicode(c: char) -> ~str {
+    let s = u32::to_str_radix(c as u32, 16u);
+    let (c, pad) = cond!(
+        (c <= '\xff')   { ('x', 2u) }
+        (c <= '\uffff') { ('u', 4u) }
+        _               { ('U', 8u) }
+    );
+    assert!(s.len() <= pad);
+    let mut out = ~"\\";
+    out.push_str(str::from_char(c));
+    for uint::range(s.len(), pad) |_| {
+        out.push_str("0");
+    }
+    out.push_str(s);
+    out
+}
+
+///
+/// Return a 'default' ASCII and C++11-like char-literal escape of a char.
+///
+/// The default is chosen with a bias toward producing literals that are
+/// legal in a variety of languages, including C++11 and similar C-family
+/// languages. The exact rules are:
+///
+/// - Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
+/// - Single-quote, double-quote and backslash chars are backslash-escaped.
+/// - Any other chars in the range [0x20,0x7e] are not escaped.
+/// - Any other chars are given hex unicode escapes; see `escape_unicode`.
+///
+pub fn escape_default(c: char) -> ~str {
+    match c {
+        '\t' => ~"\\t",
+        '\r' => ~"\\r",
+        '\n' => ~"\\n",
+        '\\' => ~"\\\\",
+        '\'' => ~"\\'",
+        '"'  => ~"\\\"",
+        '\x20' .. '\x7e' => str::from_char(c),
+        _ => c.escape_unicode(),
+    }
+}
+
+/// Returns the amount of bytes this character would need if encoded in utf8
+pub fn len_utf8_bytes(c: char) -> uint {
+    static MAX_ONE_B:   uint = 128u;
+    static MAX_TWO_B:   uint = 2048u;
+    static MAX_THREE_B: uint = 65536u;
+    static MAX_FOUR_B:  uint = 2097152u;
+
+    let code = c as uint;
+    cond!(
+        (code < MAX_ONE_B)   { 1u }
+        (code < MAX_TWO_B)   { 2u }
+        (code < MAX_THREE_B) { 3u }
+        (code < MAX_FOUR_B)  { 4u }
+        _ { fail!("invalid character!") }
+    )
+}
+
+pub trait Char {
+    fn is_alphabetic(&self) -> bool;
+    fn is_XID_start(&self) -> bool;
+    fn is_XID_continue(&self) -> bool;
+    fn is_lowercase(&self) -> bool;
+    fn is_uppercase(&self) -> bool;
+    fn is_whitespace(&self) -> bool;
+    fn is_alphanumeric(&self) -> bool;
+    fn is_digit(&self) -> bool;
+    fn is_digit_radix(&self, radix: uint) -> bool;
+    fn to_digit(&self, radix: uint) -> Option<uint>;
+    fn from_digit(num: uint, radix: uint) -> Option<char>;
+    fn escape_unicode(&self) -> ~str;
+    fn escape_default(&self) -> ~str;
+    fn len_utf8_bytes(&self) -> uint;
+}
+
+impl Char for char {
+    fn is_alphabetic(&self) -> bool { is_alphabetic(*self) }
+
+    fn is_XID_start(&self) -> bool { is_XID_start(*self) }
+
+    fn is_XID_continue(&self) -> bool { is_XID_continue(*self) }
+
+    fn is_lowercase(&self) -> bool { is_lowercase(*self) }
+
+    fn is_uppercase(&self) -> bool { is_uppercase(*self) }
+
+    fn is_whitespace(&self) -> bool { is_whitespace(*self) }
+
+    fn is_alphanumeric(&self) -> bool { is_alphanumeric(*self) }
+
+    fn is_digit(&self) -> bool { is_digit(*self) }
+
+    fn is_digit_radix(&self, radix: uint) -> bool { is_digit_radix(*self, radix) }
+
+    fn to_digit(&self, radix: uint) -> Option<uint> { to_digit(*self, radix) }
+
+    fn from_digit(num: uint, radix: uint) -> Option<char> { from_digit(num, radix) }
+
+    fn escape_unicode(&self) -> ~str { escape_unicode(*self) }
+
+    fn escape_default(&self) -> ~str { escape_default(*self) }
+
+    fn len_utf8_bytes(&self) -> uint { len_utf8_bytes(*self) }
+}
+
+#[cfg(not(test))]
+impl Eq for char {
+    #[inline(always)]
+    fn eq(&self, other: &char) -> bool { (*self) == (*other) }
+    #[inline(always)]
+    fn ne(&self, other: &char) -> bool { (*self) != (*other) }
+}
+
+#[cfg(not(test))]
+impl Ord for char {
+    #[inline(always)]
+    fn lt(&self, other: &char) -> bool { *self < *other }
+    #[inline(always)]
+    fn le(&self, other: &char) -> bool { *self <= *other }
+    #[inline(always)]
+    fn gt(&self, other: &char) -> bool { *self > *other }
+    #[inline(always)]
+    fn ge(&self, other: &char) -> bool { *self >= *other }
+}
+
+#[test]
+fn test_is_lowercase() {
+    assert!('a'.is_lowercase());
+    assert!('ö'.is_lowercase());
+    assert!('ß'.is_lowercase());
+    assert!(!'Ü'.is_lowercase());
+    assert!(!'P'.is_lowercase());
+}
+
+#[test]
+fn test_is_uppercase() {
+    assert!(!'h'.is_uppercase());
+    assert!(!'ä'.is_uppercase());
+    assert!(!'ß'.is_uppercase());
+    assert!('Ö'.is_uppercase());
+    assert!('T'.is_uppercase());
+}
+
+#[test]
+fn test_is_whitespace() {
+    assert!(' '.is_whitespace());
+    assert!('\u2007'.is_whitespace());
+    assert!('\t'.is_whitespace());
+    assert!('\n'.is_whitespace());
+    assert!(!'a'.is_whitespace());
+    assert!(!'_'.is_whitespace());
+    assert!(!'\u0000'.is_whitespace());
+}
+
+#[test]
+fn test_to_digit() {
+    assert_eq!('0'.to_digit(10u), Some(0u));
+    assert_eq!('1'.to_digit(2u), Some(1u));
+    assert_eq!('2'.to_digit(3u), Some(2u));
+    assert_eq!('9'.to_digit(10u), Some(9u));
+    assert_eq!('a'.to_digit(16u), Some(10u));
+    assert_eq!('A'.to_digit(16u), Some(10u));
+    assert_eq!('b'.to_digit(16u), Some(11u));
+    assert_eq!('B'.to_digit(16u), Some(11u));
+    assert_eq!('z'.to_digit(36u), Some(35u));
+    assert_eq!('Z'.to_digit(36u), Some(35u));
+    assert_eq!(' '.to_digit(10u), None);
+    assert_eq!('$'.to_digit(36u), None);
+}
+
+#[test]
+fn test_is_digit() {
+   assert!('2'.is_digit());
+   assert!('7'.is_digit());
+   assert!(!'c'.is_digit());
+   assert!(!'i'.is_digit());
+   assert!(!'z'.is_digit());
+   assert!(!'Q'.is_digit());
+}
+
+#[test]
+fn test_escape_default() {
+    assert_eq!('\n'.escape_default(), ~"\\n");
+    assert_eq!('\r'.escape_default(), ~"\\r");
+    assert_eq!('\''.escape_default(), ~"\\'");
+    assert_eq!('"'.escape_default(), ~"\\\"");
+    assert_eq!(' '.escape_default(), ~" ");
+    assert_eq!('a'.escape_default(), ~"a");
+    assert_eq!('~'.escape_default(), ~"~");
+    assert_eq!('\x00'.escape_default(), ~"\\x00");
+    assert_eq!('\x1f'.escape_default(), ~"\\x1f");
+    assert_eq!('\x7f'.escape_default(), ~"\\x7f");
+    assert_eq!('\xff'.escape_default(), ~"\\xff");
+    assert_eq!('\u011b'.escape_default(), ~"\\u011b");
+    assert_eq!('\U0001d4b6'.escape_default(), ~"\\U0001d4b6");
+}
+
+#[test]
+fn test_escape_unicode() {
+    assert_eq!('\x00'.escape_unicode(), ~"\\x00");
+    assert_eq!('\n'.escape_unicode(), ~"\\x0a");
+    assert_eq!(' '.escape_unicode(), ~"\\x20");
+    assert_eq!('a'.escape_unicode(), ~"\\x61");
+    assert_eq!('\u011b'.escape_unicode(), ~"\\u011b");
+    assert_eq!('\U0001d4b6'.escape_unicode(), ~"\\U0001d4b6");
+}
diff --git a/src/libstd/cleanup.rs b/src/libstd/cleanup.rs
new file mode 100644
index 00000000000..5796be7b1e4
--- /dev/null
+++ b/src/libstd/cleanup.rs
@@ -0,0 +1,253 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[doc(hidden)];
+
+use libc::{c_char, c_void, intptr_t, uintptr_t};
+use ptr::mut_null;
+use repr::BoxRepr;
+use sys::TypeDesc;
+use cast::transmute;
+#[cfg(not(test))] use unstable::lang::clear_task_borrow_list;
+
+#[cfg(not(test))] use ptr::to_unsafe_ptr;
+
+/**
+ * Runtime structures
+ *
+ * NB: These must match the representation in the C++ runtime.
+ */
+
+type DropGlue<'self> = &'self fn(**TypeDesc, *c_void);
+type FreeGlue<'self> = &'self fn(**TypeDesc, *c_void);
+
+type TaskID = uintptr_t;
+
+struct StackSegment { priv opaque: () }
+struct Scheduler { priv opaque: () }
+struct SchedulerLoop { priv opaque: () }
+struct Kernel { priv opaque: () }
+struct Env { priv opaque: () }
+struct AllocHeader { priv opaque: () }
+struct MemoryRegion { priv opaque: () }
+
+#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
+struct Registers {
+    data: [u32, ..16]
+}
+
+#[cfg(target_arch="mips")]
+struct Registers {
+    data: [u32, ..32]
+}
+
+#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
+#[cfg(target_arch="mips")]
+struct Context {
+    regs: Registers,
+    next: *Context,
+    pad: [u32, ..3]
+}
+
+#[cfg(target_arch="x86_64")]
+struct Registers {
+    data: [u64, ..22]
+}
+
+#[cfg(target_arch="x86_64")]
+struct Context {
+    regs: Registers,
+    next: *Context,
+    pad: uintptr_t
+}
+
+struct BoxedRegion {
+    env: *Env,
+    backing_region: *MemoryRegion,
+    live_allocs: *BoxRepr
+}
+
+#[cfg(target_arch="x86")]
+#[cfg(target_arch="arm")]
+#[cfg(target_arch="mips")]
+struct Task {
+    // Public fields
+    refcount: intptr_t,                 // 0
+    id: TaskID,                         // 4
+    pad: [u32, ..2],                    // 8
+    ctx: Context,                       // 16
+    stack_segment: *StackSegment,       // 96
+    runtime_sp: uintptr_t,              // 100
+    scheduler: *Scheduler,              // 104
+    scheduler_loop: *SchedulerLoop,     // 108
+
+    // Fields known only to the runtime
+    kernel: *Kernel,                    // 112
+    name: *c_char,                      // 116
+    list_index: i32,                    // 120
+    boxed_region: BoxedRegion           // 128
+}
+
+#[cfg(target_arch="x86_64")]
+struct Task {
+    // Public fields
+    refcount: intptr_t,
+    id: TaskID,
+    ctx: Context,
+    stack_segment: *StackSegment,
+    runtime_sp: uintptr_t,
+    scheduler: *Scheduler,
+    scheduler_loop: *SchedulerLoop,
+
+    // Fields known only to the runtime
+    kernel: *Kernel,
+    name: *c_char,
+    list_index: i32,
+    boxed_region: BoxedRegion
+}
+
+/*
+ * Box annihilation
+ *
+ * This runs at task death to free all boxes.
+ */
+
+struct AnnihilateStats {
+    n_total_boxes: uint,
+    n_unique_boxes: uint,
+    n_bytes_freed: uint
+}
+
+unsafe fn each_live_alloc(read_next_before: bool,
+                          f: &fn(box: *mut BoxRepr, uniq: bool) -> bool) -> bool {
+    //! Walks the internal list of allocations
+
+    use managed;
+
+    let task: *Task = transmute(rustrt::rust_get_task());
+    let box = (*task).boxed_region.live_allocs;
+    let mut box: *mut BoxRepr = transmute(copy box);
+    while box != mut_null() {
+        let next_before = transmute(copy (*box).header.next);
+        let uniq =
+            (*box).header.ref_count == managed::raw::RC_MANAGED_UNIQUE;
+
+        if !f(box, uniq) {
+            return false;
+        }
+
+        if read_next_before {
+            box = next_before;
+        } else {
+            box = transmute(copy (*box).header.next);
+        }
+    }
+    return true;
+}
+
+#[cfg(unix)]
+fn debug_mem() -> bool {
+    ::rt::env::get().debug_mem
+}
+
+#[cfg(windows)]
+fn debug_mem() -> bool {
+    false
+}
+
+/// Destroys all managed memory (i.e. @ boxes) held by the current task.
+#[cfg(not(test))]
+#[lang="annihilate"]
+pub unsafe fn annihilate() {
+    use unstable::lang::local_free;
+    use io::WriterUtil;
+    use io;
+    use libc;
+    use sys;
+    use managed;
+
+    let mut stats = AnnihilateStats {
+        n_total_boxes: 0,
+        n_unique_boxes: 0,
+        n_bytes_freed: 0
+    };
+
+    // Quick hack: we need to free this list upon task exit, and this
+    // is a convenient place to do it.
+    clear_task_borrow_list();
+
+    // Pass 1: Make all boxes immortal.
+    //
+    // In this pass, nothing gets freed, so it does not matter whether
+    // we read the next field before or after the callback.
+    for each_live_alloc(true) |box, uniq| {
+        stats.n_total_boxes += 1;
+        if uniq {
+            stats.n_unique_boxes += 1;
+        } else {
+            (*box).header.ref_count = managed::raw::RC_IMMORTAL;
+        }
+    }
+
+    // Pass 2: Drop all boxes.
+    //
+    // In this pass, unique-managed boxes may get freed, but not
+    // managed boxes, so we must read the `next` field *after* the
+    // callback, as the original value may have been freed.
+    for each_live_alloc(false) |box, uniq| {
+        if !uniq {
+            let tydesc: *TypeDesc = transmute(copy (*box).header.type_desc);
+            let drop_glue: DropGlue = transmute(((*tydesc).drop_glue, 0));
+            drop_glue(to_unsafe_ptr(&tydesc), transmute(&(*box).data));
+        }
+    }
+
+    // Pass 3: Free all boxes.
+    //
+    // In this pass, managed boxes may get freed (but not
+    // unique-managed boxes, though I think that none of those are
+    // left), so we must read the `next` field before, since it will
+    // not be valid after.
+    for each_live_alloc(true) |box, uniq| {
+        if !uniq {
+            stats.n_bytes_freed +=
+                (*((*box).header.type_desc)).size
+                + sys::size_of::<BoxRepr>();
+            local_free(transmute(box));
+        }
+    }
+
+    if debug_mem() {
+        // We do logging here w/o allocation.
+        let dbg = libc::STDERR_FILENO as io::fd_t;
+        dbg.write_str("annihilator stats:");
+        dbg.write_str("\n  total_boxes: ");
+        dbg.write_uint(stats.n_total_boxes);
+        dbg.write_str("\n  unique_boxes: ");
+        dbg.write_uint(stats.n_unique_boxes);
+        dbg.write_str("\n  bytes_freed: ");
+        dbg.write_uint(stats.n_bytes_freed);
+        dbg.write_str("\n");
+    }
+}
+
+/// Bindings to the runtime
+pub mod rustrt {
+    use libc::c_void;
+
+    #[link_name = "rustrt"]
+    pub extern {
+        #[rust_stack]
+        // FIXME (#4386): Unable to make following method private.
+        pub unsafe fn rust_get_task() -> *c_void;
+    }
+}
diff --git a/src/libstd/clone.rs b/src/libstd/clone.rs
new file mode 100644
index 00000000000..2965b31a8c3
--- /dev/null
+++ b/src/libstd/clone.rs
@@ -0,0 +1,184 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*! The Clone trait for types that cannot be "implicitly copied"
+
+In Rust, some simple types are "implicitly copyable" and when you
+assign them or pass them as arguments, the receiver will get a copy,
+leaving the original value in place. These types do not require
+allocation to copy and do not have finalizers (i.e. they do not
+contain owned boxes or implement `Drop`), so the compiler considers
+them cheap and safe to copy and automatically implements the `Copy`
+trait for them. For other types copies must be made explicitly,
+by convention implementing the `Clone` trait and calling the
+`clone` method.
+
+*/
+
+use core::kinds::Const;
+
+pub trait Clone {
+    /// Returns a copy of the value. The contents of owned pointers
+    /// are copied to maintain uniqueness, while the contents of
+    /// managed pointers are not copied.
+    fn clone(&self) -> Self;
+}
+
+impl<T: Clone> Clone for ~T {
+    /// Return a deep copy of the owned box.
+    #[inline(always)]
+    fn clone(&self) -> ~T { ~(**self).clone() }
+}
+
+impl<T> Clone for @T {
+    /// Return a shallow copy of the managed box.
+    #[inline(always)]
+    fn clone(&self) -> @T { *self }
+}
+
+impl<T> Clone for @mut T {
+    /// Return a shallow copy of the managed box.
+    #[inline(always)]
+    fn clone(&self) -> @mut T { *self }
+}
+
+impl<'self, T> Clone for &'self T {
+    /// Return a shallow copy of the borrowed pointer.
+    #[inline(always)]
+    fn clone(&self) -> &'self T { *self }
+}
+
+macro_rules! clone_impl(
+    ($t:ty) => {
+        impl Clone for $t {
+            /// Return a deep copy of the value.
+            #[inline(always)]
+            fn clone(&self) -> $t { *self }
+        }
+    }
+)
+
+clone_impl!(int)
+clone_impl!(i8)
+clone_impl!(i16)
+clone_impl!(i32)
+clone_impl!(i64)
+
+clone_impl!(uint)
+clone_impl!(u8)
+clone_impl!(u16)
+clone_impl!(u32)
+clone_impl!(u64)
+
+clone_impl!(float)
+clone_impl!(f32)
+clone_impl!(f64)
+
+clone_impl!(())
+clone_impl!(bool)
+clone_impl!(char)
+
+pub trait DeepClone {
+    /// Return a deep copy of the value. Unlike `Clone`, the contents of shared pointer types
+    /// *are* copied. Note that this is currently unimplemented for managed boxes, as
+    /// it would need to handle cycles, but it is implemented for other smart-pointer types.
+    fn deep_clone(&self) -> Self;
+}
+
+impl<T: DeepClone> DeepClone for ~T {
+    /// Return a deep copy of the owned box.
+    #[inline(always)]
+    fn deep_clone(&self) -> ~T { ~(**self).deep_clone() }
+}
+
+// FIXME: #6525: should also be implemented for `T: Owned + DeepClone`
+impl<T: Const + DeepClone> DeepClone for @T {
+    /// Return a deep copy of the managed box. The `Const` trait is required to prevent performing
+    /// a deep clone of a potentially cyclical type.
+    #[inline(always)]
+    fn deep_clone(&self) -> @T { @(**self).deep_clone() }
+}
+
+// FIXME: #6525: should also be implemented for `T: Owned + DeepClone`
+impl<T: Const + DeepClone> DeepClone for @mut T {
+    /// Return a deep copy of the managed box. The `Const` trait is required to prevent performing
+    /// a deep clone of a potentially cyclical type.
+    #[inline(always)]
+    fn deep_clone(&self) -> @mut T { @mut (**self).deep_clone() }
+}
+
+macro_rules! deep_clone_impl(
+    ($t:ty) => {
+        impl DeepClone for $t {
+            /// Return a deep copy of the value.
+            #[inline(always)]
+            fn deep_clone(&self) -> $t { *self }
+        }
+    }
+)
+
+deep_clone_impl!(int)
+deep_clone_impl!(i8)
+deep_clone_impl!(i16)
+deep_clone_impl!(i32)
+deep_clone_impl!(i64)
+
+deep_clone_impl!(uint)
+deep_clone_impl!(u8)
+deep_clone_impl!(u16)
+deep_clone_impl!(u32)
+deep_clone_impl!(u64)
+
+deep_clone_impl!(float)
+deep_clone_impl!(f32)
+deep_clone_impl!(f64)
+
+deep_clone_impl!(())
+deep_clone_impl!(bool)
+deep_clone_impl!(char)
+
+#[test]
+fn test_owned_clone() {
+    let a = ~5i;
+    let b: ~int = a.clone();
+    assert_eq!(a, b);
+}
+
+#[test]
+fn test_managed_clone() {
+    let a = @5i;
+    let b: @int = a.clone();
+    assert_eq!(a, b);
+}
+
+#[test]
+fn test_managed_mut_deep_clone() {
+    let x = @mut 5i;
+    let y: @mut int = x.deep_clone();
+    *x = 20;
+    assert_eq!(*y, 5);
+}
+
+#[test]
+fn test_managed_mut_clone() {
+    let a = @mut 5i;
+    let b: @mut int = a.clone();
+    assert_eq!(a, b);
+    *b = 10;
+    assert_eq!(a, b);
+}
+
+#[test]
+fn test_borrowed_clone() {
+    let x = 5i;
+    let y: &int = &x;
+    let z: &int = (&y).clone();
+    assert_eq!(*z, 5);
+}
diff --git a/src/libstd/cmp.rs b/src/libstd/cmp.rs
new file mode 100644
index 00000000000..ca9c49b2c06
--- /dev/null
+++ b/src/libstd/cmp.rs
@@ -0,0 +1,265 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+The `Ord` and `Eq` comparison traits
+
+This module contains the definition of both `Ord` and `Eq` which define
+the common interfaces for doing comparison. Both are language items
+that the compiler uses to implement the comparison operators. Rust code
+may implement `Ord` to overload the `<`, `<=`, `>`, and `>=` operators,
+and `Eq` to overload the `==` and `!=` operators.
+
+*/
+
+/**
+* Trait for values that can be compared for equality and inequality.
+*
+* This trait allows partial equality, where types can be unordered instead of strictly equal or
+* unequal. For example, with the built-in floating-point types `a == b` and `a != b` will both
+* evaluate to false if either `a` or `b` is NaN (cf. IEEE 754-2008 section 5.11).
+*
+* Eventually, this will be implemented by default for types that implement `TotalEq`.
+*/
+#[lang="eq"]
+pub trait Eq {
+    fn eq(&self, other: &Self) -> bool;
+    fn ne(&self, other: &Self) -> bool;
+}
+
+/// Trait for equality comparisons where `a == b` and `a != b` are strict inverses.
+pub trait TotalEq {
+    fn equals(&self, other: &Self) -> bool;
+}
+
+macro_rules! totaleq_impl(
+    ($t:ty) => {
+        impl TotalEq for $t {
+            #[inline(always)]
+            fn equals(&self, other: &$t) -> bool { *self == *other }
+        }
+    }
+)
+
+totaleq_impl!(bool)
+
+totaleq_impl!(u8)
+totaleq_impl!(u16)
+totaleq_impl!(u32)
+totaleq_impl!(u64)
+
+totaleq_impl!(i8)
+totaleq_impl!(i16)
+totaleq_impl!(i32)
+totaleq_impl!(i64)
+
+totaleq_impl!(int)
+totaleq_impl!(uint)
+
+totaleq_impl!(char)
+
+/// Trait for testing approximate equality
+pub trait ApproxEq<Eps> {
+    fn approx_epsilon() -> Eps;
+    fn approx_eq(&self, other: &Self) -> bool;
+    fn approx_eq_eps(&self, other: &Self, approx_epsilon: &Eps) -> bool;
+}
+
+#[deriving(Clone, Eq)]
+pub enum Ordering { Less = -1, Equal = 0, Greater = 1 }
+
+/// Trait for types that form a total order
+pub trait TotalOrd: TotalEq {
+    fn cmp(&self, other: &Self) -> Ordering;
+}
+
+impl TotalOrd for Ordering {
+    #[inline(always)]
+    fn cmp(&self, other: &Ordering) -> Ordering {
+        (*self as int).cmp(&(*other as int))
+    }
+}
+
+impl Ord for Ordering {
+    #[inline(always)]
+    fn lt(&self, other: &Ordering) -> bool { (*self as int) < (*other as int) }
+    #[inline(always)]
+    fn le(&self, other: &Ordering) -> bool { (*self as int) <= (*other as int) }
+    #[inline(always)]
+    fn gt(&self, other: &Ordering) -> bool { (*self as int) > (*other as int) }
+    #[inline(always)]
+    fn ge(&self, other: &Ordering) -> bool { (*self as int) >= (*other as int) }
+}
+
+macro_rules! totalord_impl(
+    ($t:ty) => {
+        impl TotalOrd for $t {
+            #[inline(always)]
+            fn cmp(&self, other: &$t) -> Ordering {
+                if *self < *other { Less }
+                else if *self > *other { Greater }
+                else { Equal }
+            }
+        }
+    }
+)
+
+totalord_impl!(u8)
+totalord_impl!(u16)
+totalord_impl!(u32)
+totalord_impl!(u64)
+
+totalord_impl!(i8)
+totalord_impl!(i16)
+totalord_impl!(i32)
+totalord_impl!(i64)
+
+totalord_impl!(int)
+totalord_impl!(uint)
+
+totalord_impl!(char)
+
+/// Compares (a1, b1) against (a2, b2), where the a values are more significant.
+pub fn cmp2<A:TotalOrd,B:TotalOrd>(
+    a1: &A, b1: &B,
+    a2: &A, b2: &B) -> Ordering
+{
+    match a1.cmp(a2) {
+        Less => Less,
+        Greater => Greater,
+        Equal => b1.cmp(b2)
+    }
+}
+
+/**
+Return `o1` if it is not `Equal`, otherwise `o2`. Simulates the
+lexical ordering on a type `(int, int)`.
+*/
+// used in deriving code in libsyntax
+#[inline(always)]
+pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
+    match o1 {
+        Equal => o2,
+        _ => o1
+    }
+}
+
+/**
+* Trait for values that can be compared for a sort-order.
+*
+* Eventually this may be simplified to only require
+* an `le` method, with the others generated from
+* default implementations. However it should remain
+* possible to implement the others separately, for
+* compatibility with floating-point NaN semantics
+* (cf. IEEE 754-2008 section 5.11).
+*/
+#[lang="ord"]
+pub trait Ord {
+    fn lt(&self, other: &Self) -> bool;
+    fn le(&self, other: &Self) -> bool;
+    fn ge(&self, other: &Self) -> bool;
+    fn gt(&self, other: &Self) -> bool;
+}
+
+#[inline(always)]
+pub fn lt<T:Ord>(v1: &T, v2: &T) -> bool {
+    (*v1).lt(v2)
+}
+
+#[inline(always)]
+pub fn le<T:Ord>(v1: &T, v2: &T) -> bool {
+    (*v1).le(v2)
+}
+
+#[inline(always)]
+pub fn eq<T:Eq>(v1: &T, v2: &T) -> bool {
+    (*v1).eq(v2)
+}
+
+#[inline(always)]
+pub fn ne<T:Eq>(v1: &T, v2: &T) -> bool {
+    (*v1).ne(v2)
+}
+
+#[inline(always)]
+pub fn ge<T:Ord>(v1: &T, v2: &T) -> bool {
+    (*v1).ge(v2)
+}
+
+#[inline(always)]
+pub fn gt<T:Ord>(v1: &T, v2: &T) -> bool {
+    (*v1).gt(v2)
+}
+
+/// The equivalence relation. Two values may be equivalent even if they are
+/// of different types. The most common use case for this relation is
+/// container types; e.g. it is often desirable to be able to use `&str`
+/// values to look up entries in a container with `~str` keys.
+pub trait Equiv<T> {
+    fn equiv(&self, other: &T) -> bool;
+}
+
+#[inline(always)]
+pub fn min<T:Ord>(v1: T, v2: T) -> T {
+    if v1 < v2 { v1 } else { v2 }
+}
+
+#[inline(always)]
+pub fn max<T:Ord>(v1: T, v2: T) -> T {
+    if v1 > v2 { v1 } else { v2 }
+}
+
+#[cfg(test)]
+mod test {
+    use super::lexical_ordering;
+
+    #[test]
+    fn test_int_totalord() {
+        assert_eq!(5.cmp(&10), Less);
+        assert_eq!(10.cmp(&5), Greater);
+        assert_eq!(5.cmp(&5), Equal);
+        assert_eq!((-5).cmp(&12), Less);
+        assert_eq!(12.cmp(-5), Greater);
+    }
+
+    #[test]
+    fn test_cmp2() {
+        assert_eq!(cmp2(1, 2, 3, 4), Less);
+        assert_eq!(cmp2(3, 2, 3, 4), Less);
+        assert_eq!(cmp2(5, 2, 3, 4), Greater);
+        assert_eq!(cmp2(5, 5, 5, 4), Greater);
+    }
+
+    #[test]
+    fn test_int_totaleq() {
+        assert!(5.equals(&5));
+        assert!(!2.equals(&17));
+    }
+
+    #[test]
+    fn test_ordering_order() {
+        assert!(Less < Equal);
+        assert_eq!(Greater.cmp(&Less), Greater);
+    }
+
+    #[test]
+    fn test_lexical_ordering() {
+        fn t(o1: Ordering, o2: Ordering, e: Ordering) {
+            assert_eq!(lexical_ordering(o1, o2), e);
+        }
+        for [Less, Equal, Greater].each |&o| {
+            t(Less, o, Less);
+            t(Equal, o, o);
+            t(Greater, o, Greater);
+         }
+    }
+}
diff --git a/src/libstd/comm.rs b/src/libstd/comm.rs
index 28d3d329b26..59eb915c239 100644
--- a/src/libstd/comm.rs
+++ b/src/libstd/comm.rs
@@ -9,102 +9,802 @@
 // except according to those terms.
 
 /*!
+Message passing
+*/
 
-Higher level communication abstractions.
+use cast::{transmute, transmute_mut};
+use container::Container;
+use either::{Either, Left, Right};
+use kinds::Owned;
+use option::{Option, Some, None};
+use uint;
+use vec;
+use vec::OwnedVector;
+use util::replace;
+use unstable::sync::{Exclusive, exclusive};
+use rtcomm = rt::comm;
+use rt;
 
-*/
+use pipes::{wait_many, PacketHeader};
+
+// FIXME #5160: Making this public exposes some plumbing from
+// pipes. Needs some refactoring
+pub use pipes::Selectable;
 
-use core::comm::{GenericChan, GenericSmartChan, GenericPort};
-use core::comm::{Chan, Port, Selectable, Peekable};
-use core::pipes;
+/// A trait for things that can send multiple messages.
+pub trait GenericChan<T> {
+    /// Sends a message.
+    fn send(&self, x: T);
+}
+
+/// Things that can send multiple messages and can detect when the receiver
+/// is closed
+pub trait GenericSmartChan<T> {
+    /// Sends a message, or report if the receiver has closed the connection.
+    fn try_send(&self, x: T) -> bool;
+}
+
+/// A trait for things that can receive multiple messages.
+pub trait GenericPort<T> {
+    /// Receives a message, or fails if the connection closes.
+    fn recv(&self) -> T;
+
+    /** Receives a message, or returns `none` if
+    the connection is closed or closes.
+    */
+    fn try_recv(&self) -> Option<T>;
+}
+
+/// Ports that can `peek`
+pub trait Peekable<T> {
+    /// Returns true if a message is available
+    fn peek(&self) -> bool;
+}
 
-/// An extension of `pipes::stream` that allows both sending and receiving.
-pub struct DuplexStream<T, U> {
-    priv chan: Chan<T>,
-    priv port: Port<U>,
+/// An endpoint that can send many messages.
+pub struct Chan<T> {
+    inner: Either<pipesy::Chan<T>, rtcomm::Chan<T>>
 }
 
-// Allow these methods to be used without import:
-pub impl<T:Owned,U:Owned> DuplexStream<T, U> {
+/// An endpoint that can receive many messages.
+pub struct Port<T> {
+    inner: Either<pipesy::Port<T>, rtcomm::Port<T>>
+}
+
+/** Creates a `(Port, Chan)` pair.
+
+These allow sending or receiving an unlimited number of messages.
+
+*/
+pub fn stream<T:Owned>() -> (Port<T>, Chan<T>) {
+    let (port, chan) = match rt::context() {
+        rt::OldTaskContext => match pipesy::stream() {
+            (p, c) => (Left(p), Left(c))
+        },
+        _ => match rtcomm::stream() {
+            (p, c) => (Right(p), Right(c))
+        }
+    };
+    let port = Port { inner: port };
+    let chan = Chan { inner: chan };
+    return (port, chan);
+}
+
+impl<T: Owned> GenericChan<T> for Chan<T> {
     fn send(&self, x: T) {
-        self.chan.send(x)
+        match self.inner {
+            Left(ref chan) => chan.send(x),
+            Right(ref chan) => chan.send(x)
+        }
     }
+}
+
+impl<T: Owned> GenericSmartChan<T> for Chan<T> {
     fn try_send(&self, x: T) -> bool {
-        self.chan.try_send(x)
+        match self.inner {
+            Left(ref chan) => chan.try_send(x),
+            Right(ref chan) => chan.try_send(x)
+        }
     }
-    fn recv(&self, ) -> U {
-        self.port.recv()
+}
+
+impl<T: Owned> GenericPort<T> for Port<T> {
+    fn recv(&self) -> T {
+        match self.inner {
+            Left(ref port) => port.recv(),
+            Right(ref port) => port.recv()
+        }
     }
-    fn try_recv(&self) -> Option<U> {
-        self.port.try_recv()
+
+    fn try_recv(&self) -> Option<T> {
+        match self.inner {
+            Left(ref port) => port.try_recv(),
+            Right(ref port) => port.try_recv()
+        }
     }
+}
+
+impl<T: Owned> Peekable<T> for Port<T> {
     fn peek(&self) -> bool {
-        self.port.peek()
+        match self.inner {
+            Left(ref port) => port.peek(),
+            Right(ref port) => port.peek()
+        }
+    }
+}
+
+impl<T: Owned> Selectable for Port<T> {
+    fn header(&mut self) -> *mut PacketHeader {
+        match self.inner {
+            Left(ref mut port) => port.header(),
+            Right(_) => fail!("can't select on newsched ports")
+        }
+    }
+}
+
+/// Treat many ports as one.
+#[unsafe_mut_field(ports)]
+pub struct PortSet<T> {
+    ports: ~[pipesy::Port<T>],
+}
+
+pub impl<T: Owned> PortSet<T> {
+    fn new() -> PortSet<T> {
+        PortSet {
+            ports: ~[]
+        }
+    }
+
+    fn add(&self, port: Port<T>) {
+        let Port { inner } = port;
+        let port = match inner {
+            Left(p) => p,
+            Right(_) => fail!("PortSet not implemented")
+        };
+        unsafe {
+            let self_ports = transmute_mut(&self.ports);
+            self_ports.push(port)
+        }
+    }
+
+    fn chan(&self) -> Chan<T> {
+        let (po, ch) = stream();
+        self.add(po);
+        ch
+    }
+}
+
+impl<T:Owned> GenericPort<T> for PortSet<T> {
+    fn try_recv(&self) -> Option<T> {
+        unsafe {
+            let self_ports = transmute_mut(&self.ports);
+            let mut result = None;
+            // we have to swap the ports array so we aren't borrowing
+            // aliasable mutable memory.
+            let mut ports = replace(self_ports, ~[]);
+            while result.is_none() && ports.len() > 0 {
+                let i = wait_many(ports);
+                match ports[i].try_recv() {
+                    Some(m) => {
+                        result = Some(m);
+                    }
+                    None => {
+                        // Remove this port.
+                        let _ = ports.swap_remove(i);
+                    }
+                }
+            }
+            *self_ports = ports;
+            result
+        }
+    }
+    fn recv(&self) -> T {
+        self.try_recv().expect("port_set: endpoints closed")
     }
 }
 
-impl<T:Owned,U:Owned> GenericChan<T> for DuplexStream<T, U> {
+impl<T: Owned> Peekable<T> for PortSet<T> {
+    fn peek(&self) -> bool {
+        // It'd be nice to use self.port.each, but that version isn't
+        // pure.
+        for uint::range(0, vec::uniq_len(&const self.ports)) |i| {
+            let port: &pipesy::Port<T> = &self.ports[i];
+            if port.peek() {
+                return true;
+            }
+        }
+        false
+    }
+}
+
+/// A channel that can be shared between many senders.
+pub struct SharedChan<T> {
+    ch: Exclusive<pipesy::Chan<T>>
+}
+
+impl<T: Owned> SharedChan<T> {
+    /// Converts a `chan` into a `shared_chan`.
+    pub fn new(c: Chan<T>) -> SharedChan<T> {
+        let Chan { inner } = c;
+        let c = match inner {
+            Left(c) => c,
+            Right(_) => fail!("SharedChan not implemented")
+        };
+        SharedChan { ch: exclusive(c) }
+    }
+}
+
+impl<T: Owned> GenericChan<T> for SharedChan<T> {
     fn send(&self, x: T) {
-        self.chan.send(x)
+        let mut xx = Some(x);
+        do self.ch.with_imm |chan| {
+            let x = replace(&mut xx, None);
+            chan.send(x.unwrap())
+        }
     }
 }
 
-impl<T:Owned,U:Owned> GenericSmartChan<T> for DuplexStream<T, U> {
+impl<T: Owned> GenericSmartChan<T> for SharedChan<T> {
     fn try_send(&self, x: T) -> bool {
-        self.chan.try_send(x)
+        let mut xx = Some(x);
+        do self.ch.with_imm |chan| {
+            let x = replace(&mut xx, None);
+            chan.try_send(x.unwrap())
+        }
+    }
+}
+
+impl<T: Owned> ::clone::Clone for SharedChan<T> {
+    fn clone(&self) -> SharedChan<T> {
+        SharedChan { ch: self.ch.clone() }
     }
 }
 
-impl<T:Owned,U:Owned> GenericPort<U> for DuplexStream<T, U> {
-    fn recv(&self) -> U {
-        self.port.recv()
+pub struct PortOne<T> {
+    inner: Either<pipesy::PortOne<T>, rtcomm::PortOne<T>>
+}
+
+pub struct ChanOne<T> {
+    inner: Either<pipesy::ChanOne<T>, rtcomm::ChanOne<T>>
+}
+
+pub fn oneshot<T: Owned>() -> (PortOne<T>, ChanOne<T>) {
+    let (port, chan) = match rt::context() {
+        rt::OldTaskContext => match pipesy::oneshot() {
+            (p, c) => (Left(p), Left(c)),
+        },
+        _ => match rtcomm::oneshot() {
+            (p, c) => (Right(p), Right(c))
+        }
+    };
+    let port = PortOne { inner: port };
+    let chan = ChanOne { inner: chan };
+    return (port, chan);
+}
+
+impl<T: Owned> PortOne<T> {
+    pub fn recv(self) -> T {
+        let PortOne { inner } = self;
+        match inner {
+            Left(p) => p.recv(),
+            Right(p) => p.recv()
+        }
     }
 
-    fn try_recv(&self) -> Option<U> {
-        self.port.try_recv()
+    pub fn try_recv(self) -> Option<T> {
+        let PortOne { inner } = self;
+        match inner {
+            Left(p) => p.try_recv(),
+            Right(p) => p.try_recv()
+        }
     }
 }
 
-impl<T:Owned,U:Owned> Peekable<U> for DuplexStream<T, U> {
-    fn peek(&self) -> bool {
-        self.port.peek()
+impl<T: Owned> ChanOne<T> {
+    pub fn send(self, data: T) {
+        let ChanOne { inner } = self;
+        match inner {
+            Left(p) => p.send(data),
+            Right(p) => p.send(data)
+        }
+    }
+
+    pub fn try_send(self, data: T) -> bool {
+        let ChanOne { inner } = self;
+        match inner {
+            Left(p) => p.try_send(data),
+            Right(p) => p.try_send(data)
+        }
+    }
+}
+
+pub fn recv_one<T: Owned>(port: PortOne<T>) -> T {
+    let PortOne { inner } = port;
+    match inner {
+        Left(p) => pipesy::recv_one(p),
+        Right(p) => p.recv()
+    }
+}
+
+pub fn try_recv_one<T: Owned>(port: PortOne<T>) -> Option<T> {
+    let PortOne { inner } = port;
+    match inner {
+        Left(p) => pipesy::try_recv_one(p),
+        Right(p) => p.try_recv()
+    }
+}
+
+pub fn send_one<T: Owned>(chan: ChanOne<T>, data: T) {
+    let ChanOne { inner } = chan;
+    match inner {
+        Left(c) => pipesy::send_one(c, data),
+        Right(c) => c.send(data)
+    }
+}
+
+pub fn try_send_one<T: Owned>(chan: ChanOne<T>, data: T) -> bool {
+    let ChanOne { inner } = chan;
+    match inner {
+        Left(c) => pipesy::try_send_one(c, data),
+        Right(c) => c.try_send(data)
+    }
+}
+
+mod pipesy {
+
+    use kinds::Owned;
+    use option::{Option, Some, None};
+    use pipes::{recv, try_recv, peek, PacketHeader};
+    use super::{GenericChan, GenericSmartChan, GenericPort, Peekable, Selectable};
+    use cast::transmute_mut;
+    use util::replace;
+
+    /*proto! oneshot (
+        Oneshot:send<T:Owned> {
+            send(T) -> !
+        }
+    )*/
+
+    #[allow(non_camel_case_types)]
+    pub mod oneshot {
+        priv use core::kinds::Owned;
+        use ptr::to_mut_unsafe_ptr;
+
+        pub fn init<T: Owned>() -> (client::Oneshot<T>, server::Oneshot<T>) {
+            pub use core::pipes::HasBuffer;
+
+            let buffer = ~::core::pipes::Buffer {
+                header: ::core::pipes::BufferHeader(),
+                data: __Buffer {
+                    Oneshot: ::core::pipes::mk_packet::<Oneshot<T>>()
+                },
+            };
+            do ::core::pipes::entangle_buffer(buffer) |buffer, data| {
+                data.Oneshot.set_buffer(buffer);
+                to_mut_unsafe_ptr(&mut data.Oneshot)
+            }
+        }
+        #[allow(non_camel_case_types)]
+        pub enum Oneshot<T> { pub send(T), }
+        #[allow(non_camel_case_types)]
+        pub struct __Buffer<T> {
+            Oneshot: ::core::pipes::Packet<Oneshot<T>>,
+        }
+
+        #[allow(non_camel_case_types)]
+        pub mod client {
+
+            priv use core::kinds::Owned;
+
+            #[allow(non_camel_case_types)]
+            pub fn try_send<T: Owned>(pipe: Oneshot<T>, x_0: T) ->
+                ::core::option::Option<()> {
+                {
+                    use super::send;
+                    let message = send(x_0);
+                    if ::core::pipes::send(pipe, message) {
+                        ::core::pipes::rt::make_some(())
+                    } else { ::core::pipes::rt::make_none() }
+                }
+            }
+
+            #[allow(non_camel_case_types)]
+            pub fn send<T: Owned>(pipe: Oneshot<T>, x_0: T) {
+                {
+                    use super::send;
+                    let message = send(x_0);
+                    ::core::pipes::send(pipe, message);
+                }
+            }
+
+            #[allow(non_camel_case_types)]
+            pub type Oneshot<T> =
+                ::core::pipes::SendPacketBuffered<super::Oneshot<T>,
+            super::__Buffer<T>>;
+        }
+
+        #[allow(non_camel_case_types)]
+        pub mod server {
+            #[allow(non_camel_case_types)]
+            pub type Oneshot<T> =
+                ::core::pipes::RecvPacketBuffered<super::Oneshot<T>,
+            super::__Buffer<T>>;
+        }
+    }
+
+    /// The send end of a oneshot pipe.
+    pub struct ChanOne<T> {
+        contents: oneshot::client::Oneshot<T>
+    }
+
+    impl<T> ChanOne<T> {
+        pub fn new(contents: oneshot::client::Oneshot<T>) -> ChanOne<T> {
+            ChanOne {
+                contents: contents
+            }
+        }
+    }
+
+    /// The receive end of a oneshot pipe.
+    pub struct PortOne<T> {
+        contents: oneshot::server::Oneshot<T>
+    }
+
+    impl<T> PortOne<T> {
+        pub fn new(contents: oneshot::server::Oneshot<T>) -> PortOne<T> {
+            PortOne {
+                contents: contents
+            }
+        }
+    }
+
+    /// Initialiase a (send-endpoint, recv-endpoint) oneshot pipe pair.
+    pub fn oneshot<T: Owned>() -> (PortOne<T>, ChanOne<T>) {
+        let (chan, port) = oneshot::init();
+        (PortOne::new(port), ChanOne::new(chan))
+    }
+
+    pub impl<T: Owned> PortOne<T> {
+        fn recv(self) -> T { recv_one(self) }
+        fn try_recv(self) -> Option<T> { try_recv_one(self) }
+        fn unwrap(self) -> oneshot::server::Oneshot<T> {
+            match self {
+                PortOne { contents: s } => s
+            }
+        }
+    }
+
+    pub impl<T: Owned> ChanOne<T> {
+        fn send(self, data: T) { send_one(self, data) }
+        fn try_send(self, data: T) -> bool { try_send_one(self, data) }
+        fn unwrap(self) -> oneshot::client::Oneshot<T> {
+            match self {
+                ChanOne { contents: s } => s
+            }
+        }
+    }
+
+    /**
+    * Receive a message from a oneshot pipe, failing if the connection was
+    * closed.
+    */
+    pub fn recv_one<T: Owned>(port: PortOne<T>) -> T {
+        match port {
+            PortOne { contents: port } => {
+                let oneshot::send(message) = recv(port);
+                message
+            }
+        }
+    }
+
+    /// Receive a message from a oneshot pipe unless the connection was closed.
+    pub fn try_recv_one<T: Owned> (port: PortOne<T>) -> Option<T> {
+        match port {
+            PortOne { contents: port } => {
+                let message = try_recv(port);
+
+                if message.is_none() {
+                    None
+                } else {
+                    let oneshot::send(message) = message.unwrap();
+                    Some(message)
+                }
+            }
+        }
+    }
+
+    /// Send a message on a oneshot pipe, failing if the connection was closed.
+    pub fn send_one<T: Owned>(chan: ChanOne<T>, data: T) {
+        match chan {
+            ChanOne { contents: chan } => oneshot::client::send(chan, data),
+        }
+    }
+
+    /**
+    * Send a message on a oneshot pipe, or return false if the connection was
+    * closed.
+    */
+    pub fn try_send_one<T: Owned>(chan: ChanOne<T>, data: T) -> bool {
+        match chan {
+            ChanOne { contents: chan } => {
+                oneshot::client::try_send(chan, data).is_some()
+            }
+        }
+    }
+
+    // Streams - Make pipes a little easier in general.
+
+    /*proto! streamp (
+        Open:send<T: Owned> {
+            data(T) -> Open<T>
+        }
+    )*/
+
+    #[allow(non_camel_case_types)]
+    pub mod streamp {
+        priv use core::kinds::Owned;
+
+        pub fn init<T: Owned>() -> (client::Open<T>, server::Open<T>) {
+            pub use core::pipes::HasBuffer;
+            ::core::pipes::entangle()
+        }
+
+        #[allow(non_camel_case_types)]
+        pub enum Open<T> { pub data(T, server::Open<T>), }
+
+        #[allow(non_camel_case_types)]
+        pub mod client {
+            priv use core::kinds::Owned;
+
+            #[allow(non_camel_case_types)]
+            pub fn try_data<T: Owned>(pipe: Open<T>, x_0: T) ->
+                ::core::option::Option<Open<T>> {
+                {
+                    use super::data;
+                    let (c, s) = ::core::pipes::entangle();
+                    let message = data(x_0, s);
+                    if ::core::pipes::send(pipe, message) {
+                        ::core::pipes::rt::make_some(c)
+                    } else { ::core::pipes::rt::make_none() }
+                }
+            }
+
+            #[allow(non_camel_case_types)]
+            pub fn data<T: Owned>(pipe: Open<T>, x_0: T) -> Open<T> {
+                {
+                    use super::data;
+                    let (c, s) = ::core::pipes::entangle();
+                    let message = data(x_0, s);
+                    ::core::pipes::send(pipe, message);
+                    c
+                }
+            }
+
+            #[allow(non_camel_case_types)]
+            pub type Open<T> = ::core::pipes::SendPacket<super::Open<T>>;
+        }
+
+        #[allow(non_camel_case_types)]
+        pub mod server {
+            #[allow(non_camel_case_types)]
+            pub type Open<T> = ::core::pipes::RecvPacket<super::Open<T>>;
+        }
+    }
+
+    /// An endpoint that can send many messages.
+    #[unsafe_mut_field(endp)]
+    pub struct Chan<T> {
+        endp: Option<streamp::client::Open<T>>
+    }
+
+    /// An endpoint that can receive many messages.
+    #[unsafe_mut_field(endp)]
+    pub struct Port<T> {
+        endp: Option<streamp::server::Open<T>>,
+    }
+
+    /** Creates a `(Port, Chan)` pair.
+
+    These allow sending or receiving an unlimited number of messages.
+
+    */
+    pub fn stream<T:Owned>() -> (Port<T>, Chan<T>) {
+        let (c, s) = streamp::init();
+
+        (Port {
+            endp: Some(s)
+        }, Chan {
+            endp: Some(c)
+        })
+    }
+
+    impl<T: Owned> GenericChan<T> for Chan<T> {
+        #[inline(always)]
+        fn send(&self, x: T) {
+            unsafe {
+                let self_endp = transmute_mut(&self.endp);
+                let endp = replace(self_endp, None);
+                *self_endp = Some(streamp::client::data(endp.unwrap(), x))
+            }
+        }
+    }
+
+    impl<T: Owned> GenericSmartChan<T> for Chan<T> {
+        #[inline(always)]
+        fn try_send(&self, x: T) -> bool {
+            unsafe {
+                let self_endp = transmute_mut(&self.endp);
+                let endp = replace(self_endp, None);
+                match streamp::client::try_data(endp.unwrap(), x) {
+                    Some(next) => {
+                        *self_endp = Some(next);
+                        true
+                    }
+                    None => false
+                }
+            }
+        }
+    }
+
+    impl<T: Owned> GenericPort<T> for Port<T> {
+        #[inline(always)]
+        fn recv(&self) -> T {
+            unsafe {
+                let self_endp = transmute_mut(&self.endp);
+                let endp = replace(self_endp, None);
+                let streamp::data(x, endp) = recv(endp.unwrap());
+                *self_endp = Some(endp);
+                x
+            }
+        }
+
+        #[inline(always)]
+        fn try_recv(&self) -> Option<T> {
+            unsafe {
+                let self_endp = transmute_mut(&self.endp);
+                let endp = replace(self_endp, None);
+                match try_recv(endp.unwrap()) {
+                    Some(streamp::data(x, endp)) => {
+                        *self_endp = Some(endp);
+                        Some(x)
+                    }
+                    None => None
+                }
+            }
+        }
+    }
+
+    impl<T: Owned> Peekable<T> for Port<T> {
+        #[inline(always)]
+        fn peek(&self) -> bool {
+            unsafe {
+                let self_endp = transmute_mut(&self.endp);
+                let mut endp = replace(self_endp, None);
+                let peek = match endp {
+                    Some(ref mut endp) => peek(endp),
+                    None => fail!("peeking empty stream")
+                };
+                *self_endp = endp;
+                peek
+            }
+        }
+    }
+
+    impl<T: Owned> Selectable for Port<T> {
+        fn header(&mut self) -> *mut PacketHeader {
+            match self.endp {
+                Some(ref mut endp) => endp.header(),
+                None => fail!("peeking empty stream")
+            }
     }
 }
 
-impl<T:Owned,U:Owned> Selectable for DuplexStream<T, U> {
-    fn header(&mut self) -> *mut pipes::PacketHeader {
-        self.port.header()
+}
+
+/// Returns the index of an endpoint that is ready to receive.
+pub fn selecti<T: Selectable>(endpoints: &mut [T]) -> uint {
+    wait_many(endpoints)
+}
+
+/// Returns 0 or 1 depending on which endpoint is ready to receive
+pub fn select2i<A:Selectable, B:Selectable>(a: &mut A, b: &mut B)
+                                            -> Either<(), ()> {
+    let mut endpoints = [ a.header(), b.header() ];
+    match wait_many(endpoints) {
+        0 => Left(()),
+        1 => Right(()),
+        _ => fail!("wait returned unexpected index"),
     }
 }
 
-/// Creates a bidirectional stream.
-pub fn DuplexStream<T:Owned,U:Owned>()
-    -> (DuplexStream<T, U>, DuplexStream<U, T>)
-{
-    let (p1, c2) = comm::stream();
-    let (p2, c1) = comm::stream();
-    (DuplexStream {
-        chan: c1,
-        port: p1
-    },
-     DuplexStream {
-         chan: c2,
-         port: p2
-     })
+/// Receive a message from one of two endpoints.
+pub trait Select2<T: Owned, U: Owned> {
+    /// Receive a message or return `None` if a connection closes.
+    fn try_select(&mut self) -> Either<Option<T>, Option<U>>;
+    /// Receive a message or fail if a connection closes.
+    fn select(&mut self) -> Either<T, U>;
+}
+
+impl<T:Owned,
+     U:Owned,
+     Left:Selectable + GenericPort<T>,
+     Right:Selectable + GenericPort<U>>
+     Select2<T, U>
+     for (Left, Right) {
+    fn select(&mut self) -> Either<T, U> {
+        // XXX: Bad borrow check workaround.
+        unsafe {
+            let this: &(Left, Right) = transmute(self);
+            match *this {
+                (ref lp, ref rp) => {
+                    let lp: &mut Left = transmute(lp);
+                    let rp: &mut Right = transmute(rp);
+                    match select2i(lp, rp) {
+                        Left(()) => Left(lp.recv()),
+                        Right(()) => Right(rp.recv()),
+                    }
+                }
+            }
+        }
+    }
+
+    fn try_select(&mut self) -> Either<Option<T>, Option<U>> {
+        // XXX: Bad borrow check workaround.
+        unsafe {
+            let this: &(Left, Right) = transmute(self);
+            match *this {
+                (ref lp, ref rp) => {
+                    let lp: &mut Left = transmute(lp);
+                    let rp: &mut Right = transmute(rp);
+                    match select2i(lp, rp) {
+                        Left(()) => Left (lp.try_recv()),
+                        Right(()) => Right(rp.try_recv()),
+                    }
+                }
+            }
+        }
+    }
 }
 
 #[cfg(test)]
 mod test {
-    use comm::DuplexStream;
+    use either::Right;
+    use super::{Chan, Port, oneshot, stream};
+
+    #[test]
+    fn test_select2() {
+        let (p1, c1) = stream();
+        let (p2, c2) = stream();
+
+        c1.send(~"abc");
+
+        let mut tuple = (p1, p2);
+        match tuple.select() {
+            Right(_) => fail!(),
+            _ => (),
+        }
+
+        c2.send(123);
+    }
+
+    #[test]
+    fn test_oneshot() {
+        let (p, c) = oneshot();
+
+        c.send(());
+
+        p.recv()
+    }
 
     #[test]
-    pub fn DuplexStream1() {
-        let (left, right) = DuplexStream();
+    fn test_peek_terminated() {
+        let (port, chan): (Port<int>, Chan<int>) = stream();
 
-        left.send(~"abc");
-        right.send(123);
+        {
+            // Destroy the channel
+            let _chan = chan;
+        }
 
-        assert_eq!(left.recv(), 123);
-        assert_eq!(right.recv(), ~"abc");
+        assert!(!port.peek());
     }
 }
diff --git a/src/libstd/condition.rs b/src/libstd/condition.rs
new file mode 100644
index 00000000000..baa6722b193
--- /dev/null
+++ b/src/libstd/condition.rs
@@ -0,0 +1,217 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*! Condition handling */
+
+use prelude::*;
+use local_data::{local_data_pop, local_data_set};
+
+// helper for transmutation, shown below.
+type RustClosure = (int, int);
+
+pub struct Handler<T, U> {
+    handle: RustClosure,
+    prev: Option<@Handler<T, U>>,
+}
+
+pub struct Condition<'self, T, U> {
+    name: &'static str,
+    key: local_data::LocalDataKey<'self, Handler<T, U>>
+}
+
+pub impl<'self, T, U> Condition<'self, T, U> {
+    fn trap(&'self self, h: &'self fn(T) -> U) -> Trap<'self, T, U> {
+        unsafe {
+            let p : *RustClosure = ::cast::transmute(&h);
+            let prev = local_data::local_data_get(self.key);
+            let h = @Handler { handle: *p, prev: prev };
+            Trap { cond: self, handler: h }
+        }
+    }
+
+    fn raise(&self, t: T) -> U {
+        let msg = fmt!("Unhandled condition: %s: %?", self.name, t);
+        self.raise_default(t, || fail!(copy msg))
+    }
+
+    fn raise_default(&self, t: T, default: &fn() -> U) -> U {
+        unsafe {
+            match local_data_pop(self.key) {
+                None => {
+                    debug!("Condition.raise: found no handler");
+                    default()
+                }
+                Some(handler) => {
+                    debug!("Condition.raise: found handler");
+                    match handler.prev {
+                        None => {}
+                        Some(hp) => local_data_set(self.key, hp)
+                    }
+                    let handle : &fn(T) -> U =
+                        ::cast::transmute(handler.handle);
+                    let u = handle(t);
+                    local_data_set(self.key, handler);
+                    u
+                }
+            }
+        }
+    }
+}
+
+struct Trap<'self, T, U> {
+    cond: &'self Condition<'self, T, U>,
+    handler: @Handler<T, U>
+}
+
+pub impl<'self, T, U> Trap<'self, T, U> {
+    fn in<V>(&self, inner: &'self fn() -> V) -> V {
+        unsafe {
+            let _g = Guard { cond: self.cond };
+            debug!("Trap: pushing handler to TLS");
+            local_data_set(self.cond.key, self.handler);
+            inner()
+        }
+    }
+}
+
+struct Guard<'self, T, U> {
+    cond: &'self Condition<'self, T, U>
+}
+
+#[unsafe_destructor]
+impl<'self, T, U> Drop for Guard<'self, T, U> {
+    fn finalize(&self) {
+        unsafe {
+            debug!("Guard: popping handler from TLS");
+            let curr = local_data_pop(self.cond.key);
+            match curr {
+                None => {}
+                Some(h) => match h.prev {
+                    None => {}
+                    Some(hp) => local_data_set(self.cond.key, hp)
+                }
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    condition! {
+        sadness: int -> int;
+    }
+
+    fn trouble(i: int) {
+        debug!("trouble: raising condition");
+        let j = sadness::cond.raise(i);
+        debug!("trouble: handler recovered with %d", j);
+    }
+
+    fn nested_trap_test_inner() {
+        let mut inner_trapped = false;
+
+        do sadness::cond.trap(|_j| {
+            debug!("nested_trap_test_inner: in handler");
+            inner_trapped = true;
+            0
+        }).in {
+            debug!("nested_trap_test_inner: in protected block");
+            trouble(1);
+        }
+
+        assert!(inner_trapped);
+    }
+
+    #[test]
+    fn nested_trap_test_outer() {
+        let mut outer_trapped = false;
+
+        do sadness::cond.trap(|_j| {
+            debug!("nested_trap_test_outer: in handler");
+            outer_trapped = true; 0
+        }).in {
+            debug!("nested_guard_test_outer: in protected block");
+            nested_trap_test_inner();
+            trouble(1);
+        }
+
+        assert!(outer_trapped);
+    }
+
+    fn nested_reraise_trap_test_inner() {
+        let mut inner_trapped = false;
+
+        do sadness::cond.trap(|_j| {
+            debug!("nested_reraise_trap_test_inner: in handler");
+            inner_trapped = true;
+            let i = 10;
+            debug!("nested_reraise_trap_test_inner: handler re-raising");
+            sadness::cond.raise(i)
+        }).in {
+            debug!("nested_reraise_trap_test_inner: in protected block");
+            trouble(1);
+        }
+
+        assert!(inner_trapped);
+    }
+
+    #[test]
+    fn nested_reraise_trap_test_outer() {
+        let mut outer_trapped = false;
+
+        do sadness::cond.trap(|_j| {
+            debug!("nested_reraise_trap_test_outer: in handler");
+            outer_trapped = true; 0
+        }).in {
+            debug!("nested_reraise_trap_test_outer: in protected block");
+            nested_reraise_trap_test_inner();
+        }
+
+        assert!(outer_trapped);
+    }
+
+    #[test]
+    fn test_default() {
+        let mut trapped = false;
+
+        do sadness::cond.trap(|j| {
+            debug!("test_default: in handler");
+            sadness::cond.raise_default(j, || { trapped=true; 5 })
+        }).in {
+            debug!("test_default: in protected block");
+            trouble(1);
+        }
+
+        assert!(trapped);
+    }
+
+    // Issue #6009
+    mod m {
+        condition! {
+            sadness: int -> int;
+        }
+
+        mod n {
+            use super::sadness;
+
+            #[test]
+            fn test_conditions_are_public() {
+                let mut trapped = false;
+                do sadness::cond.trap(|_| {
+                    trapped = true;
+                    0
+                }).in {
+                    sadness::cond.raise(0);
+                }
+                assert!(trapped);
+            }
+        }
+    }
+}
diff --git a/src/libstd/container.rs b/src/libstd/container.rs
new file mode 100644
index 00000000000..505aa5881c5
--- /dev/null
+++ b/src/libstd/container.rs
@@ -0,0 +1,101 @@
+// 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.
+
+//! Container traits
+
+use option::Option;
+
+pub trait Container {
+    /// Return the number of elements in the container
+    fn len(&const self) -> uint;
+
+    /// Return true if the container contains no elements
+    fn is_empty(&const self) -> bool;
+}
+
+pub trait Mutable: Container {
+    /// Clear the container, removing all values.
+    fn clear(&mut self);
+}
+
+pub trait Map<K, V>: Mutable {
+    /// Return true if the map contains a value for the specified key
+    fn contains_key(&self, key: &K) -> bool;
+
+    // Visits all keys and values
+    fn each<'a>(&'a self, f: &fn(&K, &'a V) -> bool) -> bool;
+
+    /// Visit all keys
+    fn each_key(&self, f: &fn(&K) -> bool) -> bool;
+
+    /// Visit all values
+    fn each_value<'a>(&'a self, f: &fn(&'a V) -> bool) -> bool;
+
+    /// Iterate over the map and mutate the contained values
+    fn mutate_values(&mut self, f: &fn(&K, &mut V) -> bool) -> bool;
+
+    /// Return a reference to the value corresponding to the key
+    fn find<'a>(&'a self, key: &K) -> Option<&'a V>;
+
+    /// Return a mutable reference to the value corresponding to the key
+    fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V>;
+
+    /// Insert a key-value pair into the map. An existing value for a
+    /// key is replaced by the new value. Return true if the key did
+    /// not already exist in the map.
+    fn insert(&mut self, key: K, value: V) -> bool;
+
+    /// Remove a key-value pair from the map. Return true if the key
+    /// was present in the map, otherwise false.
+    fn remove(&mut self, key: &K) -> bool;
+
+    /// Insert a key-value pair from the map. If the key already had a value
+    /// present in the map, that value is returned. Otherwise None is returned.
+    fn swap(&mut self, k: K, v: V) -> Option<V>;
+
+    /// Removes a key from the map, returning the value at the key if the key
+    /// was previously in the map.
+    fn pop(&mut self, k: &K) -> Option<V>;
+}
+
+pub trait Set<T>: Mutable {
+    /// Return true if the set contains a value
+    fn contains(&self, value: &T) -> bool;
+
+    /// Add a value to the set. Return true if the value was not already
+    /// present in the set.
+    fn insert(&mut self, value: T) -> bool;
+
+    /// Remove a value from the set. Return true if the value was
+    /// present in the set.
+    fn remove(&mut self, value: &T) -> bool;
+
+    /// Return true if the set has no elements in common with `other`.
+    /// This is equivalent to checking for an empty intersection.
+    fn is_disjoint(&self, other: &Self) -> bool;
+
+    /// Return true if the set is a subset of another
+    fn is_subset(&self, other: &Self) -> bool;
+
+    /// Return true if the set is a superset of another
+    fn is_superset(&self, other: &Self) -> bool;
+
+    /// Visit the values representing the difference
+    fn difference(&self, other: &Self, f: &fn(&T) -> bool) -> bool;
+
+    /// Visit the values representing the symmetric difference
+    fn symmetric_difference(&self, other: &Self, f: &fn(&T) -> bool) -> bool;
+
+    /// Visit the values representing the intersection
+    fn intersection(&self, other: &Self, f: &fn(&T) -> bool) -> bool;
+
+    /// Visit the values representing the union
+    fn union(&self, other: &Self, f: &fn(&T) -> bool) -> bool;
+}
diff --git a/src/libstd/core.rc b/src/libstd/core.rc
new file mode 100644
index 00000000000..60093ff96bb
--- /dev/null
+++ b/src/libstd/core.rc
@@ -0,0 +1,226 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+# The Rust core library
+
+The Rust core library provides runtime features required by the language,
+including the task scheduler and memory allocators, as well as library
+support for Rust built-in types, platform abstractions, and other commonly
+used features.
+
+`core` includes modules corresponding to each of the integer types, each of
+the floating point types, the `bool` type, tuples, characters, strings
+(`str`), vectors (`vec`), managed boxes (`managed`), owned boxes (`owned`),
+and unsafe and borrowed pointers (`ptr`).  Additionally, `core` provides
+pervasive types (`option` and `result`), task creation and communication
+primitives (`task`, `comm`), platform 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`).
+
+# Core injection and the Rust prelude
+
+`core` is imported at the topmost level of every crate by default, as
+if the first line of each crate was
+
+    extern mod core;
+
+This means that the contents of core can be accessed from from any context
+with the `core::` path prefix, as in `use core::vec`, `use core::task::spawn`,
+etc.
+
+Additionally, `core` contains a `prelude` module that reexports many of the
+most common core modules, types and traits. The contents of the prelude are
+imported into every *module* by default.  Implicitly, all modules behave as if
+they contained the following prologue:
+
+    use core::prelude::*;
+
+*/
+
+
+#[link(name = "core",
+       vers = "0.7-pre",
+       uuid = "c70c24a7-5551-4f73-8e37-380b11d80be8",
+       url = "https://github.com/mozilla/rust/tree/master/src/libcore")];
+
+#[comment = "The Rust core library"];
+#[license = "MIT/ASL2"];
+#[crate_type = "lib"];
+
+
+// Don't link to core. We are core.
+#[no_core];
+
+#[deny(non_camel_case_types)];
+
+// Make core testable by not duplicating lang items. See #2912
+#[cfg(test)] extern mod realcore(name = "core");
+#[cfg(test)] pub use kinds = realcore::kinds;
+#[cfg(test)] pub use ops = realcore::ops;
+#[cfg(test)] pub use cmp = realcore::cmp;
+
+// On Linux, link to the runtime with -lrt.
+#[cfg(target_os = "linux")]
+#[doc(hidden)]
+pub mod linkhack {
+    #[link_args="-lrustrt -lrt"]
+    #[link_args = "-lpthread"]
+    extern {
+    }
+}
+
+// Internal macros
+mod macros;
+
+/* The Prelude. */
+
+pub mod prelude;
+
+/* Primitive types */
+
+#[path = "num/int-template.rs"] #[merge = "num/int-template/int.rs"]
+pub mod int;
+#[path = "num/int-template.rs"] #[merge = "num/int-template/i8.rs"]
+pub mod i8;
+#[path = "num/int-template.rs"] #[merge = "num/int-template/i16.rs"]
+pub mod i16;
+#[path = "num/int-template.rs"] #[merge = "num/int-template/i32.rs"]
+pub mod i32;
+#[path = "num/int-template.rs"] #[merge = "num/int-template/i64.rs"]
+pub mod i64;
+#[path = "num/uint-template.rs"] #[merge = "num/uint-template/uint.rs"]
+pub mod uint;
+
+#[path = "num/uint-template.rs"] #[merge = "num/uint-template/u8.rs"]
+pub mod u8;
+#[path = "num/uint-template.rs"] #[merge = "num/uint-template/u16.rs"]
+pub mod u16;
+#[path = "num/uint-template.rs"] #[merge = "num/uint-template/u32.rs"]
+pub mod u32;
+#[path = "num/uint-template.rs"] #[merge = "num/uint-template/u64.rs"]
+pub mod u64;
+
+#[path = "num/float.rs"]
+pub mod float;
+#[path = "num/f32.rs"]
+pub mod f32;
+#[path = "num/f64.rs"]
+pub mod f64;
+
+pub mod nil;
+pub mod bool;
+pub mod char;
+pub mod tuple;
+
+pub mod vec;
+pub mod at_vec;
+pub mod str;
+
+#[path = "str/ascii.rs"]
+pub mod ascii;
+
+pub mod ptr;
+pub mod owned;
+pub mod managed;
+
+
+/* Core language traits */
+
+#[cfg(not(test))] pub mod kinds;
+#[cfg(not(test))] pub mod ops;
+#[cfg(not(test))] pub mod cmp;
+
+
+/* Common traits */
+
+pub mod from_str;
+#[path = "num/num.rs"]
+pub mod num;
+pub mod iter;
+pub mod old_iter;
+pub mod iterator;
+pub mod to_str;
+pub mod to_bytes;
+pub mod clone;
+pub mod io;
+pub mod hash;
+pub mod container;
+
+
+/* Common data structures */
+
+pub mod option;
+pub mod result;
+pub mod either;
+pub mod hashmap;
+pub mod cell;
+pub mod trie;
+
+
+/* Tasks and communication */
+
+#[path = "task/mod.rs"]
+pub mod task;
+pub mod comm;
+pub mod pipes;
+pub mod local_data;
+
+
+/* Runtime and platform support */
+
+pub mod gc;
+pub mod libc;
+pub mod os;
+pub mod path;
+pub mod rand;
+pub mod run;
+pub mod sys;
+pub mod cast;
+pub mod repr;
+pub mod cleanup;
+pub mod reflect;
+pub mod condition;
+pub mod logging;
+pub mod util;
+
+
+/* Unsupported interfaces */
+
+// Private APIs
+#[path = "unstable/mod.rs"]
+pub mod unstable;
+
+/* For internal use, not exported */
+
+mod unicode;
+#[path = "num/cmath.rs"]
+mod cmath;
+mod stackwalk;
+
+// XXX: This shouldn't be pub, and it should be reexported under 'unstable'
+// but name resolution doesn't work without it being pub.
+#[path = "rt/mod.rs"]
+pub mod rt;
+
+// A curious inner-module that's not exported that contains the binding
+// 'core' so that macro-expanded references to core::error and such
+// can be resolved within libcore.
+#[doc(hidden)]
+mod core {
+    pub use clone;
+    pub use cmp;
+    pub use condition;
+    pub use option;
+    pub use kinds;
+    pub use sys;
+    pub use pipes;
+}
diff --git a/src/libstd/dbg.rs b/src/libstd/dbg.rs
deleted file mode 100644
index 4b2d2a60a68..00000000000
--- a/src/libstd/dbg.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Unsafe debugging functions for inspecting values.
-
-use core::cast::transmute;
-use core::sys;
-
-pub mod rustrt {
-    use core::sys;
-
-    #[abi = "cdecl"]
-    pub extern {
-        pub unsafe fn debug_tydesc(td: *sys::TypeDesc);
-        pub unsafe fn debug_opaque(td: *sys::TypeDesc, x: *());
-        pub unsafe fn debug_box(td: *sys::TypeDesc, x: *());
-        pub unsafe fn debug_tag(td: *sys::TypeDesc, x: *());
-        pub unsafe fn debug_fn(td: *sys::TypeDesc, x: *());
-        pub unsafe fn debug_ptrcast(td: *sys::TypeDesc, x: *()) -> *();
-        pub unsafe fn rust_dbg_breakpoint();
-    }
-}
-
-pub fn debug_tydesc<T>() {
-    unsafe {
-        rustrt::debug_tydesc(sys::get_type_desc::<T>());
-    }
-}
-
-pub fn debug_opaque<T>(x: T) {
-    unsafe {
-        rustrt::debug_opaque(sys::get_type_desc::<T>(), transmute(&x));
-    }
-}
-
-pub fn debug_box<T>(x: @T) {
-    unsafe {
-        rustrt::debug_box(sys::get_type_desc::<T>(), transmute(&x));
-    }
-}
-
-pub fn debug_tag<T>(x: T) {
-    unsafe {
-        rustrt::debug_tag(sys::get_type_desc::<T>(), transmute(&x));
-    }
-}
-
-pub fn debug_fn<T>(x: T) {
-    unsafe {
-        rustrt::debug_fn(sys::get_type_desc::<T>(), transmute(&x));
-    }
-}
-
-pub unsafe fn ptr_cast<T, U>(x: @T) -> @U {
-    transmute(
-        rustrt::debug_ptrcast(sys::get_type_desc::<T>(), transmute(x)))
-}
-
-/// Triggers a debugger breakpoint
-pub fn breakpoint() {
-    unsafe {
-        rustrt::rust_dbg_breakpoint();
-    }
-}
-
-#[test]
-fn test_breakpoint_should_not_abort_process_when_not_under_gdb() {
-    // Triggering a breakpoint involves raising SIGTRAP, which terminates
-    // the process under normal circumstances
-    breakpoint();
-}
diff --git a/src/libstd/deque.rs b/src/libstd/deque.rs
deleted file mode 100644
index 60f16074177..00000000000
--- a/src/libstd/deque.rs
+++ /dev/null
@@ -1,329 +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.
-
-//! A double-ended queue implemented as a circular buffer
-
-use core::util::replace;
-
-static initial_capacity: uint = 32u; // 2^5
-
-pub struct Deque<T> {
-    priv nelts: uint,
-    priv lo: uint,
-    priv hi: uint,
-    priv elts: ~[Option<T>]
-}
-
-impl<T> Container for Deque<T> {
-    /// Return the number of elements in the deque
-    fn len(&const self) -> uint { self.nelts }
-
-    /// Return true if the deque contains no elements
-    fn is_empty(&const self) -> bool { self.len() == 0 }
-}
-
-impl<T> Mutable for Deque<T> {
-    /// Clear the deque, removing all values.
-    fn clear(&mut self) {
-        for self.elts.each_mut |x| { *x = None }
-        self.nelts = 0;
-        self.lo = 0;
-        self.hi = 0;
-    }
-}
-
-pub impl<T> Deque<T> {
-    /// Create an empty Deque
-    fn new() -> Deque<T> {
-        Deque{nelts: 0, lo: 0, hi: 0,
-              elts: vec::from_fn(initial_capacity, |_| None)}
-    }
-
-    /// Return a reference to the first element in the deque
-    ///
-    /// Fails if the deque is empty
-    fn peek_front<'a>(&'a self) -> &'a T { get(self.elts, self.lo) }
-
-    /// Return a reference to the last element in the deque
-    ///
-    /// Fails if the deque is empty
-    fn peek_back<'a>(&'a self) -> &'a T { get(self.elts, self.hi - 1u) }
-
-    /// Retrieve an element in the deque by index
-    ///
-    /// Fails if there is no element with the given index
-    fn get<'a>(&'a self, i: int) -> &'a T {
-        let idx = (self.lo + (i as uint)) % self.elts.len();
-        get(self.elts, idx)
-    }
-
-    /// Iterate over the elements in the deque
-    fn each(&self, f: &fn(&T) -> bool) -> bool {
-        self.eachi(|_i, e| f(e))
-    }
-
-    /// Iterate over the elements in the deque by index
-    fn eachi(&self, f: &fn(uint, &T) -> bool) -> bool {
-        uint::range(0, self.nelts, |i| f(i, self.get(i as int)))
-    }
-
-    /// Remove and return the first element in the deque
-    ///
-    /// Fails if the deque is empty
-    fn pop_front(&mut self) -> T {
-        let result = self.elts[self.lo].swap_unwrap();
-        self.lo = (self.lo + 1u) % self.elts.len();
-        self.nelts -= 1u;
-        result
-    }
-
-    /// Remove and return the last element in the deque
-    ///
-    /// Fails if the deque is empty
-    fn pop_back(&mut self) -> T {
-        if self.hi == 0u {
-            self.hi = self.elts.len() - 1u;
-        } else { self.hi -= 1u; }
-        let result = self.elts[self.hi].swap_unwrap();
-        self.elts[self.hi] = None;
-        self.nelts -= 1u;
-        result
-    }
-
-    /// Prepend an element to the deque
-    fn add_front(&mut self, t: T) {
-        let oldlo = self.lo;
-        if self.lo == 0u {
-            self.lo = self.elts.len() - 1u;
-        } else { self.lo -= 1u; }
-        if self.lo == self.hi {
-            self.elts = grow(self.nelts, oldlo, self.elts);
-            self.lo = self.elts.len() - 1u;
-            self.hi = self.nelts;
-        }
-        self.elts[self.lo] = Some(t);
-        self.nelts += 1u;
-    }
-
-    /// Append an element to the deque
-    fn add_back(&mut self, t: T) {
-        if self.lo == self.hi && self.nelts != 0u {
-            self.elts = grow(self.nelts, self.lo, self.elts);
-            self.lo = 0u;
-            self.hi = self.nelts;
-        }
-        self.elts[self.hi] = Some(t);
-        self.hi = (self.hi + 1u) % self.elts.len();
-        self.nelts += 1u;
-    }
-}
-
-/// Grow is only called on full elts, so nelts is also len(elts), unlike
-/// elsewhere.
-fn grow<T>(nelts: uint, lo: uint, elts: &mut [Option<T>]) -> ~[Option<T>] {
-    assert_eq!(nelts, elts.len());
-    let mut rv = ~[];
-
-    do rv.grow_fn(nelts + 1) |i| {
-        replace(&mut elts[(lo + i) % nelts], None)
-    }
-
-    rv
-}
-
-fn get<'r, T>(elts: &'r [Option<T>], i: uint) -> &'r T {
-    match elts[i] { Some(ref t) => t, _ => fail!() }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use core::cmp::Eq;
-    use core::kinds::Copy;
-
-    #[test]
-    fn test_simple() {
-        let mut d = Deque::new();
-        assert_eq!(d.len(), 0u);
-        d.add_front(17);
-        d.add_front(42);
-        d.add_back(137);
-        assert_eq!(d.len(), 3u);
-        d.add_back(137);
-        assert_eq!(d.len(), 4u);
-        debug!(d.peek_front());
-        assert_eq!(*d.peek_front(), 42);
-        debug!(d.peek_back());
-        assert_eq!(*d.peek_back(), 137);
-        let mut i: int = d.pop_front();
-        debug!(i);
-        assert_eq!(i, 42);
-        i = d.pop_back();
-        debug!(i);
-        assert_eq!(i, 137);
-        i = d.pop_back();
-        debug!(i);
-        assert_eq!(i, 137);
-        i = d.pop_back();
-        debug!(i);
-        assert_eq!(i, 17);
-        assert_eq!(d.len(), 0u);
-        d.add_back(3);
-        assert_eq!(d.len(), 1u);
-        d.add_front(2);
-        assert_eq!(d.len(), 2u);
-        d.add_back(4);
-        assert_eq!(d.len(), 3u);
-        d.add_front(1);
-        assert_eq!(d.len(), 4u);
-        debug!(d.get(0));
-        debug!(d.get(1));
-        debug!(d.get(2));
-        debug!(d.get(3));
-        assert_eq!(*d.get(0), 1);
-        assert_eq!(*d.get(1), 2);
-        assert_eq!(*d.get(2), 3);
-        assert_eq!(*d.get(3), 4);
-    }
-
-    #[test]
-    fn test_boxes() {
-        let a: @int = @5;
-        let b: @int = @72;
-        let c: @int = @64;
-        let d: @int = @175;
-
-        let mut deq = Deque::new();
-        assert_eq!(deq.len(), 0);
-        deq.add_front(a);
-        deq.add_front(b);
-        deq.add_back(c);
-        assert_eq!(deq.len(), 3);
-        deq.add_back(d);
-        assert_eq!(deq.len(), 4);
-        assert_eq!(*deq.peek_front(), b);
-        assert_eq!(*deq.peek_back(), d);
-        assert_eq!(deq.pop_front(), b);
-        assert_eq!(deq.pop_back(), d);
-        assert_eq!(deq.pop_back(), c);
-        assert_eq!(deq.pop_back(), a);
-        assert_eq!(deq.len(), 0);
-        deq.add_back(c);
-        assert_eq!(deq.len(), 1);
-        deq.add_front(b);
-        assert_eq!(deq.len(), 2);
-        deq.add_back(d);
-        assert_eq!(deq.len(), 3);
-        deq.add_front(a);
-        assert_eq!(deq.len(), 4);
-        assert_eq!(*deq.get(0), a);
-        assert_eq!(*deq.get(1), b);
-        assert_eq!(*deq.get(2), c);
-        assert_eq!(*deq.get(3), d);
-    }
-
-    #[cfg(test)]
-    fn test_parameterized<T:Copy + Eq>(a: T, b: T, c: T, d: T) {
-        let mut deq = Deque::new();
-        assert_eq!(deq.len(), 0);
-        deq.add_front(a);
-        deq.add_front(b);
-        deq.add_back(c);
-        assert_eq!(deq.len(), 3);
-        deq.add_back(d);
-        assert_eq!(deq.len(), 4);
-        assert_eq!(*deq.peek_front(), b);
-        assert_eq!(*deq.peek_back(), d);
-        assert_eq!(deq.pop_front(), b);
-        assert_eq!(deq.pop_back(), d);
-        assert_eq!(deq.pop_back(), c);
-        assert_eq!(deq.pop_back(), a);
-        assert_eq!(deq.len(), 0);
-        deq.add_back(c);
-        assert_eq!(deq.len(), 1);
-        deq.add_front(b);
-        assert_eq!(deq.len(), 2);
-        deq.add_back(d);
-        assert_eq!(deq.len(), 3);
-        deq.add_front(a);
-        assert_eq!(deq.len(), 4);
-        assert_eq!(*deq.get(0), a);
-        assert_eq!(*deq.get(1), b);
-        assert_eq!(*deq.get(2), c);
-        assert_eq!(*deq.get(3), d);
-    }
-
-    #[deriving(Eq)]
-    enum Taggy { One(int), Two(int, int), Three(int, int, int), }
-
-    #[deriving(Eq)]
-    enum Taggypar<T> {
-        Onepar(int), Twopar(int, int), Threepar(int, int, int),
-    }
-
-    #[deriving(Eq)]
-    struct RecCy {
-        x: int,
-        y: int,
-        t: Taggy
-    }
-
-    #[test]
-    fn test_param_int() {
-        test_parameterized::<int>(5, 72, 64, 175);
-    }
-
-    #[test]
-    fn test_param_at_int() {
-        test_parameterized::<@int>(@5, @72, @64, @175);
-    }
-
-    #[test]
-    fn test_param_taggy() {
-        test_parameterized::<Taggy>(One(1), Two(1, 2), Three(1, 2, 3),
-                                    Two(17, 42));
-    }
-
-    #[test]
-    fn test_param_taggypar() {
-        test_parameterized::<Taggypar<int>>(Onepar::<int>(1),
-                                            Twopar::<int>(1, 2),
-                                            Threepar::<int>(1, 2, 3),
-                                            Twopar::<int>(17, 42));
-    }
-
-    #[test]
-    fn test_param_reccy() {
-        let reccy1 = RecCy { x: 1, y: 2, t: One(1) };
-        let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) };
-        let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) };
-        let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) };
-        test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4);
-    }
-
-    #[test]
-    fn test_eachi() {
-        let mut deq = Deque::new();
-        deq.add_back(1);
-        deq.add_back(2);
-        deq.add_back(3);
-
-        for deq.eachi |i, e| {
-            assert_eq!(*e, i + 1);
-        }
-
-        deq.pop_front();
-
-        for deq.eachi |i, e| {
-            assert_eq!(*e, i + 2);
-        }
-
-    }
-}
diff --git a/src/libstd/dlist.rs b/src/libstd/dlist.rs
deleted file mode 100644
index 57cd03e16a0..00000000000
--- a/src/libstd/dlist.rs
+++ /dev/null
@@ -1,981 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
-
-A doubly-linked list. Supports O(1) head, tail, count, push, pop, etc.
-
-# Safety note
-
-Do not use ==, !=, <, etc on doubly-linked lists -- it may not terminate.
-
-*/
-
-use core::managed;
-
-pub type DListLink<T> = Option<@mut DListNode<T>>;
-
-pub struct DListNode<T> {
-    data: T,
-    linked: bool, // for assertions
-    prev: DListLink<T>,
-    next: DListLink<T>,
-}
-
-pub struct DList<T> {
-    size: uint,
-    hd: DListLink<T>,
-    tl: DListLink<T>,
-}
-
-priv impl<T> DListNode<T> {
-    fn assert_links(@mut self) {
-        match self.next {
-            Some(neighbour) => match neighbour.prev {
-              Some(me) => if !managed::mut_ptr_eq(self, me) {
-                  fail!("Asymmetric next-link in dlist node.")
-              },
-              None => fail!("One-way next-link in dlist node.")
-            },
-            None => ()
-        }
-        match self.prev {
-            Some(neighbour) => match neighbour.next {
-              Some(me) => if !managed::mut_ptr_eq(me, self) {
-                  fail!("Asymmetric prev-link in dlist node.")
-              },
-              None => fail!("One-way prev-link in dlist node.")
-            },
-            None => ()
-        }
-    }
-}
-
-pub impl<T> DListNode<T> {
-    /// Get the next node in the list, if there is one.
-    fn next_link(@mut self) -> DListLink<T> {
-        self.assert_links();
-        self.next
-    }
-    /// Get the next node in the list, failing if there isn't one.
-    fn next_node(@mut self) -> @mut DListNode<T> {
-        match self.next_link() {
-            Some(nobe) => nobe,
-            None       => fail!("This dlist node has no next neighbour.")
-        }
-    }
-    /// Get the previous node in the list, if there is one.
-    fn prev_link(@mut self) -> DListLink<T> {
-        self.assert_links();
-        self.prev
-    }
-    /// Get the previous node in the list, failing if there isn't one.
-    fn prev_node(@mut self) -> @mut DListNode<T> {
-        match self.prev_link() {
-            Some(nobe) => nobe,
-            None       => fail!("This dlist node has no previous neighbour.")
-        }
-    }
-}
-
-/// Creates a new dlist node with the given data.
-pub fn new_dlist_node<T>(data: T) -> @mut DListNode<T> {
-    @mut DListNode { data: data, linked: false, prev: None, next: None }
-}
-
-/// Creates a new, empty dlist.
-pub fn DList<T>() -> @mut DList<T> {
-    @mut DList { size: 0, hd: None, tl: None }
-}
-
-/// Creates a new dlist with a single element
-pub fn from_elem<T>(data: T) -> @mut DList<T> {
-    let list = DList();
-    list.push(data);
-    list
-}
-
-pub fn from_vec<T:Copy>(vec: &[T]) -> @mut DList<T> {
-    do vec::foldl(DList(), vec) |list,data| {
-        list.push(*data); // Iterating left-to-right -- add newly to the tail.
-        list
-    }
-}
-
-/// Produce a list from a list of lists, leaving no elements behind in the
-/// input. O(number of sub-lists).
-pub fn concat<T>(lists: @mut DList<@mut DList<T>>) -> @mut DList<T> {
-    let result = DList();
-    while !lists.is_empty() {
-        result.append(lists.pop().get());
-    }
-    result
-}
-
-priv impl<T> DList<T> {
-    fn new_link(data: T) -> DListLink<T> {
-        Some(@mut DListNode {
-            data: data,
-            linked: true,
-            prev: None,
-            next: None
-        })
-    }
-    fn assert_mine(@mut self, nobe: @mut DListNode<T>) {
-        // These asserts could be stronger if we had node-root back-pointers,
-        // but those wouldn't allow for O(1) append.
-        if self.size == 0 {
-            fail!("This dlist is empty; that node can't be on it.")
-        }
-        if !nobe.linked { fail!("That node isn't linked to any dlist.") }
-        if !((nobe.prev.is_some()
-              || managed::mut_ptr_eq(self.hd.expect("headless dlist?"),
-                                 nobe)) &&
-             (nobe.next.is_some()
-              || managed::mut_ptr_eq(self.tl.expect("tailless dlist?"),
-                                 nobe))) {
-            fail!("That node isn't on this dlist.")
-        }
-    }
-    fn make_mine(&self, nobe: @mut DListNode<T>) {
-        if nobe.prev.is_some() || nobe.next.is_some() || nobe.linked {
-            fail!("Cannot insert node that's already on a dlist!")
-        }
-        nobe.linked = true;
-    }
-    // Link two nodes together. If either of them are 'none', also sets
-    // the head and/or tail pointers appropriately.
-    #[inline(always)]
-    fn link(&mut self, before: DListLink<T>, after: DListLink<T>) {
-        match before {
-            Some(neighbour) => neighbour.next = after,
-            None            => self.hd        = after
-        }
-        match after {
-            Some(neighbour) => neighbour.prev = before,
-            None            => self.tl        = before
-        }
-    }
-    // Remove a node from the list.
-    fn unlink(@mut self, nobe: @mut DListNode<T>) {
-        self.assert_mine(nobe);
-        assert!(self.size > 0);
-        self.link(nobe.prev, nobe.next);
-        nobe.prev = None; // Release extraneous references.
-        nobe.next = None;
-        nobe.linked = false;
-        self.size -= 1;
-    }
-
-    fn add_head(@mut self, nobe: DListLink<T>) {
-        self.link(nobe, self.hd); // Might set tail too.
-        self.hd = nobe;
-        self.size += 1;
-    }
-    fn add_tail(@mut self, nobe: DListLink<T>) {
-        self.link(self.tl, nobe); // Might set head too.
-        self.tl = nobe;
-        self.size += 1;
-    }
-    fn insert_left(@mut self,
-                   nobe: DListLink<T>,
-                   neighbour: @mut DListNode<T>) {
-        self.assert_mine(neighbour);
-        assert!(self.size > 0);
-        self.link(neighbour.prev, nobe);
-        self.link(nobe, Some(neighbour));
-        self.size += 1;
-    }
-    fn insert_right(@mut self,
-                    neighbour: @mut DListNode<T>,
-                    nobe: DListLink<T>) {
-        self.assert_mine(neighbour);
-        assert!(self.size > 0);
-        self.link(nobe, neighbour.next);
-        self.link(Some(neighbour), nobe);
-        self.size += 1;
-    }
-}
-
-pub impl<T> DList<T> {
-    /// Get the size of the list. O(1).
-    fn len(@mut self) -> uint { self.size }
-    /// Returns true if the list is empty. O(1).
-    fn is_empty(@mut self) -> bool { self.len() == 0 }
-
-    /// Add data to the head of the list. O(1).
-    fn push_head(@mut self, data: T) {
-        self.add_head(DList::new_link(data));
-    }
-    /**
-     * Add data to the head of the list, and get the new containing
-     * node. O(1).
-     */
-    fn push_head_n(@mut self, data: T) -> @mut DListNode<T> {
-        let nobe = DList::new_link(data);
-        self.add_head(nobe);
-        nobe.get()
-    }
-    /// Add data to the tail of the list. O(1).
-    fn push(@mut self, data: T) {
-        self.add_tail(DList::new_link(data));
-    }
-    /**
-     * Add data to the tail of the list, and get the new containing
-     * node. O(1).
-     */
-    fn push_n(@mut self, data: T) -> @mut DListNode<T> {
-        let nobe = DList::new_link(data);
-        self.add_tail(nobe);
-        nobe.get()
-    }
-    /**
-     * Insert data into the middle of the list, left of the given node.
-     * O(1).
-     */
-    fn insert_before(@mut self, data: T, neighbour: @mut DListNode<T>) {
-        self.insert_left(DList::new_link(data), neighbour);
-    }
-    /**
-     * Insert an existing node in the middle of the list, left of the
-     * given node. O(1).
-     */
-    fn insert_n_before(@mut self,
-                       nobe: @mut DListNode<T>,
-                       neighbour: @mut DListNode<T>) {
-        self.make_mine(nobe);
-        self.insert_left(Some(nobe), neighbour);
-    }
-    /**
-     * Insert data in the middle of the list, left of the given node,
-     * and get its containing node. O(1).
-     */
-    fn insert_before_n(
-        @mut self,
-        data: T,
-        neighbour: @mut DListNode<T>
-    ) -> @mut DListNode<T> {
-        let nobe = DList::new_link(data);
-        self.insert_left(nobe, neighbour);
-        nobe.get()
-    }
-    /**
-     * Insert data into the middle of the list, right of the given node.
-     * O(1).
-     */
-    fn insert_after(@mut self, data: T, neighbour: @mut DListNode<T>) {
-        self.insert_right(neighbour, DList::new_link(data));
-    }
-    /**
-     * Insert an existing node in the middle of the list, right of the
-     * given node. O(1).
-     */
-    fn insert_n_after(@mut self,
-                      nobe: @mut DListNode<T>,
-                      neighbour: @mut DListNode<T>) {
-        self.make_mine(nobe);
-        self.insert_right(neighbour, Some(nobe));
-    }
-    /**
-     * Insert data in the middle of the list, right of the given node,
-     * and get its containing node. O(1).
-     */
-    fn insert_after_n(
-        @mut self,
-        data: T,
-        neighbour: @mut DListNode<T>
-    ) -> @mut DListNode<T> {
-        let nobe = DList::new_link(data);
-        self.insert_right(neighbour, nobe);
-        nobe.get()
-    }
-
-    /// Remove a node from the head of the list. O(1).
-    fn pop_n(@mut self) -> DListLink<T> {
-        let hd = self.peek_n();
-        hd.map(|nobe| self.unlink(*nobe));
-        hd
-    }
-    /// Remove a node from the tail of the list. O(1).
-    fn pop_tail_n(@mut self) -> DListLink<T> {
-        let tl = self.peek_tail_n();
-        tl.map(|nobe| self.unlink(*nobe));
-        tl
-    }
-    /// Get the node at the list's head. O(1).
-    fn peek_n(@mut self) -> DListLink<T> { self.hd }
-    /// Get the node at the list's tail. O(1).
-    fn peek_tail_n(@mut self) -> DListLink<T> { self.tl }
-
-    /// Get the node at the list's head, failing if empty. O(1).
-    fn head_n(@mut self) -> @mut DListNode<T> {
-        match self.hd {
-            Some(nobe) => nobe,
-            None       => fail!("Attempted to get the head of an empty dlist.")
-        }
-    }
-    /// Get the node at the list's tail, failing if empty. O(1).
-    fn tail_n(@mut self) -> @mut DListNode<T> {
-        match self.tl {
-            Some(nobe) => nobe,
-            None       => fail!("Attempted to get the tail of an empty dlist.")
-        }
-    }
-
-    /// Remove a node from anywhere in the list. O(1).
-    fn remove(@mut self, nobe: @mut DListNode<T>) { self.unlink(nobe); }
-
-    /**
-     * Empty another list onto the end of this list, joining this list's tail
-     * to the other list's head. O(1).
-     */
-    fn append(@mut self, them: @mut DList<T>) {
-        if managed::mut_ptr_eq(self, them) {
-            fail!("Cannot append a dlist to itself!")
-        }
-        if them.len() > 0 {
-            self.link(self.tl, them.hd);
-            self.tl    = them.tl;
-            self.size += them.size;
-            them.size  = 0;
-            them.hd    = None;
-            them.tl    = None;
-        }
-    }
-    /**
-     * Empty another list onto the start of this list, joining the other
-     * list's tail to this list's head. O(1).
-     */
-    fn prepend(@mut self, them: @mut DList<T>) {
-        if managed::mut_ptr_eq(self, them) {
-            fail!("Cannot prepend a dlist to itself!")
-        }
-        if them.len() > 0 {
-            self.link(them.tl, self.hd);
-            self.hd    = them.hd;
-            self.size += them.size;
-            them.size  = 0;
-            them.hd    = None;
-            them.tl    = None;
-        }
-    }
-
-    /// Reverse the list's elements in place. O(n).
-    fn reverse(@mut self) {
-        do self.hd.while_some |nobe| {
-            let next_nobe = nobe.next;
-            self.remove(nobe);
-            self.make_mine(nobe);
-            self.add_head(Some(nobe));
-            next_nobe
-        }
-    }
-
-    /**
-     * Remove everything from the list. This is important because the cyclic
-     * links won't otherwise be automatically refcounted-collected. O(n).
-     */
-    fn clear(@mut self) {
-        // Cute as it would be to simply detach the list and proclaim "O(1)!",
-        // the GC would still be a hidden O(n). Better to be honest about it.
-        while !self.is_empty() {
-            let _ = self.pop_n();
-        }
-    }
-
-    /// Iterate over nodes.
-    fn each_node(@mut self, f: &fn(@mut DListNode<T>) -> bool) -> bool {
-        let mut link = self.peek_n();
-        while link.is_some() {
-            let nobe = link.get();
-            if !f(nobe) { return false; }
-            link = nobe.next_link();
-        }
-        return true;
-    }
-
-    /// Check data structure integrity. O(n).
-    fn assert_consistent(@mut self) {
-        if self.hd.is_none() || self.tl.is_none() {
-            assert!(self.hd.is_none() && self.tl.is_none());
-        }
-        // iterate forwards
-        let mut count = 0;
-        let mut link = self.peek_n();
-        let mut rabbit = link;
-        while link.is_some() {
-            let nobe = link.get();
-            assert!(nobe.linked);
-            // check cycle
-            if rabbit.is_some() {
-                rabbit = rabbit.get().next;
-            }
-            if rabbit.is_some() {
-                rabbit = rabbit.get().next;
-            }
-            if rabbit.is_some() {
-                assert!(!managed::mut_ptr_eq(rabbit.get(), nobe));
-            }
-            // advance
-            link = nobe.next_link();
-            count += 1;
-        }
-        assert_eq!(count, self.len());
-        // iterate backwards - some of this is probably redundant.
-        link = self.peek_tail_n();
-        rabbit = link;
-        while link.is_some() {
-            let nobe = link.get();
-            assert!(nobe.linked);
-            // check cycle
-            if rabbit.is_some() {
-                rabbit = rabbit.get().prev;
-            }
-            if rabbit.is_some() {
-                rabbit = rabbit.get().prev;
-            }
-            if rabbit.is_some() {
-                assert!(!managed::mut_ptr_eq(rabbit.get(), nobe));
-            }
-            // advance
-            link = nobe.prev_link();
-            count -= 1;
-        }
-        assert_eq!(count, 0);
-    }
-}
-
-pub impl<T:Copy> DList<T> {
-    /// Remove data from the head of the list. O(1).
-    fn pop(@mut self) -> Option<T> {
-        self.pop_n().map(|nobe| nobe.data)
-    }
-
-    /// Remove data from the tail of the list. O(1).
-    fn pop_tail(@mut self) -> Option<T> {
-        self.pop_tail_n().map(|nobe| nobe.data)
-    }
-
-    /// Get data at the list's head. O(1).
-    fn peek(@mut self) -> Option<T> {
-        self.peek_n().map(|nobe| nobe.data)
-    }
-
-    /// Get data at the list's tail. O(1).
-    fn peek_tail(@mut self) -> Option<T> {
-        self.peek_tail_n().map (|nobe| nobe.data)
-    }
-
-    /// Get data at the list's head, failing if empty. O(1).
-    fn head(@mut self) -> T { self.head_n().data }
-
-    /// Get data at the list's tail, failing if empty. O(1).
-    fn tail(@mut self) -> T { self.tail_n().data }
-
-    /// Get the elements of the list as a vector. O(n).
-    fn to_vec(@mut self) -> ~[T] {
-        let mut v = vec::with_capacity(self.size);
-        for old_iter::eachi(&self) |index,data| {
-            v[index] = *data;
-        }
-        v
-    }
-}
-
-impl<T> BaseIter<T> for @mut DList<T> {
-    /**
-     * Iterates through the current contents.
-     *
-     * Attempts to access this dlist during iteration are allowed (to
-     * allow for e.g. breadth-first search with in-place enqueues), but
-     * removing the current node is forbidden.
-     */
-    fn each(&self, f: &fn(v: &T) -> bool) -> bool {
-        let mut link = self.peek_n();
-        while link.is_some() {
-            let nobe = link.get();
-            assert!(nobe.linked);
-
-            {
-                let frozen_nobe = &*nobe;
-                if !f(&frozen_nobe.data) { return false; }
-            }
-
-            // Check (weakly) that the user didn't do a remove.
-            if self.size == 0 {
-                fail!("The dlist became empty during iteration??")
-            }
-            if !nobe.linked ||
-                (!((nobe.prev.is_some()
-                    || managed::mut_ptr_eq(self.hd.expect("headless dlist?"),
-                                           nobe))
-                   && (nobe.next.is_some()
-                    || managed::mut_ptr_eq(self.tl.expect("tailless dlist?"),
-                                           nobe)))) {
-                fail!("Removing a dlist node during iteration is forbidden!")
-            }
-            link = nobe.next_link();
-        }
-        return true;
-    }
-
-    #[inline(always)]
-    fn size_hint(&self) -> Option<uint> { Some(self.len()) }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn test_dlist_concat() {
-        let a = from_vec(~[1,2]);
-        let b = from_vec(~[3,4]);
-        let c = from_vec(~[5,6]);
-        let d = from_vec(~[7,8]);
-        let ab = from_vec(~[a,b]);
-        let cd = from_vec(~[c,d]);
-        let abcd = concat(concat(from_vec(~[ab,cd])));
-        abcd.assert_consistent(); assert_eq!(abcd.len(), 8);
-        abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 1);
-        abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 2);
-        abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 3);
-        abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 4);
-        abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 5);
-        abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 6);
-        abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 7);
-        abcd.assert_consistent(); assert_eq!(abcd.pop().get(), 8);
-        abcd.assert_consistent(); assert!(abcd.is_empty());
-    }
-    #[test]
-    fn test_dlist_append() {
-        let a = from_vec(~[1,2,3]);
-        let b = from_vec(~[4,5,6]);
-        a.append(b);
-        assert_eq!(a.len(), 6);
-        assert_eq!(b.len(), 0);
-        b.assert_consistent();
-        a.assert_consistent(); assert_eq!(a.pop().get(), 1);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 2);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 3);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 4);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 5);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 6);
-        a.assert_consistent(); assert!(a.is_empty());
-    }
-    #[test]
-    fn test_dlist_append_empty() {
-        let a = from_vec(~[1,2,3]);
-        let b = DList::<int>();
-        a.append(b);
-        assert_eq!(a.len(), 3);
-        assert_eq!(b.len(), 0);
-        b.assert_consistent();
-        a.assert_consistent(); assert_eq!(a.pop().get(), 1);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 2);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 3);
-        a.assert_consistent(); assert!(a.is_empty());
-    }
-    #[test]
-    fn test_dlist_append_to_empty() {
-        let a = DList::<int>();
-        let b = from_vec(~[4,5,6]);
-        a.append(b);
-        assert_eq!(a.len(), 3);
-        assert_eq!(b.len(), 0);
-        b.assert_consistent();
-        a.assert_consistent(); assert_eq!(a.pop().get(), 4);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 5);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 6);
-        a.assert_consistent(); assert!(a.is_empty());
-    }
-    #[test]
-    fn test_dlist_append_two_empty() {
-        let a = DList::<int>();
-        let b = DList::<int>();
-        a.append(b);
-        assert_eq!(a.len(), 0);
-        assert_eq!(b.len(), 0);
-        b.assert_consistent();
-        a.assert_consistent();
-    }
-    #[test]
-    #[ignore(cfg(windows))]
-    #[should_fail]
-    fn test_dlist_append_self() {
-        let a = DList::<int>();
-        a.append(a);
-    }
-    #[test]
-    #[ignore(cfg(windows))]
-    #[should_fail]
-    fn test_dlist_prepend_self() {
-        let a = DList::<int>();
-        a.prepend(a);
-    }
-    #[test]
-    fn test_dlist_prepend() {
-        let a = from_vec(~[1,2,3]);
-        let b = from_vec(~[4,5,6]);
-        b.prepend(a);
-        assert_eq!(a.len(), 0);
-        assert_eq!(b.len(), 6);
-        a.assert_consistent();
-        b.assert_consistent(); assert_eq!(b.pop().get(), 1);
-        b.assert_consistent(); assert_eq!(b.pop().get(), 2);
-        b.assert_consistent(); assert_eq!(b.pop().get(), 3);
-        b.assert_consistent(); assert_eq!(b.pop().get(), 4);
-        b.assert_consistent(); assert_eq!(b.pop().get(), 5);
-        b.assert_consistent(); assert_eq!(b.pop().get(), 6);
-        b.assert_consistent(); assert!(b.is_empty());
-    }
-    #[test]
-    fn test_dlist_reverse() {
-        let a = from_vec(~[5,4,3,2,1]);
-        a.reverse();
-        assert_eq!(a.len(), 5);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 1);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 2);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 3);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 4);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 5);
-        a.assert_consistent(); assert!(a.is_empty());
-    }
-    #[test]
-    fn test_dlist_reverse_empty() {
-        let a = DList::<int>();
-        a.reverse();
-        assert_eq!(a.len(), 0);
-        a.assert_consistent();
-    }
-    #[test]
-    fn test_dlist_each_node() {
-        let a = from_vec(~[1,2,4,5]);
-        for a.each_node |nobe| {
-            if nobe.data > 3 {
-                a.insert_before(3, nobe);
-            }
-        }
-        assert_eq!(a.len(), 6);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 1);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 2);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 3);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 4);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 3);
-        a.assert_consistent(); assert_eq!(a.pop().get(), 5);
-        a.assert_consistent(); assert!(a.is_empty());
-    }
-    #[test]
-    fn test_dlist_clear() {
-        let a = from_vec(~[5,4,3,2,1]);
-        a.clear();
-        assert_eq!(a.len(), 0);
-        a.assert_consistent();
-    }
-    #[test]
-    fn test_dlist_is_empty() {
-        let empty = DList::<int>();
-        let full1 = from_vec(~[1,2,3]);
-        assert!(empty.is_empty());
-        assert!(!full1.is_empty());
-    }
-    #[test]
-    fn test_dlist_head_tail() {
-        let l = from_vec(~[1,2,3]);
-        assert_eq!(l.head(), 1);
-        assert_eq!(l.tail(), 3);
-        assert_eq!(l.len(), 3);
-    }
-    #[test]
-    fn test_dlist_pop() {
-        let l = from_vec(~[1,2,3]);
-        assert_eq!(l.pop().get(), 1);
-        assert_eq!(l.tail(), 3);
-        assert_eq!(l.head(), 2);
-        assert_eq!(l.pop().get(), 2);
-        assert_eq!(l.tail(), 3);
-        assert_eq!(l.head(), 3);
-        assert_eq!(l.pop().get(), 3);
-        assert!(l.is_empty());
-        assert!(l.pop().is_none());
-    }
-    #[test]
-    fn test_dlist_pop_tail() {
-        let l = from_vec(~[1,2,3]);
-        assert_eq!(l.pop_tail().get(), 3);
-        assert_eq!(l.tail(), 2);
-        assert_eq!(l.head(), 1);
-        assert_eq!(l.pop_tail().get(), 2);
-        assert_eq!(l.tail(), 1);
-        assert_eq!(l.head(), 1);
-        assert_eq!(l.pop_tail().get(), 1);
-        assert!(l.is_empty());
-        assert!(l.pop_tail().is_none());
-    }
-    #[test]
-    fn test_dlist_push() {
-        let l = DList::<int>();
-        l.push(1);
-        assert_eq!(l.head(), 1);
-        assert_eq!(l.tail(), 1);
-        l.push(2);
-        assert_eq!(l.head(), 1);
-        assert_eq!(l.tail(), 2);
-        l.push(3);
-        assert_eq!(l.head(), 1);
-        assert_eq!(l.tail(), 3);
-        assert_eq!(l.len(), 3);
-    }
-    #[test]
-    fn test_dlist_push_head() {
-        let l = DList::<int>();
-        l.push_head(3);
-        assert_eq!(l.head(), 3);
-        assert_eq!(l.tail(), 3);
-        l.push_head(2);
-        assert_eq!(l.head(), 2);
-        assert_eq!(l.tail(), 3);
-        l.push_head(1);
-        assert_eq!(l.head(), 1);
-        assert_eq!(l.tail(), 3);
-        assert_eq!(l.len(), 3);
-    }
-    #[test]
-    fn test_dlist_foldl() {
-        let l = from_vec(vec::from_fn(101, |x|x));
-        assert_eq!(old_iter::foldl(&l, 0, |accum,elem| *accum+*elem), 5050);
-    }
-    #[test]
-    fn test_dlist_break_early() {
-        let l = from_vec(~[1,2,3,4,5]);
-        let mut x = 0;
-        for l.each |i| {
-            x += 1;
-            if (*i == 3) { break; }
-        }
-        assert_eq!(x, 3);
-    }
-    #[test]
-    fn test_dlist_remove_head() {
-        let l = DList::<int>();
-        l.assert_consistent(); let one = l.push_n(1);
-        l.assert_consistent(); let _two = l.push_n(2);
-        l.assert_consistent(); let _three = l.push_n(3);
-        l.assert_consistent(); assert_eq!(l.len(), 3);
-        l.assert_consistent(); l.remove(one);
-        l.assert_consistent(); assert_eq!(l.len(), 2);
-        l.assert_consistent(); assert_eq!(l.head(), 2);
-        l.assert_consistent(); assert_eq!(l.tail(), 3);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 2);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 3);
-        l.assert_consistent(); assert!(l.is_empty());
-    }
-    #[test]
-    fn test_dlist_remove_mid() {
-        let l = DList::<int>();
-        l.assert_consistent(); let _one = l.push_n(1);
-        l.assert_consistent(); let two = l.push_n(2);
-        l.assert_consistent(); let _three = l.push_n(3);
-        l.assert_consistent(); assert_eq!(l.len(), 3);
-        l.assert_consistent(); l.remove(two);
-        l.assert_consistent(); assert_eq!(l.len(), 2);
-        l.assert_consistent(); assert_eq!(l.head(), 1);
-        l.assert_consistent(); assert_eq!(l.tail(), 3);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 1);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 3);
-        l.assert_consistent(); assert!(l.is_empty());
-    }
-    #[test]
-    fn test_dlist_remove_tail() {
-        let l = DList::<int>();
-        l.assert_consistent(); let _one = l.push_n(1);
-        l.assert_consistent(); let _two = l.push_n(2);
-        l.assert_consistent(); let three = l.push_n(3);
-        l.assert_consistent(); assert_eq!(l.len(), 3);
-        l.assert_consistent(); l.remove(three);
-        l.assert_consistent(); assert_eq!(l.len(), 2);
-        l.assert_consistent(); assert_eq!(l.head(), 1);
-        l.assert_consistent(); assert_eq!(l.tail(), 2);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 1);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 2);
-        l.assert_consistent(); assert!(l.is_empty());
-    }
-    #[test]
-    fn test_dlist_remove_one_two() {
-        let l = DList::<int>();
-        l.assert_consistent(); let one = l.push_n(1);
-        l.assert_consistent(); let two = l.push_n(2);
-        l.assert_consistent(); let _three = l.push_n(3);
-        l.assert_consistent(); assert_eq!(l.len(), 3);
-        l.assert_consistent(); l.remove(one);
-        l.assert_consistent(); l.remove(two);
-        // and through and through, the vorpal blade went snicker-snack
-        l.assert_consistent(); assert_eq!(l.len(), 1);
-        l.assert_consistent(); assert_eq!(l.head(), 3);
-        l.assert_consistent(); assert_eq!(l.tail(), 3);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 3);
-        l.assert_consistent(); assert!(l.is_empty());
-    }
-    #[test]
-    fn test_dlist_remove_one_three() {
-        let l = DList::<int>();
-        l.assert_consistent(); let one = l.push_n(1);
-        l.assert_consistent(); let _two = l.push_n(2);
-        l.assert_consistent(); let three = l.push_n(3);
-        l.assert_consistent(); assert_eq!(l.len(), 3);
-        l.assert_consistent(); l.remove(one);
-        l.assert_consistent(); l.remove(three);
-        l.assert_consistent(); assert_eq!(l.len(), 1);
-        l.assert_consistent(); assert_eq!(l.head(), 2);
-        l.assert_consistent(); assert_eq!(l.tail(), 2);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 2);
-        l.assert_consistent(); assert!(l.is_empty());
-    }
-    #[test]
-    fn test_dlist_remove_two_three() {
-        let l = DList::<int>();
-        l.assert_consistent(); let _one = l.push_n(1);
-        l.assert_consistent(); let two = l.push_n(2);
-        l.assert_consistent(); let three = l.push_n(3);
-        l.assert_consistent(); assert_eq!(l.len(), 3);
-        l.assert_consistent(); l.remove(two);
-        l.assert_consistent(); l.remove(three);
-        l.assert_consistent(); assert_eq!(l.len(), 1);
-        l.assert_consistent(); assert_eq!(l.head(), 1);
-        l.assert_consistent(); assert_eq!(l.tail(), 1);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 1);
-        l.assert_consistent(); assert!(l.is_empty());
-    }
-    #[test]
-    fn test_dlist_remove_all() {
-        let l = DList::<int>();
-        l.assert_consistent(); let one = l.push_n(1);
-        l.assert_consistent(); let two = l.push_n(2);
-        l.assert_consistent(); let three = l.push_n(3);
-        l.assert_consistent(); assert_eq!(l.len(), 3);
-        l.assert_consistent(); l.remove(two);
-        l.assert_consistent(); l.remove(three);
-        l.assert_consistent(); l.remove(one); // Twenty-three is number one!
-        l.assert_consistent(); assert!(l.peek().is_none());
-        l.assert_consistent(); assert!(l.is_empty());
-    }
-    #[test]
-    fn test_dlist_insert_n_before() {
-        let l = DList::<int>();
-        l.assert_consistent(); let _one = l.push_n(1);
-        l.assert_consistent(); let two = l.push_n(2);
-        l.assert_consistent(); let three = new_dlist_node(3);
-        l.assert_consistent(); assert_eq!(l.len(), 2);
-        l.assert_consistent(); l.insert_n_before(three, two);
-        l.assert_consistent(); assert_eq!(l.len(), 3);
-        l.assert_consistent(); assert_eq!(l.head(), 1);
-        l.assert_consistent(); assert_eq!(l.tail(), 2);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 1);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 3);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 2);
-        l.assert_consistent(); assert!(l.is_empty());
-    }
-    #[test]
-    fn test_dlist_insert_n_after() {
-        let l = DList::<int>();
-        l.assert_consistent(); let one = l.push_n(1);
-        l.assert_consistent(); let _two = l.push_n(2);
-        l.assert_consistent(); let three = new_dlist_node(3);
-        l.assert_consistent(); assert_eq!(l.len(), 2);
-        l.assert_consistent(); l.insert_n_after(three, one);
-        l.assert_consistent(); assert_eq!(l.len(), 3);
-        l.assert_consistent(); assert_eq!(l.head(), 1);
-        l.assert_consistent(); assert_eq!(l.tail(), 2);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 1);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 3);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 2);
-        l.assert_consistent(); assert!(l.is_empty());
-    }
-    #[test]
-    fn test_dlist_insert_before_head() {
-        let l = DList::<int>();
-        l.assert_consistent(); let one = l.push_n(1);
-        l.assert_consistent(); let _two = l.push_n(2);
-        l.assert_consistent(); assert_eq!(l.len(), 2);
-        l.assert_consistent(); l.insert_before(3, one);
-        l.assert_consistent(); assert_eq!(l.len(), 3);
-        l.assert_consistent(); assert_eq!(l.head(), 3);
-        l.assert_consistent(); assert_eq!(l.tail(), 2);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 3);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 1);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 2);
-        l.assert_consistent(); assert!(l.is_empty());
-    }
-    #[test]
-    fn test_dlist_insert_after_tail() {
-        let l = DList::<int>();
-        l.assert_consistent(); let _one = l.push_n(1);
-        l.assert_consistent(); let two = l.push_n(2);
-        l.assert_consistent(); assert_eq!(l.len(), 2);
-        l.assert_consistent(); l.insert_after(3, two);
-        l.assert_consistent(); assert_eq!(l.len(), 3);
-        l.assert_consistent(); assert_eq!(l.head(), 1);
-        l.assert_consistent(); assert_eq!(l.tail(), 3);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 1);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 2);
-        l.assert_consistent(); assert_eq!(l.pop().get(), 3);
-        l.assert_consistent(); assert!(l.is_empty());
-    }
-    #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_dlist_asymmetric_link() {
-        let l = DList::<int>();
-        let _one = l.push_n(1);
-        let two = l.push_n(2);
-        two.prev = None;
-        l.assert_consistent();
-    }
-    #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_dlist_cyclic_list() {
-        let l = DList::<int>();
-        let one = l.push_n(1);
-        let _two = l.push_n(2);
-        let three = l.push_n(3);
-        three.next = Some(one);
-        one.prev = Some(three);
-        l.assert_consistent();
-    }
-    #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_dlist_headless() {
-        DList::<int>().head();
-    }
-    #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_dlist_insert_already_present_before() {
-        let l = DList::<int>();
-        let one = l.push_n(1);
-        let two = l.push_n(2);
-        l.insert_n_before(two, one);
-    }
-    #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_dlist_insert_already_present_after() {
-        let l = DList::<int>();
-        let one = l.push_n(1);
-        let two = l.push_n(2);
-        l.insert_n_after(one, two);
-    }
-    #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_dlist_insert_before_orphan() {
-        let l = DList::<int>();
-        let one = new_dlist_node(1);
-        let two = new_dlist_node(2);
-        l.insert_n_before(one, two);
-    }
-    #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_dlist_insert_after_orphan() {
-        let l = DList::<int>();
-        let one = new_dlist_node(1);
-        let two = new_dlist_node(2);
-        l.insert_n_after(two, one);
-    }
-}
diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs
deleted file mode 100644
index a7c18ebf5cd..00000000000
--- a/src/libstd/ebml.rs
+++ /dev/null
@@ -1,957 +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.
-
-// Simple Extensible Binary Markup Language (ebml) reader and writer on a
-// cursor model. See the specification here:
-//     http://www.matroska.org/technical/specs/rfc/index.html
-
-// Common data structures
-struct EbmlTag {
-    id: uint,
-    size: uint,
-}
-
-struct EbmlState {
-    ebml_tag: EbmlTag,
-    tag_pos: uint,
-    data_pos: uint,
-}
-
-pub struct Doc {
-    data: @~[u8],
-    start: uint,
-    end: uint,
-}
-
-pub struct TaggedDoc {
-    tag: uint,
-    doc: Doc,
-}
-
-pub enum EbmlEncoderTag {
-    EsUint,     // 0
-    EsU64,      // 1
-    EsU32,      // 2
-    EsU16,      // 3
-    EsU8,       // 4
-    EsInt,      // 5
-    EsI64,      // 6
-    EsI32,      // 7
-    EsI16,      // 8
-    EsI8,       // 9
-    EsBool,     // 10
-    EsStr,      // 11
-    EsF64,      // 12
-    EsF32,      // 13
-    EsFloat,    // 14
-    EsEnum,     // 15
-    EsEnumVid,  // 16
-    EsEnumBody, // 17
-    EsVec,      // 18
-    EsVecLen,   // 19
-    EsVecElt,   // 20
-
-    EsOpaque,
-
-    EsLabel // Used only when debugging
-}
-// --------------------------------------
-
-pub mod reader {
-    use ebml::{Doc, EbmlEncoderTag, EsBool, EsEnum, EsEnumBody, EsEnumVid};
-    use ebml::{EsI16, EsI32, EsI64, EsI8, EsInt};
-    use ebml::{EsLabel, EsOpaque, EsStr, EsU16, EsU32, EsU64, EsU8, EsUint};
-    use ebml::{EsVec, EsVecElt, EsVecLen, TaggedDoc};
-    use serialize;
-
-    use core::cast::transmute;
-    use core::int;
-    use core::io;
-    use core::ptr::offset;
-    use core::str;
-    use core::unstable::intrinsics::bswap32;
-    use core::vec;
-
-    // ebml reading
-
-    pub impl Doc {
-        fn get(&self, tag: uint) -> Doc {
-            get_doc(*self, tag)
-        }
-    }
-
-    struct Res {
-        val: uint,
-        next: uint
-    }
-
-    #[inline(never)]
-    fn vuint_at_slow(data: &[u8], start: uint) -> Res {
-        let a = data[start];
-        if a & 0x80u8 != 0u8 {
-            return Res {val: (a & 0x7fu8) as uint, next: start + 1u};
-        }
-        if a & 0x40u8 != 0u8 {
-            return Res {val: ((a & 0x3fu8) as uint) << 8u |
-                        (data[start + 1u] as uint),
-                    next: start + 2u};
-        }
-        if a & 0x20u8 != 0u8 {
-            return Res {val: ((a & 0x1fu8) as uint) << 16u |
-                        (data[start + 1u] as uint) << 8u |
-                        (data[start + 2u] as uint),
-                    next: start + 3u};
-        }
-        if a & 0x10u8 != 0u8 {
-            return Res {val: ((a & 0x0fu8) as uint) << 24u |
-                        (data[start + 1u] as uint) << 16u |
-                        (data[start + 2u] as uint) << 8u |
-                        (data[start + 3u] as uint),
-                    next: start + 4u};
-        }
-        fail!("vint too big");
-    }
-
-    #[cfg(target_arch = "x86")]
-    #[cfg(target_arch = "x86_64")]
-    pub fn vuint_at(data: &[u8], start: uint) -> Res {
-        if data.len() - start < 4 {
-            return vuint_at_slow(data, start);
-        }
-
-        unsafe {
-            let (ptr, _): (*u8, uint) = transmute(data);
-            let ptr = offset(ptr, start);
-            let ptr: *i32 = transmute(ptr);
-            let val = bswap32(*ptr);
-            let val: u32 = transmute(val);
-            if (val & 0x80000000) != 0 {
-                Res {
-                    val: ((val >> 24) & 0x7f) as uint,
-                    next: start + 1
-                }
-            } else if (val & 0x40000000) != 0 {
-                Res {
-                    val: ((val >> 16) & 0x3fff) as uint,
-                    next: start + 2
-                }
-            } else if (val & 0x20000000) != 0 {
-                Res {
-                    val: ((val >> 8) & 0x1fffff) as uint,
-                    next: start + 3
-                }
-            } else {
-                Res {
-                    val: (val & 0x0fffffff) as uint,
-                    next: start + 4
-                }
-            }
-        }
-    }
-
-    #[cfg(target_arch = "arm")]
-    #[cfg(target_arch = "mips")]
-    pub fn vuint_at(data: &[u8], start: uint) -> Res {
-        vuint_at_slow(data, start)
-    }
-
-    pub fn Doc(data: @~[u8]) -> Doc {
-        Doc { data: data, start: 0u, end: vec::len::<u8>(*data) }
-    }
-
-    pub fn doc_at(data: @~[u8], start: uint) -> TaggedDoc {
-        let elt_tag = vuint_at(*data, start);
-        let elt_size = vuint_at(*data, elt_tag.next);
-        let end = elt_size.next + elt_size.val;
-        TaggedDoc {
-            tag: elt_tag.val,
-            doc: Doc { data: data, start: elt_size.next, end: end }
-        }
-    }
-
-    pub fn maybe_get_doc(d: Doc, tg: uint) -> Option<Doc> {
-        let mut pos = d.start;
-        while pos < d.end {
-            let elt_tag = vuint_at(*d.data, pos);
-            let elt_size = vuint_at(*d.data, elt_tag.next);
-            pos = elt_size.next + elt_size.val;
-            if elt_tag.val == tg {
-                return Some(Doc { data: d.data, start: elt_size.next,
-                                  end: pos });
-            }
-        }
-        None
-    }
-
-    pub fn get_doc(d: Doc, tg: uint) -> Doc {
-        match maybe_get_doc(d, tg) {
-            Some(d) => d,
-            None => {
-                error!("failed to find block with tag %u", tg);
-                fail!();
-            }
-        }
-    }
-
-    pub fn docs(d: Doc, it: &fn(uint, Doc) -> bool) -> bool {
-        let mut pos = d.start;
-        while pos < d.end {
-            let elt_tag = vuint_at(*d.data, pos);
-            let elt_size = vuint_at(*d.data, elt_tag.next);
-            pos = elt_size.next + elt_size.val;
-            let doc = Doc { data: d.data, start: elt_size.next, end: pos };
-            if !it(elt_tag.val, doc) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    pub fn tagged_docs(d: Doc, tg: uint, it: &fn(Doc) -> bool) -> bool {
-        let mut pos = d.start;
-        while pos < d.end {
-            let elt_tag = vuint_at(*d.data, pos);
-            let elt_size = vuint_at(*d.data, elt_tag.next);
-            pos = elt_size.next + elt_size.val;
-            if elt_tag.val == tg {
-                let doc = Doc { data: d.data, start: elt_size.next,
-                                end: pos };
-                if !it(doc) {
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    pub fn doc_data(d: Doc) -> ~[u8] {
-        vec::slice::<u8>(*d.data, d.start, d.end).to_vec()
-    }
-
-    pub fn with_doc_data<T>(d: Doc, f: &fn(x: &[u8]) -> T) -> T {
-        f(vec::slice(*d.data, d.start, d.end))
-    }
-
-    pub fn doc_as_str(d: Doc) -> ~str { str::from_bytes(doc_data(d)) }
-
-    pub fn doc_as_u8(d: Doc) -> u8 {
-        assert_eq!(d.end, d.start + 1u);
-        (*d.data)[d.start]
-    }
-
-    pub fn doc_as_u16(d: Doc) -> u16 {
-        assert_eq!(d.end, d.start + 2u);
-        io::u64_from_be_bytes(*d.data, d.start, 2u) as u16
-    }
-
-    pub fn doc_as_u32(d: Doc) -> u32 {
-        assert_eq!(d.end, d.start + 4u);
-        io::u64_from_be_bytes(*d.data, d.start, 4u) as u32
-    }
-
-    pub fn doc_as_u64(d: Doc) -> u64 {
-        assert_eq!(d.end, d.start + 8u);
-        io::u64_from_be_bytes(*d.data, d.start, 8u)
-    }
-
-    pub fn doc_as_i8(d: Doc) -> i8 { doc_as_u8(d) as i8 }
-    pub fn doc_as_i16(d: Doc) -> i16 { doc_as_u16(d) as i16 }
-    pub fn doc_as_i32(d: Doc) -> i32 { doc_as_u32(d) as i32 }
-    pub fn doc_as_i64(d: Doc) -> i64 { doc_as_u64(d) as i64 }
-
-    pub struct Decoder {
-        priv parent: Doc,
-        priv pos: uint,
-    }
-
-    pub fn Decoder(d: Doc) -> Decoder {
-        Decoder {
-            parent: d,
-            pos: d.start
-        }
-    }
-
-    priv impl Decoder {
-        fn _check_label(&mut self, lbl: &str) {
-            if self.pos < self.parent.end {
-                let TaggedDoc { tag: r_tag, doc: r_doc } =
-                    doc_at(self.parent.data, self.pos);
-
-                if r_tag == (EsLabel as uint) {
-                    self.pos = r_doc.end;
-                    let str = doc_as_str(r_doc);
-                    if lbl != str {
-                        fail!("Expected label %s but found %s", lbl, str);
-                    }
-                }
-            }
-        }
-
-        fn next_doc(&mut self, exp_tag: EbmlEncoderTag) -> Doc {
-            debug!(". next_doc(exp_tag=%?)", exp_tag);
-            if self.pos >= self.parent.end {
-                fail!("no more documents in current node!");
-            }
-            let TaggedDoc { tag: r_tag, doc: r_doc } =
-                doc_at(self.parent.data, self.pos);
-            debug!("self.parent=%?-%? self.pos=%? r_tag=%? r_doc=%?-%?",
-                   copy self.parent.start, copy self.parent.end,
-                   copy self.pos, r_tag, r_doc.start, r_doc.end);
-            if r_tag != (exp_tag as uint) {
-                fail!("expected EBML doc with tag %? but found tag %?", exp_tag, r_tag);
-            }
-            if r_doc.end > self.parent.end {
-                fail!("invalid EBML, child extends to 0x%x, parent to 0x%x",
-                      r_doc.end, self.parent.end);
-            }
-            self.pos = r_doc.end;
-            r_doc
-        }
-
-        fn push_doc<T>(&mut self, d: Doc, f: &fn() -> T) -> T {
-            let old_parent = self.parent;
-            let old_pos = self.pos;
-            self.parent = d;
-            self.pos = d.start;
-            let r = f();
-            self.parent = old_parent;
-            self.pos = old_pos;
-            r
-        }
-
-        fn _next_uint(&mut self, exp_tag: EbmlEncoderTag) -> uint {
-            let r = doc_as_u32(self.next_doc(exp_tag));
-            debug!("_next_uint exp_tag=%? result=%?", exp_tag, r);
-            r as uint
-        }
-    }
-
-    pub impl Decoder {
-        fn read_opaque<R>(&mut self, op: &fn(&mut Decoder, Doc) -> R) -> R {
-            let doc = self.next_doc(EsOpaque);
-
-            let (old_parent, old_pos) = (self.parent, self.pos);
-            self.parent = doc;
-            self.pos = doc.start;
-
-            let result = op(self, doc);
-
-            self.parent = old_parent;
-            self.pos = old_pos;
-            result
-        }
-    }
-
-    impl serialize::Decoder for Decoder {
-        fn read_nil(&mut self) -> () { () }
-
-        fn read_u64(&mut self) -> u64 { doc_as_u64(self.next_doc(EsU64)) }
-        fn read_u32(&mut self) -> u32 { doc_as_u32(self.next_doc(EsU32)) }
-        fn read_u16(&mut self) -> u16 { doc_as_u16(self.next_doc(EsU16)) }
-        fn read_u8 (&mut self) -> u8  { doc_as_u8 (self.next_doc(EsU8 )) }
-        fn read_uint(&mut self) -> uint {
-            let v = doc_as_u64(self.next_doc(EsUint));
-            if v > (::core::uint::max_value as u64) {
-                fail!("uint %? too large for this architecture", v);
-            }
-            v as uint
-        }
-
-        fn read_i64(&mut self) -> i64 {
-            doc_as_u64(self.next_doc(EsI64)) as i64
-        }
-        fn read_i32(&mut self) -> i32 {
-            doc_as_u32(self.next_doc(EsI32)) as i32
-        }
-        fn read_i16(&mut self) -> i16 {
-            doc_as_u16(self.next_doc(EsI16)) as i16
-        }
-        fn read_i8 (&mut self) -> i8 {
-            doc_as_u8(self.next_doc(EsI8 )) as i8
-        }
-        fn read_int(&mut self) -> int {
-            let v = doc_as_u64(self.next_doc(EsInt)) as i64;
-            if v > (int::max_value as i64) || v < (int::min_value as i64) {
-                debug!("FIXME #6122: Removing this makes this function miscompile");
-                fail!("int %? out of range for this architecture", v);
-            }
-            v as int
-        }
-
-        fn read_bool(&mut self) -> bool {
-            doc_as_u8(self.next_doc(EsBool)) as bool
-        }
-
-        fn read_f64(&mut self) -> f64 { fail!("read_f64()"); }
-        fn read_f32(&mut self) -> f32 { fail!("read_f32()"); }
-        fn read_float(&mut self) -> float { fail!("read_float()"); }
-        fn read_char(&mut self) -> char { fail!("read_char()"); }
-        fn read_str(&mut self) -> ~str { doc_as_str(self.next_doc(EsStr)) }
-
-        // Compound types:
-        fn read_enum<T>(&mut self,
-                        name: &str,
-                        f: &fn(&mut Decoder) -> T)
-                        -> T {
-            debug!("read_enum(%s)", name);
-            self._check_label(name);
-
-            let doc = self.next_doc(EsEnum);
-
-            let (old_parent, old_pos) = (self.parent, self.pos);
-            self.parent = doc;
-            self.pos = self.parent.start;
-
-            let result = f(self);
-
-            self.parent = old_parent;
-            self.pos = old_pos;
-            result
-        }
-
-        fn read_enum_variant<T>(&mut self,
-                                _: &[&str],
-                                f: &fn(&mut Decoder, uint) -> T)
-                                -> T {
-            debug!("read_enum_variant()");
-            let idx = self._next_uint(EsEnumVid);
-            debug!("  idx=%u", idx);
-
-            let doc = self.next_doc(EsEnumBody);
-
-            let (old_parent, old_pos) = (self.parent, self.pos);
-            self.parent = doc;
-            self.pos = self.parent.start;
-
-            let result = f(self, idx);
-
-            self.parent = old_parent;
-            self.pos = old_pos;
-            result
-        }
-
-        fn read_enum_variant_arg<T>(&mut self,
-                                    idx: uint,
-                                    f: &fn(&mut Decoder) -> T) -> T {
-            debug!("read_enum_variant_arg(idx=%u)", idx);
-            f(self)
-        }
-
-        fn read_enum_struct_variant<T>(&mut self,
-                                       _: &[&str],
-                                       f: &fn(&mut Decoder, uint) -> T)
-                                       -> T {
-            debug!("read_enum_struct_variant()");
-            let idx = self._next_uint(EsEnumVid);
-            debug!("  idx=%u", idx);
-
-            let doc = self.next_doc(EsEnumBody);
-
-            let (old_parent, old_pos) = (self.parent, self.pos);
-            self.parent = doc;
-            self.pos = self.parent.start;
-
-            let result = f(self, idx);
-
-            self.parent = old_parent;
-            self.pos = old_pos;
-            result
-        }
-
-        fn read_enum_struct_variant_field<T>(&mut self,
-                                             name: &str,
-                                             idx: uint,
-                                             f: &fn(&mut Decoder) -> T)
-                                             -> T {
-            debug!("read_enum_struct_variant_arg(name=%?, idx=%u)", name, idx);
-            f(self)
-        }
-
-        fn read_struct<T>(&mut self,
-                          name: &str,
-                          _: uint,
-                          f: &fn(&mut Decoder) -> T)
-                          -> T {
-            debug!("read_struct(name=%s)", name);
-            f(self)
-        }
-
-        fn read_struct_field<T>(&mut self,
-                                name: &str,
-                                idx: uint,
-                                f: &fn(&mut Decoder) -> T)
-                                -> T {
-            debug!("read_struct_field(name=%?, idx=%u)", name, idx);
-            self._check_label(name);
-            f(self)
-        }
-
-        fn read_tuple<T>(&mut self, f: &fn(&mut Decoder, uint) -> T) -> T {
-            debug!("read_tuple()");
-            self.read_seq(f)
-        }
-
-        fn read_tuple_arg<T>(&mut self, idx: uint, f: &fn(&mut Decoder) -> T)
-                             -> T {
-            debug!("read_tuple_arg(idx=%u)", idx);
-            self.read_seq_elt(idx, f)
-        }
-
-        fn read_tuple_struct<T>(&mut self,
-                                name: &str,
-                                f: &fn(&mut Decoder, uint) -> T)
-                                -> T {
-            debug!("read_tuple_struct(name=%?)", name);
-            self.read_tuple(f)
-        }
-
-        fn read_tuple_struct_arg<T>(&mut self,
-                                    idx: uint,
-                                    f: &fn(&mut Decoder) -> T)
-                                    -> T {
-            debug!("read_tuple_struct_arg(idx=%u)", idx);
-            self.read_tuple_arg(idx, f)
-        }
-
-        fn read_option<T>(&mut self, f: &fn(&mut Decoder, bool) -> T) -> T {
-            debug!("read_option()");
-            do self.read_enum("Option") |this| {
-                do this.read_enum_variant(["None", "Some"]) |this, idx| {
-                    match idx {
-                        0 => f(this, false),
-                        1 => f(this, true),
-                        _ => fail!(),
-                    }
-                }
-            }
-        }
-
-        fn read_seq<T>(&mut self, f: &fn(&mut Decoder, uint) -> T) -> T {
-            debug!("read_seq()");
-            let doc = self.next_doc(EsVec);
-
-            let (old_parent, old_pos) = (self.parent, self.pos);
-            self.parent = doc;
-            self.pos = self.parent.start;
-
-            let len = self._next_uint(EsVecLen);
-            debug!("  len=%u", len);
-            let result = f(self, len);
-
-            self.parent = old_parent;
-            self.pos = old_pos;
-            result
-        }
-
-        fn read_seq_elt<T>(&mut self, idx: uint, f: &fn(&mut Decoder) -> T)
-                           -> T {
-            debug!("read_seq_elt(idx=%u)", idx);
-            let doc = self.next_doc(EsVecElt);
-
-            let (old_parent, old_pos) = (self.parent, self.pos);
-            self.parent = doc;
-            self.pos = self.parent.start;
-
-            let result = f(self);
-
-            self.parent = old_parent;
-            self.pos = old_pos;
-            result
-        }
-
-        fn read_map<T>(&mut self, _: &fn(&mut Decoder, uint) -> T) -> T {
-            debug!("read_map()");
-            fail!("read_map is unimplemented");
-        }
-
-        fn read_map_elt_key<T>(&mut self,
-                               idx: uint,
-                               _: &fn(&mut Decoder) -> T)
-                               -> T {
-            debug!("read_map_elt_key(idx=%u)", idx);
-            fail!("read_map_elt_val is unimplemented");
-        }
-
-        fn read_map_elt_val<T>(&mut self,
-                               idx: uint,
-                               _: &fn(&mut Decoder) -> T)
-                               -> T {
-            debug!("read_map_elt_val(idx=%u)", idx);
-            fail!("read_map_elt_val is unimplemented");
-        }
-    }
-}
-
-pub mod writer {
-    use ebml::{EbmlEncoderTag, EsBool, EsEnum, EsEnumBody, EsEnumVid};
-    use ebml::{EsI16, EsI32, EsI64, EsI8, EsInt};
-    use ebml::{EsLabel, EsOpaque, EsStr, EsU16, EsU32, EsU64, EsU8, EsUint};
-    use ebml::{EsVec, EsVecElt, EsVecLen};
-
-    use core::io;
-    use core::str;
-
-    // ebml writing
-    pub struct Encoder {
-        writer: @io::Writer,
-        priv size_positions: ~[uint],
-    }
-
-    fn write_sized_vuint(w: @io::Writer, n: uint, size: uint) {
-        match size {
-            1u => w.write(&[0x80u8 | (n as u8)]),
-            2u => w.write(&[0x40u8 | ((n >> 8_u) as u8), n as u8]),
-            3u => w.write(&[0x20u8 | ((n >> 16_u) as u8), (n >> 8_u) as u8,
-                            n as u8]),
-            4u => w.write(&[0x10u8 | ((n >> 24_u) as u8), (n >> 16_u) as u8,
-                            (n >> 8_u) as u8, n as u8]),
-            _ => fail!("vint to write too big: %?", n)
-        };
-    }
-
-    fn write_vuint(w: @io::Writer, n: uint) {
-        if n < 0x7f_u { write_sized_vuint(w, n, 1u); return; }
-        if n < 0x4000_u { write_sized_vuint(w, n, 2u); return; }
-        if n < 0x200000_u { write_sized_vuint(w, n, 3u); return; }
-        if n < 0x10000000_u { write_sized_vuint(w, n, 4u); return; }
-        fail!("vint to write too big: %?", n);
-    }
-
-    pub fn Encoder(w: @io::Writer) -> Encoder {
-        let size_positions: ~[uint] = ~[];
-        Encoder {
-            writer: w,
-            size_positions: size_positions
-        }
-    }
-
-    // FIXME (#2741): Provide a function to write the standard ebml header.
-    pub impl Encoder {
-        fn start_tag(&mut self, tag_id: uint) {
-            debug!("Start tag %u", tag_id);
-
-            // Write the enum ID:
-            write_vuint(self.writer, tag_id);
-
-            // Write a placeholder four-byte size.
-            self.size_positions.push(self.writer.tell());
-            let zeroes: &[u8] = &[0u8, 0u8, 0u8, 0u8];
-            self.writer.write(zeroes);
-        }
-
-        fn end_tag(&mut self) {
-            let last_size_pos = self.size_positions.pop();
-            let cur_pos = self.writer.tell();
-            self.writer.seek(last_size_pos as int, io::SeekSet);
-            let size = (cur_pos - last_size_pos - 4u);
-            write_sized_vuint(self.writer, size, 4u);
-            self.writer.seek(cur_pos as int, io::SeekSet);
-
-            debug!("End tag (size = %u)", size);
-        }
-
-        fn wr_tag(&mut self, tag_id: uint, blk: &fn()) {
-            self.start_tag(tag_id);
-            blk();
-            self.end_tag();
-        }
-
-        fn wr_tagged_bytes(&mut self, tag_id: uint, b: &[u8]) {
-            write_vuint(self.writer, tag_id);
-            write_vuint(self.writer, b.len());
-            self.writer.write(b);
-        }
-
-        fn wr_tagged_u64(&mut self, tag_id: uint, v: u64) {
-            do io::u64_to_be_bytes(v, 8u) |v| {
-                self.wr_tagged_bytes(tag_id, v);
-            }
-        }
-
-        fn wr_tagged_u32(&mut self, tag_id: uint, v: u32) {
-            do io::u64_to_be_bytes(v as u64, 4u) |v| {
-                self.wr_tagged_bytes(tag_id, v);
-            }
-        }
-
-        fn wr_tagged_u16(&mut self, tag_id: uint, v: u16) {
-            do io::u64_to_be_bytes(v as u64, 2u) |v| {
-                self.wr_tagged_bytes(tag_id, v);
-            }
-        }
-
-        fn wr_tagged_u8(&mut self, tag_id: uint, v: u8) {
-            self.wr_tagged_bytes(tag_id, &[v]);
-        }
-
-        fn wr_tagged_i64(&mut self, tag_id: uint, v: i64) {
-            do io::u64_to_be_bytes(v as u64, 8u) |v| {
-                self.wr_tagged_bytes(tag_id, v);
-            }
-        }
-
-        fn wr_tagged_i32(&mut self, tag_id: uint, v: i32) {
-            do io::u64_to_be_bytes(v as u64, 4u) |v| {
-                self.wr_tagged_bytes(tag_id, v);
-            }
-        }
-
-        fn wr_tagged_i16(&mut self, tag_id: uint, v: i16) {
-            do io::u64_to_be_bytes(v as u64, 2u) |v| {
-                self.wr_tagged_bytes(tag_id, v);
-            }
-        }
-
-        fn wr_tagged_i8(&mut self, tag_id: uint, v: i8) {
-            self.wr_tagged_bytes(tag_id, &[v as u8]);
-        }
-
-        fn wr_tagged_str(&mut self, tag_id: uint, v: &str) {
-            str::byte_slice(v, |b| self.wr_tagged_bytes(tag_id, b));
-        }
-
-        fn wr_bytes(&mut self, b: &[u8]) {
-            debug!("Write %u bytes", b.len());
-            self.writer.write(b);
-        }
-
-        fn wr_str(&mut self, s: &str) {
-            debug!("Write str: %?", s);
-            self.writer.write(str::to_bytes(s));
-        }
-    }
-
-    // FIXME (#2743): optionally perform "relaxations" on end_tag to more
-    // efficiently encode sizes; this is a fixed point iteration
-
-    // Set to true to generate more debugging in EBML code.
-    // Totally lame approach.
-    static debug: bool = true;
-
-    priv impl Encoder {
-        // used internally to emit things like the vector length and so on
-        fn _emit_tagged_uint(&mut self, t: EbmlEncoderTag, v: uint) {
-            assert!(v <= 0xFFFF_FFFF_u);
-            self.wr_tagged_u32(t as uint, v as u32);
-        }
-
-        fn _emit_label(&mut self, label: &str) {
-            // There are various strings that we have access to, such as
-            // the name of a record field, which do not actually appear in
-            // the encoded EBML (normally).  This is just for
-            // efficiency.  When debugging, though, we can emit such
-            // labels and then they will be checked by decoder to
-            // try and check failures more quickly.
-            if debug { self.wr_tagged_str(EsLabel as uint, label) }
-        }
-    }
-
-    pub impl Encoder {
-        fn emit_opaque(&mut self, f: &fn(&mut Encoder)) {
-            self.start_tag(EsOpaque as uint);
-            f(self);
-            self.end_tag();
-        }
-    }
-
-    impl ::serialize::Encoder for Encoder {
-        fn emit_nil(&mut self) {}
-
-        fn emit_uint(&mut self, v: uint) {
-            self.wr_tagged_u64(EsUint as uint, v as u64);
-        }
-        fn emit_u64(&mut self, v: u64) {
-            self.wr_tagged_u64(EsU64 as uint, v);
-        }
-        fn emit_u32(&mut self, v: u32) {
-            self.wr_tagged_u32(EsU32 as uint, v);
-        }
-        fn emit_u16(&mut self, v: u16) {
-            self.wr_tagged_u16(EsU16 as uint, v);
-        }
-        fn emit_u8(&mut self, v: u8) {
-            self.wr_tagged_u8(EsU8 as uint, v);
-        }
-
-        fn emit_int(&mut self, v: int) {
-            self.wr_tagged_i64(EsInt as uint, v as i64);
-        }
-        fn emit_i64(&mut self, v: i64) {
-            self.wr_tagged_i64(EsI64 as uint, v);
-        }
-        fn emit_i32(&mut self, v: i32) {
-            self.wr_tagged_i32(EsI32 as uint, v);
-        }
-        fn emit_i16(&mut self, v: i16) {
-            self.wr_tagged_i16(EsI16 as uint, v);
-        }
-        fn emit_i8(&mut self, v: i8) {
-            self.wr_tagged_i8(EsI8 as uint, v);
-        }
-
-        fn emit_bool(&mut self, v: bool) {
-            self.wr_tagged_u8(EsBool as uint, v as u8)
-        }
-
-        // FIXME (#2742): implement these
-        fn emit_f64(&mut self, _v: f64) {
-            fail!("Unimplemented: serializing an f64");
-        }
-        fn emit_f32(&mut self, _v: f32) {
-            fail!("Unimplemented: serializing an f32");
-        }
-        fn emit_float(&mut self, _v: float) {
-            fail!("Unimplemented: serializing a float");
-        }
-
-        fn emit_char(&mut self, _v: char) {
-            fail!("Unimplemented: serializing a char");
-        }
-
-        fn emit_str(&mut self, v: &str) {
-            self.wr_tagged_str(EsStr as uint, v)
-        }
-
-        fn emit_enum(&mut self, name: &str, f: &fn(&mut Encoder)) {
-            self._emit_label(name);
-            self.start_tag(EsEnum as uint);
-            f(self);
-            self.end_tag();
-        }
-
-        fn emit_enum_variant(&mut self,
-                             _: &str,
-                             v_id: uint,
-                             _: uint,
-                             f: &fn(&mut Encoder)) {
-            self._emit_tagged_uint(EsEnumVid, v_id);
-            self.start_tag(EsEnumBody as uint);
-            f(self);
-            self.end_tag();
-        }
-
-        fn emit_enum_variant_arg(&mut self, _: uint, f: &fn(&mut Encoder)) {
-            f(self)
-        }
-
-        fn emit_enum_struct_variant(&mut self,
-                                    v_name: &str,
-                                    v_id: uint,
-                                    cnt: uint,
-                                    f: &fn(&mut Encoder)) {
-            self.emit_enum_variant(v_name, v_id, cnt, f)
-        }
-
-        fn emit_enum_struct_variant_field(&mut self,
-                                          _: &str,
-                                          idx: uint,
-                                          f: &fn(&mut Encoder)) {
-            self.emit_enum_variant_arg(idx, f)
-        }
-
-        fn emit_struct(&mut self, _: &str, _len: uint, f: &fn(&mut Encoder)) {
-            f(self)
-        }
-
-        fn emit_struct_field(&mut self,
-                             name: &str,
-                             _: uint,
-                             f: &fn(&mut Encoder)) {
-            self._emit_label(name);
-            f(self)
-        }
-
-        fn emit_tuple(&mut self, len: uint, f: &fn(&mut Encoder)) {
-            self.emit_seq(len, f)
-        }
-        fn emit_tuple_arg(&mut self, idx: uint, f: &fn(&mut Encoder)) {
-            self.emit_seq_elt(idx, f)
-        }
-
-        fn emit_tuple_struct(&mut self,
-                             _: &str,
-                             len: uint,
-                             f: &fn(&mut Encoder)) {
-            self.emit_seq(len, f)
-        }
-        fn emit_tuple_struct_arg(&mut self, idx: uint, f: &fn(&mut Encoder)) {
-            self.emit_seq_elt(idx, f)
-        }
-
-        fn emit_option(&mut self, f: &fn(&mut Encoder)) {
-            self.emit_enum("Option", f);
-        }
-        fn emit_option_none(&mut self) {
-            self.emit_enum_variant("None", 0, 0, |_| ())
-        }
-        fn emit_option_some(&mut self, f: &fn(&mut Encoder)) {
-            self.emit_enum_variant("Some", 1, 1, f)
-        }
-
-        fn emit_seq(&mut self, len: uint, f: &fn(&mut Encoder)) {
-            self.start_tag(EsVec as uint);
-            self._emit_tagged_uint(EsVecLen, len);
-            f(self);
-            self.end_tag();
-        }
-
-        fn emit_seq_elt(&mut self, _idx: uint, f: &fn(&mut Encoder)) {
-            self.start_tag(EsVecElt as uint);
-            f(self);
-            self.end_tag();
-        }
-
-        fn emit_map(&mut self, _len: uint, _f: &fn(&mut Encoder)) {
-            fail!("emit_map is unimplemented");
-        }
-
-        fn emit_map_elt_key(&mut self, _idx: uint, _f: &fn(&mut Encoder)) {
-            fail!("emit_map_elt_key is unimplemented");
-        }
-
-        fn emit_map_elt_val(&mut self, _idx: uint, _f: &fn(&mut Encoder)) {
-            fail!("emit_map_elt_val is unimplemented");
-        }
-    }
-}
-
-// ___________________________________________________________________________
-// Testing
-
-#[cfg(test)]
-mod tests {
-    use ebml::reader;
-    use ebml::writer;
-    use serialize::Encodable;
-    use serialize;
-
-    use core::io;
-    use core::option::{None, Option, Some};
-
-    #[test]
-    fn test_option_int() {
-        fn test_v(v: Option<int>) {
-            debug!("v == %?", v);
-            let bytes = do io::with_bytes_writer |wr| {
-                let mut ebml_w = writer::Encoder(wr);
-                v.encode(&mut ebml_w)
-            };
-            let ebml_doc = reader::Doc(@bytes);
-            let mut deser = reader::Decoder(ebml_doc);
-            let v1 = serialize::Decodable::decode(&mut deser);
-            debug!("v1 == %?", v1);
-            assert_eq!(v, v1);
-        }
-
-        test_v(Some(22));
-        test_v(None);
-        test_v(Some(3));
-    }
-}
diff --git a/src/libstd/either.rs b/src/libstd/either.rs
new file mode 100644
index 00000000000..f89bb3b2f90
--- /dev/null
+++ b/src/libstd/either.rs
@@ -0,0 +1,256 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! A type that represents one of two alternatives
+
+use container::Container;
+use cmp::Eq;
+use kinds::Copy;
+use old_iter::BaseIter;
+use result::Result;
+use result;
+use vec;
+use vec::OwnedVector;
+
+/// The either type
+#[deriving(Clone, Eq)]
+pub enum Either<T, U> {
+    Left(T),
+    Right(U)
+}
+
+/// Applies a function based on the given either value
+///
+/// If `value` is left(T) then `f_left` is applied to its contents, if
+/// `value` is right(U) then `f_right` is applied to its contents, and the
+/// result is returned.
+#[inline(always)]
+pub fn either<T, U, V>(f_left: &fn(&T) -> V,
+                       f_right: &fn(&U) -> V, value: &Either<T, U>) -> V {
+    match *value {
+        Left(ref l) => f_left(l),
+        Right(ref r) => f_right(r)
+    }
+}
+
+/// Extracts from a vector of either all the left values
+pub fn lefts<T:Copy,U>(eithers: &[Either<T, U>]) -> ~[T] {
+    do vec::build_sized(eithers.len()) |push| {
+        for eithers.each |elt| {
+            match *elt {
+                Left(ref l) => { push(*l); }
+                _ => { /* fallthrough */ }
+            }
+        }
+    }
+}
+
+/// Extracts from a vector of either all the right values
+pub fn rights<T, U: Copy>(eithers: &[Either<T, U>]) -> ~[U] {
+    do vec::build_sized(eithers.len()) |push| {
+        for eithers.each |elt| {
+            match *elt {
+                Right(ref r) => { push(*r); }
+                _ => { /* fallthrough */ }
+            }
+        }
+    }
+}
+
+/// Extracts from a vector of either all the left values and right values
+///
+/// Returns a structure containing a vector of left values and a vector of
+/// right values.
+pub fn partition<T, U>(eithers: ~[Either<T, U>]) -> (~[T], ~[U]) {
+    let mut lefts: ~[T] = ~[];
+    let mut rights: ~[U] = ~[];
+    do vec::consume(eithers) |_i, elt| {
+        match elt {
+            Left(l) => lefts.push(l),
+            Right(r) => rights.push(r)
+        }
+    }
+    return (lefts, rights);
+}
+
+/// Flips between left and right of a given either
+#[inline(always)]
+pub fn flip<T, U>(eith: Either<T, U>) -> Either<U, T> {
+    match eith {
+        Right(r) => Left(r),
+        Left(l) => Right(l)
+    }
+}
+
+/// Converts either::t to a result::t
+///
+/// Converts an `either` type to a `result` type, making the "right" choice
+/// an ok result, and the "left" choice a fail
+#[inline(always)]
+pub fn to_result<T, U>(eith: Either<T, U>) -> Result<U, T> {
+    match eith {
+        Right(r) => result::Ok(r),
+        Left(l) => result::Err(l)
+    }
+}
+
+/// Checks whether the given value is a left
+#[inline(always)]
+pub fn is_left<T, U>(eith: &Either<T, U>) -> bool {
+    match *eith {
+        Left(_) => true,
+        _ => false
+    }
+}
+
+/// Checks whether the given value is a right
+#[inline(always)]
+pub fn is_right<T, U>(eith: &Either<T, U>) -> bool {
+    match *eith {
+        Right(_) => true,
+        _ => false
+    }
+}
+
+/// Retrieves the value in the left branch. Fails if the either is Right.
+#[inline(always)]
+pub fn unwrap_left<T,U>(eith: Either<T,U>) -> T {
+    match eith {
+        Left(x) => x,
+        Right(_) => fail!("either::unwrap_left Right")
+    }
+}
+
+/// Retrieves the value in the right branch. Fails if the either is Left.
+#[inline(always)]
+pub fn unwrap_right<T,U>(eith: Either<T,U>) -> U {
+    match eith {
+        Right(x) => x,
+        Left(_) => fail!("either::unwrap_right Left")
+    }
+}
+
+pub impl<T, U> Either<T, U> {
+    #[inline(always)]
+    fn either<V>(&self, f_left: &fn(&T) -> V, f_right: &fn(&U) -> V) -> V {
+        either(f_left, f_right, self)
+    }
+
+    #[inline(always)]
+    fn flip(self) -> Either<U, T> { flip(self) }
+
+    #[inline(always)]
+    fn to_result(self) -> Result<U, T> { to_result(self) }
+
+    #[inline(always)]
+    fn is_left(&self) -> bool { is_left(self) }
+
+    #[inline(always)]
+    fn is_right(&self) -> bool { is_right(self) }
+
+    #[inline(always)]
+    fn unwrap_left(self) -> T { unwrap_left(self) }
+
+    #[inline(always)]
+    fn unwrap_right(self) -> U { unwrap_right(self) }
+}
+
+#[test]
+fn test_either_left() {
+    let val = Left(10);
+    fn f_left(x: &int) -> bool { *x == 10 }
+    fn f_right(_x: &uint) -> bool { false }
+    assert!((either(f_left, f_right, &val)));
+}
+
+#[test]
+fn test_either_right() {
+    let val = Right(10u);
+    fn f_left(_x: &int) -> bool { false }
+    fn f_right(x: &uint) -> bool { *x == 10u }
+    assert!((either(f_left, f_right, &val)));
+}
+
+#[test]
+fn test_lefts() {
+    let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
+    let result = lefts(input);
+    assert_eq!(result, ~[10, 12, 14]);
+}
+
+#[test]
+fn test_lefts_none() {
+    let input: ~[Either<int, int>] = ~[Right(10), Right(10)];
+    let result = lefts(input);
+    assert_eq!(result.len(), 0u);
+}
+
+#[test]
+fn test_lefts_empty() {
+    let input: ~[Either<int, int>] = ~[];
+    let result = lefts(input);
+    assert_eq!(result.len(), 0u);
+}
+
+#[test]
+fn test_rights() {
+    let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
+    let result = rights(input);
+    assert_eq!(result, ~[11, 13]);
+}
+
+#[test]
+fn test_rights_none() {
+    let input: ~[Either<int, int>] = ~[Left(10), Left(10)];
+    let result = rights(input);
+    assert_eq!(result.len(), 0u);
+}
+
+#[test]
+fn test_rights_empty() {
+    let input: ~[Either<int, int>] = ~[];
+    let result = rights(input);
+    assert_eq!(result.len(), 0u);
+}
+
+#[test]
+fn test_partition() {
+    let input = ~[Left(10), Right(11), Left(12), Right(13), Left(14)];
+    let (lefts, rights) = partition(input);
+    assert_eq!(lefts[0], 10);
+    assert_eq!(lefts[1], 12);
+    assert_eq!(lefts[2], 14);
+    assert_eq!(rights[0], 11);
+    assert_eq!(rights[1], 13);
+}
+
+#[test]
+fn test_partition_no_lefts() {
+    let input: ~[Either<int, int>] = ~[Right(10), Right(11)];
+    let (lefts, rights) = partition(input);
+    assert_eq!(lefts.len(), 0u);
+    assert_eq!(rights.len(), 2u);
+}
+
+#[test]
+fn test_partition_no_rights() {
+    let input: ~[Either<int, int>] = ~[Left(10), Left(11)];
+    let (lefts, rights) = partition(input);
+    assert_eq!(lefts.len(), 2u);
+    assert_eq!(rights.len(), 0u);
+}
+
+#[test]
+fn test_partition_empty() {
+    let input: ~[Either<int, int>] = ~[];
+    let (lefts, rights) = partition(input);
+    assert_eq!(lefts.len(), 0u);
+    assert_eq!(rights.len(), 0u);
+}
diff --git a/src/libstd/fileinput.rs b/src/libstd/fileinput.rs
deleted file mode 100644
index d9a932fbe7c..00000000000
--- a/src/libstd/fileinput.rs
+++ /dev/null
@@ -1,604 +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.
-
-/*!
-A library for iterating through the lines in a series of
-files. Very similar to [the Python module of the same
-name](http://docs.python.org/3.3/library/fileinput.html).
-
-It allows the programmer to automatically take filenames from the
-command line arguments (via `input` and `input_state`), as well as
-specify them as a vector directly (`input_vec` and
-`input_vec_state`). The files are opened as necessary, so any files
-that can't be opened only cause an error when reached in the
-iteration.
-
-On the command line, `stdin` is represented by a filename of `-` (a
-single hyphen) and in the functions that take a vector directly
-(e.g. `input_vec`) it is represented by `None`. Note `stdin` is *not*
-reset once it has been finished, so attempting to iterate on `[None,
-None]` will only take input once unless `io::stdin().seek(0, SeekSet)`
-is called between.
-
-The `pathify` function handles converting a list of file paths as
-strings to the appropriate format, including the (optional) conversion
-of `"-"` to `stdin`.
-
-# Basic
-
-In many cases, one can use the `input_*` functions without having
-to handle any `FileInput` structs. E.g. a simple `cat` program
-
-    for input |line| {
-        io::println(line)
-    }
-
-or a program that numbers lines after concatenating two files
-
-    for input_vec_state(pathify([~"a.txt", ~"b.txt"])) |line, state| {
-        io::println(fmt!("%u: %s", state.line_num,
-                                   line));
-    }
-
-The two `input_vec*` functions take a vec of file names (where empty
-means read from `stdin`), the other two functions use the command line
-arguments.
-
-# Advanced
-
-For more complicated uses (e.g. if one needs to pause iteration and
-resume it later), a `FileInput` instance can be constructed via the
-`from_vec`, `from_vec_raw` and `from_args` functions.
-
-Once created, the `each_line` (from the `core::io::ReaderUtil` trait)
-and `each_line_state` methods allow one to iterate on the lines; the
-latter provides more information about the position within the
-iteration to the caller.
-
-It is possible (and safe) to skip lines and files using the
-`read_line` and `next_file` methods. Also, `FileInput` implements
-`core::io::Reader`, and the state will be updated correctly while
-using any of those methods.
-
-E.g. the following program reads until an empty line, pauses for user
-input, skips the current file and then numbers the remaining lines
-(where the numbers are from the start of each file, rather than the
-total line count).
-
-    let in = FileInput::from_vec(pathify([~"a.txt", ~"b.txt", ~"c.txt"],
-                                             true));
-
-    for in.each_line |line| {
-        if line.is_empty() {
-            break
-        }
-        io::println(line);
-    }
-
-    io::println("Continue?");
-
-    if io::stdin().read_line() == ~"yes" {
-        in.next_file(); // skip!
-
-        for in.each_line_state |line, state| {
-           io::println(fmt!("%u: %s", state.line_num_file,
-                                      line))
-        }
-    }
-*/
-
-use core::io::ReaderUtil;
-
-/**
-A summary of the internal state of a `FileInput` object. `line_num`
-and `line_num_file` represent the number of lines read in total and in
-the current file respectively. `current_path` is `None` if the current
-file is `stdin`.
-*/
-pub struct FileInputState {
-    current_path: Option<Path>,
-    line_num: uint,
-    line_num_file: uint
-}
-
-impl FileInputState {
-    fn is_stdin(&self) -> bool {
-        self.current_path.is_none()
-    }
-
-    fn is_first_line(&self) -> bool {
-        self.line_num_file == 1
-    }
-}
-
-struct FileInput_ {
-    /**
-    `Some(path)` is the file represented by `path`, `None` is
-    `stdin`. Consumed as the files are read.
-    */
-    priv files: ~[Option<Path>],
-    /**
-    The current file: `Some(r)` for an open file, `None` before
-    starting and after reading everything.
-    */
-    priv current_reader: Option<@io::Reader>,
-    priv state: FileInputState,
-
-    /**
-    Used to keep track of whether we need to insert the newline at the
-    end of a file that is missing it, which is needed to separate the
-    last and first lines.
-    */
-    priv previous_was_newline: bool
-}
-
-// XXX: remove this when Reader has &mut self. Should be removable via
-// "self.fi." -> "self." and renaming FileInput_. Documentation above
-// will likely have to be updated to use `let mut in = ...`.
-pub struct FileInput  {
-    priv fi: @mut FileInput_
-}
-
-impl FileInput {
-    /**
-    Create a `FileInput` object from a vec of files. An empty
-    vec means lines are read from `stdin` (use `from_vec_raw` to stop
-    this behaviour). Any occurence of `None` represents `stdin`.
-    */
-    pub fn from_vec(files: ~[Option<Path>]) -> FileInput {
-        FileInput::from_vec_raw(
-            if files.is_empty() {
-                ~[None]
-            } else {
-                files
-            })
-    }
-
-    /**
-    Identical to `from_vec`, but an empty `files` vec stays
-    empty. (`None` is `stdin`.)
-    */
-    pub fn from_vec_raw(files: ~[Option<Path>])
-                                         -> FileInput {
-        FileInput{
-            fi: @mut FileInput_ {
-                files: files,
-                current_reader: None,
-                state: FileInputState {
-                    current_path: None,
-                    line_num: 0,
-                    line_num_file: 0
-                },
-                // there was no previous unended line
-                previous_was_newline: true
-            }
-        }
-    }
-
-    /**
-    Create a `FileInput` object from the command line
-    arguments. `"-"` represents `stdin`.
-    */
-    pub fn from_args() -> FileInput {
-        let args = os::args(),
-            pathed = pathify(args.tail(), true);
-        FileInput::from_vec(pathed)
-    }
-
-    priv fn current_file_eof(&self) -> bool {
-        match self.fi.current_reader {
-            None => false,
-            Some(r) => r.eof()
-        }
-    }
-
-    /**
-    Skip to the next file in the queue. Can `fail` when opening
-    a file.
-
-    Returns `false` if there is no more files, and `true` when it
-    successfully opens the next file.
-    */
-
-    pub fn next_file(&self) -> bool {
-        // No more files
-
-        if self.fi.files.is_empty() {
-            self.fi.current_reader = None;
-            return false;
-        }
-
-        let path_option = self.fi.files.shift(),
-            file = match path_option {
-                None => io::stdin(),
-                Some(ref path) => io::file_reader(path).get()
-            };
-
-        self.fi.current_reader = Some(file);
-        self.fi.state.current_path = path_option;
-        self.fi.state.line_num_file = 0;
-        true
-    }
-
-    /**
-    Attempt to open the next file if there is none currently open,
-    or if the current one is EOF'd.
-
-    Returns `true` if it had to move to the next file and did
-    so successfully.
-    */
-    priv fn next_file_if_eof(&self) -> bool {
-        match self.fi.current_reader {
-            None => self.next_file(),
-            Some(r) => {
-                if r.eof() {
-                    self.next_file()
-                } else {
-                    false
-                }
-            }
-        }
-    }
-
-    /**
-    Apply `f` to each line successively, along with some state
-    (line numbers and file names, see documentation for
-    `FileInputState`). Otherwise identical to `lines_each`.
-    */
-    pub fn each_line_state(&self,
-                            f: &fn(&str, FileInputState) -> bool) -> bool {
-         self.each_line(|line| f(line, copy self.fi.state))
-    }
-
-
-    /**
-    Retrieve the current `FileInputState` information.
-    */
-    pub fn state(&self) -> FileInputState {
-        copy self.fi.state
-    }
-}
-
-impl io::Reader for FileInput {
-    fn read_byte(&self) -> int {
-        loop {
-            let stepped = self.next_file_if_eof();
-
-            // if we moved to the next file, and the previous
-            // character wasn't \n, then there is an unfinished line
-            // from the previous file. This library models
-            // line-by-line processing and the trailing line of the
-            // previous file and the leading of the current file
-            // should be considered different, so we need to insert a
-            // fake line separator
-            if stepped && !self.fi.previous_was_newline {
-                self.fi.state.line_num += 1;
-                self.fi.state.line_num_file += 1;
-                self.fi.previous_was_newline = true;
-                return '\n' as int;
-            }
-
-            match self.fi.current_reader {
-                None => return -1,
-                Some(r) => {
-                    let b = r.read_byte();
-
-                    if b < 0 {
-                        loop;
-                    }
-
-                    if b == '\n' as int {
-                        self.fi.state.line_num += 1;
-                        self.fi.state.line_num_file += 1;
-                        self.fi.previous_was_newline = true;
-                    } else {
-                        self.fi.previous_was_newline = false;
-                    }
-
-                    return b;
-                }
-            }
-        }
-    }
-    fn read(&self, buf: &mut [u8], len: uint) -> uint {
-        let mut count = 0;
-        while count < len {
-            let b = self.read_byte();
-            if b < 0 { break }
-
-            buf[count] = b as u8;
-            count += 1;
-        }
-
-        count
-    }
-    fn eof(&self) -> bool {
-        // we've run out of files, and current_reader is either None or eof.
-
-        self.fi.files.is_empty() &&
-            match self.fi.current_reader { None => true, Some(r) => r.eof() }
-
-    }
-    fn seek(&self, offset: int, whence: io::SeekStyle) {
-        match self.fi.current_reader {
-            None => {},
-            Some(r) => r.seek(offset, whence)
-        }
-    }
-    fn tell(&self) -> uint {
-        match self.fi.current_reader {
-            None => 0,
-            Some(r) => r.tell()
-        }
-    }
-}
-
-/**
-Convert a list of strings to an appropriate form for a `FileInput`
-instance. `stdin_hyphen` controls whether `-` represents `stdin` or
-a literal `-`.
-*/
-// XXX: stupid, unclear name
-pub fn pathify(vec: &[~str], stdin_hyphen : bool) -> ~[Option<Path>] {
-    vec::map(vec, |&str : & ~str| {
-        if stdin_hyphen && str == ~"-" {
-            None
-        } else {
-            Some(Path(str))
-        }
-    })
-}
-
-/**
-Iterate directly over the command line arguments (no arguments implies
-reading from `stdin`).
-
-Fails when attempting to read from a file that can't be opened.
-*/
-pub fn input(f: &fn(&str) -> bool) -> bool {
-    let i = FileInput::from_args();
-    i.each_line(f)
-}
-
-/**
-Iterate directly over the command line arguments (no arguments
-implies reading from `stdin`) with the current state of the iteration
-provided at each call.
-
-Fails when attempting to read from a file that can't be opened.
-*/
-pub fn input_state(f: &fn(&str, FileInputState) -> bool) -> bool {
-    let i = FileInput::from_args();
-    i.each_line_state(f)
-}
-
-/**
-Iterate over a vector of files (an empty vector implies just `stdin`).
-
-Fails when attempting to read from a file that can't be opened.
-*/
-pub fn input_vec(files: ~[Option<Path>], f: &fn(&str) -> bool) -> bool {
-    let i = FileInput::from_vec(files);
-    i.each_line(f)
-}
-
-/**
-Iterate over a vector of files (an empty vector implies just `stdin`)
-with the current state of the iteration provided at each call.
-
-Fails when attempting to read from a file that can't be opened.
-*/
-pub fn input_vec_state(files: ~[Option<Path>],
-                       f: &fn(&str, FileInputState) -> bool) -> bool {
-    let i = FileInput::from_vec(files);
-    i.each_line_state(f)
-}
-
-#[cfg(test)]
-mod test {
-    use core::io::WriterUtil;
-    use super::{FileInput, pathify, input_vec, input_vec_state};
-
-    fn make_file(path : &Path, contents: &[~str]) {
-        let file = io::file_writer(path, [io::Create, io::Truncate]).get();
-
-        for contents.each |&str| {
-            file.write_str(str);
-            file.write_char('\n');
-        }
-    }
-
-    #[test]
-    fn test_pathify() {
-        let strs = [~"some/path",
-                    ~"some/other/path"],
-            paths = ~[Some(Path("some/path")),
-                      Some(Path("some/other/path"))];
-
-        assert_eq!(pathify(strs, true), copy paths);
-        assert_eq!(pathify(strs, false), paths);
-
-        assert_eq!(pathify([~"-"], true), ~[None]);
-        assert_eq!(pathify([~"-"], false), ~[Some(Path("-"))]);
-    }
-
-    #[test]
-    fn test_fileinput_read_byte() {
-        let filenames = pathify(vec::from_fn(
-            3,
-            |i| fmt!("tmp/lib-fileinput-test-fileinput-read-byte-%u.tmp", i)), true);
-
-        // 3 files containing 0\n, 1\n, and 2\n respectively
-        for filenames.eachi |i, &filename| {
-            make_file(filename.get_ref(), ~[fmt!("%u", i)]);
-        }
-
-        let fi = FileInput::from_vec(copy filenames);
-
-        for "012".each_chari |line, c| {
-            assert_eq!(fi.read_byte(), c as int);
-            assert_eq!(fi.state().line_num, line);
-            assert_eq!(fi.state().line_num_file, 0);
-            assert_eq!(fi.read_byte(), '\n' as int);
-            assert_eq!(fi.state().line_num, line + 1);
-            assert_eq!(fi.state().line_num_file, 1);
-
-            assert_eq!(copy fi.state().current_path, copy filenames[line]);
-        }
-
-        assert_eq!(fi.read_byte(), -1);
-        assert!(fi.eof());
-        assert_eq!(fi.state().line_num, 3)
-
-    }
-
-    #[test]
-    fn test_fileinput_read() {
-        let filenames = pathify(vec::from_fn(
-            3,
-            |i| fmt!("tmp/lib-fileinput-test-fileinput-read-%u.tmp", i)), true);
-
-        // 3 files containing 1\n, 2\n, and 3\n respectively
-        for filenames.eachi |i, &filename| {
-            make_file(filename.get_ref(), ~[fmt!("%u", i)]);
-        }
-
-        let fi = FileInput::from_vec(filenames);
-        let mut buf : ~[u8] = vec::from_elem(6, 0u8);
-        let count = fi.read(buf, 10);
-        assert_eq!(count, 6);
-        assert_eq!(buf, "0\n1\n2\n".to_bytes());
-        assert!(fi.eof())
-        assert_eq!(fi.state().line_num, 3);
-    }
-
-    #[test]
-    fn test_input_vec() {
-        let mut all_lines = ~[];
-        let filenames = pathify(vec::from_fn(
-            3,
-            |i| fmt!("tmp/lib-fileinput-test-input-vec-%u.tmp", i)), true);
-
-        for filenames.eachi |i, &filename| {
-            let contents =
-                vec::from_fn(3, |j| fmt!("%u %u", i, j));
-            make_file(filename.get_ref(), contents);
-            all_lines.push_all(contents);
-        }
-
-        let mut read_lines = ~[];
-        for input_vec(filenames) |line| {
-            read_lines.push(line.to_owned());
-        }
-        assert_eq!(read_lines, all_lines);
-    }
-
-    #[test]
-    fn test_input_vec_state() {
-        let filenames = pathify(vec::from_fn(
-            3,
-            |i| fmt!("tmp/lib-fileinput-test-input-vec-state-%u.tmp", i)),true);
-
-        for filenames.eachi |i, &filename| {
-            let contents =
-                vec::from_fn(3, |j| fmt!("%u %u", i, j + 1));
-            make_file(filename.get_ref(), contents);
-        }
-
-        for input_vec_state(filenames) |line, state| {
-            let nums = do vec::build |p| {
-                for str::each_split_char(line, ' ') |s| { p(s.to_owned()); }
-            };
-            let file_num = uint::from_str(nums[0]).get();
-            let line_num = uint::from_str(nums[1]).get();
-            assert_eq!(line_num, state.line_num_file);
-            assert_eq!(file_num * 3 + line_num, state.line_num);
-        }
-    }
-
-    #[test]
-    fn test_empty_files() {
-        let filenames = pathify(vec::from_fn(
-            3,
-            |i| fmt!("tmp/lib-fileinput-test-empty-files-%u.tmp", i)),true);
-
-        make_file(filenames[0].get_ref(), ~[~"1", ~"2"]);
-        make_file(filenames[1].get_ref(), ~[]);
-        make_file(filenames[2].get_ref(), ~[~"3", ~"4"]);
-
-        let mut count = 0;
-        for input_vec_state(copy filenames) |line, state| {
-            let expected_path = match line {
-                "1" | "2" => copy filenames[0],
-                "3" | "4" => copy filenames[2],
-                _ => fail!("unexpected line")
-            };
-            assert_eq!(copy state.current_path, expected_path);
-            count += 1;
-        }
-        assert_eq!(count, 4);
-    }
-
-    #[test]
-    fn test_no_trailing_newline() {
-        let f1 = Some(Path("tmp/lib-fileinput-test-no-trailing-newline-1.tmp")),
-            f2 = Some(Path("tmp/lib-fileinput-test-no-trailing-newline-2.tmp"));
-
-        let wr = io::file_writer(f1.get_ref(), [io::Create, io::Truncate]).get();
-        wr.write_str("1\n2");
-        let wr = io::file_writer(f2.get_ref(), [io::Create, io::Truncate]).get();
-        wr.write_str("3\n4");
-
-        let mut lines = ~[];
-        for input_vec(~[f1, f2]) |line| {
-            lines.push(line.to_owned());
-        }
-        assert_eq!(lines, ~[~"1", ~"2", ~"3", ~"4"]);
-    }
-
-
-    #[test]
-    fn test_next_file() {
-        let filenames = pathify(vec::from_fn(
-            3,
-            |i| fmt!("tmp/lib-fileinput-test-next-file-%u.tmp", i)),true);
-
-        for filenames.eachi |i, &filename| {
-            let contents =
-                vec::from_fn(3, |j| fmt!("%u %u", i, j + 1));
-            make_file(&filename.get(), contents);
-        }
-
-        let mut in = FileInput::from_vec(filenames);
-
-        // read once from 0
-        assert_eq!(in.read_line(), ~"0 1");
-        in.next_file(); // skip the rest of 1
-
-        // read all lines from 1 (but don't read any from 2),
-        for uint::range(1, 4) |i| {
-            assert_eq!(in.read_line(), fmt!("1 %u", i));
-        }
-        // 1 is finished, but 2 hasn't been started yet, so this will
-        // just "skip" to the beginning of 2 (Python's fileinput does
-        // the same)
-        in.next_file();
-
-        assert_eq!(in.read_line(), ~"2 1");
-    }
-
-    #[test]
-    #[should_fail]
-    fn test_input_vec_missing_file() {
-        for input_vec(pathify([~"this/file/doesnt/exist"], true)) |line| {
-            io::println(line);
-        }
-    }
-}
diff --git a/src/libstd/flate.rs b/src/libstd/flate.rs
deleted file mode 100644
index b0d219bc945..00000000000
--- a/src/libstd/flate.rs
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
-
-Simple compression
-
-*/
-
-use libc;
-use core::libc::{c_void, size_t, c_int};
-use vec;
-
-#[cfg(test)] use core::rand;
-#[cfg(test)] use core::rand::RngUtil;
-
-pub mod rustrt {
-    use core::libc::{c_int, c_void, size_t};
-
-    #[link_name = "rustrt"]
-    pub extern {
-        unsafe fn tdefl_compress_mem_to_heap(psrc_buf: *const c_void,
-                                             src_buf_len: size_t,
-                                             pout_len: *mut size_t,
-                                             flags: c_int)
-                                          -> *c_void;
-
-        unsafe fn tinfl_decompress_mem_to_heap(psrc_buf: *const c_void,
-                                               src_buf_len: size_t,
-                                               pout_len: *mut size_t,
-                                               flags: c_int)
-                                            -> *c_void;
-    }
-}
-
-static lz_none : c_int = 0x0;   // Huffman-coding only.
-static lz_fast : c_int = 0x1;   // LZ with only one probe
-static lz_norm : c_int = 0x80;  // LZ with 128 probes, "normal"
-static lz_best : c_int = 0xfff; // LZ with 4095 probes, "best"
-
-pub fn deflate_bytes(bytes: &const [u8]) -> ~[u8] {
-    do vec::as_const_buf(bytes) |b, len| {
-        unsafe {
-            let mut outsz : size_t = 0;
-            let res =
-                rustrt::tdefl_compress_mem_to_heap(b as *c_void,
-                                                   len as size_t,
-                                                   &mut outsz,
-                                                   lz_norm);
-            assert!(res as int != 0);
-            let out = vec::raw::from_buf_raw(res as *u8,
-                                             outsz as uint);
-            libc::free(res);
-            out
-        }
-    }
-}
-
-pub fn inflate_bytes(bytes: &const [u8]) -> ~[u8] {
-    do vec::as_const_buf(bytes) |b, len| {
-        unsafe {
-            let mut outsz : size_t = 0;
-            let res =
-                rustrt::tinfl_decompress_mem_to_heap(b as *c_void,
-                                                     len as size_t,
-                                                     &mut outsz,
-                                                     0);
-            assert!(res as int != 0);
-            let out = vec::raw::from_buf_raw(res as *u8,
-                                            outsz as uint);
-            libc::free(res);
-            out
-        }
-    }
-}
-
-#[test]
-#[allow(non_implicitly_copyable_typarams)]
-fn test_flate_round_trip() {
-    let mut r = rand::rng();
-    let mut words = ~[];
-    for 20.times {
-        let range = r.gen_uint_range(1, 10);
-        words.push(r.gen_bytes(range));
-    }
-    for 20.times {
-        let mut in = ~[];
-        for 2000.times {
-            in.push_all(r.choose(words));
-        }
-        debug!("de/inflate of %u bytes of random word-sequences",
-               in.len());
-        let cmp = deflate_bytes(in);
-        let out = inflate_bytes(cmp);
-        debug!("%u bytes deflated to %u (%.1f%% size)",
-               in.len(), cmp.len(),
-               100.0 * ((cmp.len() as float) / (in.len() as float)));
-        assert_eq!(in, out);
-    }
-}
diff --git a/src/libstd/flatpipes.rs b/src/libstd/flatpipes.rs
deleted file mode 100644
index a634f88dcf5..00000000000
--- a/src/libstd/flatpipes.rs
+++ /dev/null
@@ -1,962 +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.
-
-/*!
-
-Generic communication channels for things that can be represented as,
-or transformed to and from, byte vectors.
-
-The `FlatPort` and `FlatChan` types implement the generic channel and
-port interface for arbitrary types and transport strategies. It can
-particularly be used to send and receive serializable types over I/O
-streams.
-
-`FlatPort` and `FlatChan` implement the same comm traits as pipe-based
-ports and channels.
-
-# Example
-
-This example sends boxed integers across tasks using serialization.
-
-~~~
-let (port, chan) = serial::pipe_stream();
-
-do task::spawn || {
-    for int::range(0, 10) |i| {
-        chan.send(@i)
-    }
-}
-
-for int::range(0, 10) |i| {
-    assert @i == port.recv()
-}
-~~~
-
-# Safety Note
-
-Flat pipes created from `io::Reader`s and `io::Writer`s share the same
-blocking properties as the underlying stream. Since some implementations
-block the scheduler thread, so will their pipes.
-
-*/
-
-// The basic send/recv interface FlatChan and PortChan will implement
-use core::io;
-use core::comm::GenericChan;
-use core::comm::GenericPort;
-use core::sys::size_of;
-use core::vec;
-
-/**
-A FlatPort, consisting of a `BytePort` that receives byte vectors,
-and an `Unflattener` that converts the bytes to a value.
-
-Create using the constructors in the `serial` and `pod` modules.
-*/
-pub struct FlatPort<T, U, P> {
-    unflattener: U,
-    byte_port: P
-}
-
-/**
-A FlatChan, consisting of a `Flattener` that converts values to
-byte vectors, and a `ByteChan` that transmits the bytes.
-
-Create using the constructors in the `serial` and `pod` modules.
-*/
-pub struct FlatChan<T, F, C> {
-    flattener: F,
-    byte_chan: C
-}
-
-/**
-Constructors for flat pipes that using serialization-based flattening.
-*/
-pub mod serial {
-    pub use DefaultEncoder = ebml::writer::Encoder;
-    pub use DefaultDecoder = ebml::reader::Decoder;
-
-    use serialize::{Decodable, Encodable};
-    use flatpipes::flatteners::{DeserializingUnflattener,
-                                SerializingFlattener};
-    use flatpipes::flatteners::{deserialize_buffer, serialize_value};
-    use flatpipes::bytepipes::{ReaderBytePort, WriterByteChan};
-    use flatpipes::bytepipes::{PipeBytePort, PipeByteChan};
-    use flatpipes::{FlatPort, FlatChan};
-
-    use core::io::{Reader, Writer};
-    use core::comm::{Port, Chan};
-    use core::comm;
-
-    pub type ReaderPort<T, R> = FlatPort<
-        T, DeserializingUnflattener<DefaultDecoder, T>,
-        ReaderBytePort<R>>;
-    pub type WriterChan<T, W> = FlatChan<
-        T, SerializingFlattener<DefaultEncoder, T>, WriterByteChan<W>>;
-    pub type PipePort<T> = FlatPort<
-        T, DeserializingUnflattener<DefaultDecoder, T>, PipeBytePort>;
-    pub type PipeChan<T> = FlatChan<
-        T, SerializingFlattener<DefaultEncoder, T>, PipeByteChan>;
-
-    /// Create a `FlatPort` from a `Reader`
-    pub fn reader_port<T: Decodable<DefaultDecoder>,
-                       R: Reader>(reader: R) -> ReaderPort<T, R> {
-        let unflat: DeserializingUnflattener<DefaultDecoder, T> =
-            DeserializingUnflattener::new(
-                deserialize_buffer::<DefaultDecoder, T>);
-        let byte_port = ReaderBytePort::new(reader);
-        FlatPort::new(unflat, byte_port)
-    }
-
-    /// Create a `FlatChan` from a `Writer`
-    pub fn writer_chan<T: Encodable<DefaultEncoder>,
-                       W: Writer>(writer: W) -> WriterChan<T, W> {
-        let flat: SerializingFlattener<DefaultEncoder, T> =
-            SerializingFlattener::new(
-                serialize_value::<DefaultEncoder, T>);
-        let byte_chan = WriterByteChan::new(writer);
-        FlatChan::new(flat, byte_chan)
-    }
-
-    /// Create a `FlatPort` from a `Port<~[u8]>`
-    pub fn pipe_port<T:Decodable<DefaultDecoder>>(
-        port: Port<~[u8]>
-    ) -> PipePort<T> {
-        let unflat: DeserializingUnflattener<DefaultDecoder, T> =
-            DeserializingUnflattener::new(
-                deserialize_buffer::<DefaultDecoder, T>);
-        let byte_port = PipeBytePort::new(port);
-        FlatPort::new(unflat, byte_port)
-    }
-
-    /// Create a `FlatChan` from a `Chan<~[u8]>`
-    pub fn pipe_chan<T:Encodable<DefaultEncoder>>(
-        chan: Chan<~[u8]>
-    ) -> PipeChan<T> {
-        let flat: SerializingFlattener<DefaultEncoder, T> =
-            SerializingFlattener::new(
-                serialize_value::<DefaultEncoder, T>);
-        let byte_chan = PipeByteChan::new(chan);
-        FlatChan::new(flat, byte_chan)
-    }
-
-    /// Create a pair of `FlatChan` and `FlatPort`, backed by pipes
-    pub fn pipe_stream<T: Encodable<DefaultEncoder> +
-                          Decodable<DefaultDecoder>>(
-                          ) -> (PipePort<T>, PipeChan<T>) {
-        let (port, chan) = comm::stream();
-        return (pipe_port(port), pipe_chan(chan));
-    }
-}
-
-// FIXME #4074 this doesn't correctly enforce POD bounds
-/**
-Constructors for flat pipes that send POD types using memcpy.
-
-# Safety Note
-
-This module is currently unsafe because it uses `Copy Owned` as a type
-parameter bounds meaning POD (plain old data), but `Copy Owned` and
-POD are not equivelant.
-
-*/
-pub mod pod {
-    use flatpipes::flatteners::{PodUnflattener, PodFlattener};
-    use flatpipes::bytepipes::{ReaderBytePort, WriterByteChan};
-    use flatpipes::bytepipes::{PipeBytePort, PipeByteChan};
-    use flatpipes::{FlatPort, FlatChan};
-
-    use core::io::{Reader, Writer};
-    use core::comm::{Port, Chan};
-    use core::comm;
-
-    pub type ReaderPort<T, R> =
-        FlatPort<T, PodUnflattener<T>, ReaderBytePort<R>>;
-    pub type WriterChan<T, W> =
-        FlatChan<T, PodFlattener<T>, WriterByteChan<W>>;
-    pub type PipePort<T> = FlatPort<T, PodUnflattener<T>, PipeBytePort>;
-    pub type PipeChan<T> = FlatChan<T, PodFlattener<T>, PipeByteChan>;
-
-    /// Create a `FlatPort` from a `Reader`
-    pub fn reader_port<T:Copy + Owned,R:Reader>(
-        reader: R
-    ) -> ReaderPort<T, R> {
-        let unflat: PodUnflattener<T> = PodUnflattener::new();
-        let byte_port = ReaderBytePort::new(reader);
-        FlatPort::new(unflat, byte_port)
-    }
-
-    /// Create a `FlatChan` from a `Writer`
-    pub fn writer_chan<T:Copy + Owned,W:Writer>(
-        writer: W
-    ) -> WriterChan<T, W> {
-        let flat: PodFlattener<T> = PodFlattener::new();
-        let byte_chan = WriterByteChan::new(writer);
-        FlatChan::new(flat, byte_chan)
-    }
-
-    /// Create a `FlatPort` from a `Port<~[u8]>`
-    pub fn pipe_port<T:Copy + Owned>(port: Port<~[u8]>) -> PipePort<T> {
-        let unflat: PodUnflattener<T> = PodUnflattener::new();
-        let byte_port = PipeBytePort::new(port);
-        FlatPort::new(unflat, byte_port)
-    }
-
-    /// Create a `FlatChan` from a `Chan<~[u8]>`
-    pub fn pipe_chan<T:Copy + Owned>(chan: Chan<~[u8]>) -> PipeChan<T> {
-        let flat: PodFlattener<T> = PodFlattener::new();
-        let byte_chan = PipeByteChan::new(chan);
-        FlatChan::new(flat, byte_chan)
-    }
-
-    /// Create a pair of `FlatChan` and `FlatPort`, backed by pipes
-    pub fn pipe_stream<T:Copy + Owned>() -> (PipePort<T>, PipeChan<T>) {
-        let (port, chan) = comm::stream();
-        return (pipe_port(port), pipe_chan(chan));
-    }
-
-}
-
-/**
-Flatteners present a value as a byte vector
-*/
-pub trait Flattener<T> {
-    fn flatten(&self, val: T) -> ~[u8];
-}
-
-/**
-Unflatteners convert a byte vector to a value
-*/
-pub trait Unflattener<T> {
-    fn unflatten(&self, buf: ~[u8]) -> T;
-}
-
-/**
-BytePorts are a simple interface for receiving a specified number
-*/
-pub trait BytePort {
-    fn try_recv(&self, count: uint) -> Option<~[u8]>;
-}
-
-/**
-ByteChans are a simple interface for sending bytes
-*/
-pub trait ByteChan {
-    fn send(&self, val: ~[u8]);
-}
-
-static CONTINUE: [u8, ..4] = [0xAA, 0xBB, 0xCC, 0xDD];
-
-impl<T,U:Unflattener<T>,P:BytePort> GenericPort<T> for FlatPort<T, U, P> {
-    fn recv(&self) -> T {
-        match self.try_recv() {
-            Some(val) => val,
-            None => fail!("port is closed")
-        }
-    }
-    fn try_recv(&self) -> Option<T> {
-        let command = match self.byte_port.try_recv(CONTINUE.len()) {
-            Some(c) => c,
-            None => {
-                warn!("flatpipe: broken pipe");
-                return None;
-            }
-        };
-
-        if vec::eq(command, CONTINUE) {
-            let msg_len = match self.byte_port.try_recv(size_of::<u64>()) {
-                Some(bytes) => {
-                    io::u64_from_be_bytes(bytes, 0, size_of::<u64>())
-                },
-                None => {
-                    warn!("flatpipe: broken pipe");
-                    return None;
-                }
-            };
-
-            let msg_len = msg_len as uint;
-
-            match self.byte_port.try_recv(msg_len) {
-                Some(bytes) => {
-                    Some(self.unflattener.unflatten(bytes))
-                }
-                None => {
-                    warn!("flatpipe: broken pipe");
-                    return None;
-                }
-            }
-        }
-        else {
-            fail!("flatpipe: unrecognized command");
-        }
-    }
-}
-
-impl<T,F:Flattener<T>,C:ByteChan> GenericChan<T> for FlatChan<T, F, C> {
-    fn send(&self, val: T) {
-        self.byte_chan.send(CONTINUE.to_vec());
-        let bytes = self.flattener.flatten(val);
-        let len = bytes.len() as u64;
-        do io::u64_to_be_bytes(len, size_of::<u64>()) |len_bytes| {
-            self.byte_chan.send(len_bytes.to_vec());
-        }
-        self.byte_chan.send(bytes);
-    }
-}
-
-pub impl<T,U:Unflattener<T>,P:BytePort> FlatPort<T, U, P> {
-    fn new(u: U, p: P) -> FlatPort<T, U, P> {
-        FlatPort {
-            unflattener: u,
-            byte_port: p
-        }
-    }
-}
-
-pub impl<T,F:Flattener<T>,C:ByteChan> FlatChan<T, F, C> {
-    fn new(f: F, c: C) -> FlatChan<T, F, C> {
-        FlatChan {
-            flattener: f,
-            byte_chan: c
-        }
-    }
-}
-
-
-pub mod flatteners {
-    use ebml;
-    use flatpipes::{Flattener, Unflattener};
-    use io_util::BufReader;
-    use json;
-    use serialize::{Encoder, Decoder, Encodable, Decodable};
-
-    use core::cast;
-    use core::io::{Writer, Reader, ReaderUtil};
-    use core::ptr;
-    use core::sys::size_of;
-    use core::vec;
-
-
-    // FIXME #4074: Copy + Owned != POD
-    pub struct PodUnflattener<T> {
-        bogus: ()
-    }
-
-    pub struct PodFlattener<T> {
-        bogus: ()
-    }
-
-    impl<T:Copy + Owned> Unflattener<T> for PodUnflattener<T> {
-        fn unflatten(&self, buf: ~[u8]) -> T {
-            assert!(size_of::<T>() != 0);
-            assert_eq!(size_of::<T>(), buf.len());
-            let addr_of_init: &u8 = unsafe { &*vec::raw::to_ptr(buf) };
-            let addr_of_value: &T = unsafe { cast::transmute(addr_of_init) };
-            copy *addr_of_value
-        }
-    }
-
-    impl<T:Copy + Owned> Flattener<T> for PodFlattener<T> {
-        fn flatten(&self, val: T) -> ~[u8] {
-            assert!(size_of::<T>() != 0);
-            let val: *T = ptr::to_unsafe_ptr(&val);
-            let byte_value = val as *u8;
-            unsafe { vec::from_buf(byte_value, size_of::<T>()) }
-        }
-    }
-
-    pub impl<T:Copy + Owned> PodUnflattener<T> {
-        fn new() -> PodUnflattener<T> {
-            PodUnflattener {
-                bogus: ()
-            }
-        }
-    }
-
-    pub impl<T:Copy + Owned> PodFlattener<T> {
-        fn new() -> PodFlattener<T> {
-            PodFlattener {
-                bogus: ()
-            }
-        }
-    }
-
-
-    pub type DeserializeBuffer<T> = ~fn(buf: &[u8]) -> T;
-
-    pub struct DeserializingUnflattener<D, T> {
-        deserialize_buffer: DeserializeBuffer<T>
-    }
-
-    pub type SerializeValue<T> = ~fn(val: &T) -> ~[u8];
-
-    pub struct SerializingFlattener<S, T> {
-        serialize_value: SerializeValue<T>
-    }
-
-    impl<D:Decoder,T:Decodable<D>> Unflattener<T>
-            for DeserializingUnflattener<D, T> {
-        fn unflatten(&self, buf: ~[u8]) -> T {
-            (self.deserialize_buffer)(buf)
-        }
-    }
-
-    impl<S:Encoder,T:Encodable<S>> Flattener<T>
-            for SerializingFlattener<S, T> {
-        fn flatten(&self, val: T) -> ~[u8] {
-            (self.serialize_value)(&val)
-        }
-    }
-
-    pub impl<D:Decoder,T:Decodable<D>> DeserializingUnflattener<D, T> {
-        fn new(deserialize_buffer: DeserializeBuffer<T>)
-                   -> DeserializingUnflattener<D, T> {
-            DeserializingUnflattener {
-                deserialize_buffer: deserialize_buffer
-            }
-        }
-    }
-
-    pub impl<S:Encoder,T:Encodable<S>> SerializingFlattener<S, T> {
-        fn new(serialize_value: SerializeValue<T>)
-                   -> SerializingFlattener<S, T> {
-            SerializingFlattener {
-                serialize_value: serialize_value
-            }
-        }
-    }
-
-    /*
-    Implementations of the serialization functions required by
-    SerializingFlattener
-    */
-
-    pub fn deserialize_buffer<D: Decoder + FromReader,
-                              T: Decodable<D>>(
-                              buf: &[u8])
-                              -> T {
-        let buf = vec::to_owned(buf);
-        let buf_reader = @BufReader::new(buf);
-        let reader = buf_reader as @Reader;
-        let mut deser: D = FromReader::from_reader(reader);
-        Decodable::decode(&mut deser)
-    }
-
-    pub fn serialize_value<D: Encoder + FromWriter,
-                           T: Encodable<D>>(
-                           val: &T)
-                           -> ~[u8] {
-        do io::with_bytes_writer |writer| {
-            let mut ser = FromWriter::from_writer(writer);
-            val.encode(&mut ser);
-        }
-    }
-
-    pub trait FromReader {
-        fn from_reader(r: @Reader) -> Self;
-    }
-
-    pub trait FromWriter {
-        fn from_writer(w: @Writer) -> Self;
-    }
-
-    impl FromReader for json::Decoder {
-        fn from_reader(r: @Reader) -> json::Decoder {
-            match json::from_reader(r) {
-                Ok(json) => {
-                    json::Decoder(json)
-                }
-                Err(e) => fail!("flatpipe: can't parse json: %?", e)
-            }
-        }
-    }
-
-    impl FromWriter for json::Encoder {
-        fn from_writer(w: @Writer) -> json::Encoder {
-            json::Encoder(w)
-        }
-    }
-
-    impl FromReader for ebml::reader::Decoder {
-        fn from_reader(r: @Reader) -> ebml::reader::Decoder {
-            let buf = @r.read_whole_stream();
-            let doc = ebml::reader::Doc(buf);
-            ebml::reader::Decoder(doc)
-        }
-    }
-
-    impl FromWriter for ebml::writer::Encoder {
-        fn from_writer(w: @Writer) -> ebml::writer::Encoder {
-            ebml::writer::Encoder(w)
-        }
-    }
-
-}
-
-pub mod bytepipes {
-    use flatpipes::{ByteChan, BytePort};
-
-    use core::io::{Writer, Reader, ReaderUtil};
-    use core::comm::{Port, Chan};
-
-    pub struct ReaderBytePort<R> {
-        reader: R
-    }
-
-    pub struct WriterByteChan<W> {
-        writer: W
-    }
-
-    impl<R:Reader> BytePort for ReaderBytePort<R> {
-        fn try_recv(&self, count: uint) -> Option<~[u8]> {
-            let mut left = count;
-            let mut bytes = ~[];
-            while !self.reader.eof() && left > 0 {
-                assert!(left <= count);
-                assert!(left > 0);
-                let new_bytes = self.reader.read_bytes(left);
-                bytes.push_all(new_bytes);
-                assert!(new_bytes.len() <= left);
-                left -= new_bytes.len();
-            }
-
-            if left == 0 {
-                return Some(bytes);
-            } else {
-                warn!("flatpipe: dropped %? broken bytes", left);
-                return None;
-            }
-        }
-    }
-
-    impl<W:Writer> ByteChan for WriterByteChan<W> {
-        fn send(&self, val: ~[u8]) {
-            self.writer.write(val);
-        }
-    }
-
-    pub impl<R:Reader> ReaderBytePort<R> {
-        fn new(r: R) -> ReaderBytePort<R> {
-            ReaderBytePort {
-                reader: r
-            }
-        }
-    }
-
-    pub impl<W:Writer> WriterByteChan<W> {
-        fn new(w: W) -> WriterByteChan<W> {
-            WriterByteChan {
-                writer: w
-            }
-        }
-    }
-
-    // XXX: Remove `@mut` when this module is ported to the new I/O traits,
-    // which use `&mut self` properly.
-    pub struct PipeBytePort {
-        port: comm::Port<~[u8]>,
-        buf: @mut ~[u8]
-    }
-
-    pub struct PipeByteChan {
-        chan: comm::Chan<~[u8]>
-    }
-
-    impl BytePort for PipeBytePort {
-        fn try_recv(&self, count: uint) -> Option<~[u8]> {
-            if vec::uniq_len(&const *self.buf) >= count {
-                let mut bytes = ::core::util::replace(&mut *self.buf, ~[]);
-                *self.buf = bytes.slice(count, bytes.len()).to_owned();
-                bytes.truncate(count);
-                return Some(bytes);
-            } else if vec::uniq_len(&const *self.buf) > 0 {
-                let mut bytes = ::core::util::replace(&mut *self.buf, ~[]);
-                assert!(count > bytes.len());
-                match self.try_recv(count - bytes.len()) {
-                    Some(rest) => {
-                        bytes.push_all(rest);
-                        return Some(bytes);
-                    }
-                    None => return None
-                }
-            } else if vec::uniq_len(&const *self.buf) == 0 {
-                match self.port.try_recv() {
-                    Some(buf) => {
-                        assert!(!buf.is_empty());
-                        *self.buf = buf;
-                        return self.try_recv(count);
-                    }
-                    None => return None
-                }
-            } else {
-                ::core::util::unreachable()
-            }
-        }
-    }
-
-    impl ByteChan for PipeByteChan {
-        fn send(&self, val: ~[u8]) {
-            self.chan.send(val)
-        }
-    }
-
-    pub impl PipeBytePort {
-        fn new(p: Port<~[u8]>) -> PipeBytePort {
-            PipeBytePort {
-                port: p,
-                buf: @mut ~[]
-            }
-        }
-    }
-
-    pub impl PipeByteChan {
-        fn new(c: Chan<~[u8]>) -> PipeByteChan {
-            PipeByteChan {
-                chan: c
-            }
-        }
-    }
-
-}
-
-#[cfg(test)]
-mod test {
-    use flatpipes::{Flattener, Unflattener};
-    use flatpipes::bytepipes::*;
-    use flatpipes::pod;
-    use flatpipes::serial;
-    use io_util::BufReader;
-    use flatpipes::{BytePort, FlatChan, FlatPort};
-    use net::tcp::TcpSocketBuf;
-
-    use core::io::BytesWriter;
-
-    #[test]
-    #[ignore(reason = "ebml failure")]
-    fn test_serializing_memory_stream() {
-        let writer = BytesWriter();
-        let chan = serial::writer_chan(writer);
-
-        chan.send(10);
-
-        let bytes = copy *chan.byte_chan.writer.bytes;
-
-        let reader = BufReader::new(bytes);
-        let port = serial::reader_port(reader);
-
-        let res: int = port.recv();
-        assert_eq!(res, 10i);
-    }
-
-    #[test]
-    #[ignore(reason = "FIXME #6211 failing on linux snapshot machine")]
-    fn test_serializing_pipes() {
-        let (port, chan) = serial::pipe_stream();
-
-        do task::spawn || {
-            for int::range(0, 10) |i| {
-                chan.send(i)
-            }
-        }
-
-        for int::range(0, 10) |i| {
-            assert!(i == port.recv())
-        }
-    }
-
-    #[test]
-    #[ignore(reason = "ebml failure")]
-    fn test_serializing_boxes() {
-        let (port, chan) = serial::pipe_stream();
-
-        do task::spawn || {
-            for int::range(0, 10) |i| {
-                chan.send(@i)
-            }
-        }
-
-        for int::range(0, 10) |i| {
-            assert!(@i == port.recv())
-        }
-    }
-
-    #[test]
-    fn test_pod_memory_stream() {
-        let writer = BytesWriter();
-        let chan = pod::writer_chan(writer);
-
-        chan.send(10);
-
-        let bytes = copy *chan.byte_chan.writer.bytes;
-
-        let reader = BufReader::new(bytes);
-        let port = pod::reader_port(reader);
-
-        let res: int = port.recv();
-        assert_eq!(res, 10);
-    }
-
-    #[test]
-    fn test_pod_pipes() {
-        let (port, chan) = pod::pipe_stream();
-
-        do task::spawn || {
-            for int::range(0, 10) |i| {
-                chan.send(i)
-            }
-        }
-
-        for int::range(0, 10) |i| {
-            assert!(i == port.recv())
-        }
-    }
-
-    // FIXME #2064: Networking doesn't work on x86
-    #[test]
-    #[cfg(target_arch = "x86_64")]
-    fn test_pod_tcp_stream() {
-        fn reader_port(buf: TcpSocketBuf
-                      ) -> pod::ReaderPort<int, TcpSocketBuf> {
-            pod::reader_port(buf)
-        }
-        fn writer_chan(buf: TcpSocketBuf
-                      ) -> pod::WriterChan<int, TcpSocketBuf> {
-            pod::writer_chan(buf)
-        }
-        test_some_tcp_stream(reader_port, writer_chan, 9666);
-    }
-
-    #[test]
-    #[cfg(target_arch = "x86_64")]
-    fn test_serializing_tcp_stream() {
-        fn reader_port(buf: TcpSocketBuf
-                      ) -> serial::ReaderPort<int, TcpSocketBuf> {
-            serial::reader_port(buf)
-        }
-        fn writer_chan(buf: TcpSocketBuf
-                      ) -> serial::WriterChan<int, TcpSocketBuf> {
-            serial::writer_chan(buf)
-        }
-        test_some_tcp_stream(reader_port, writer_chan, 9667);
-    }
-
-    type ReaderPortFactory<U> =
-        ~fn(TcpSocketBuf) -> FlatPort<int, U, ReaderBytePort<TcpSocketBuf>>;
-    type WriterChanFactory<F> =
-        ~fn(TcpSocketBuf) -> FlatChan<int, F, WriterByteChan<TcpSocketBuf>>;
-
-    fn test_some_tcp_stream<U:Unflattener<int>,F:Flattener<int>>(
-        reader_port: ReaderPortFactory<U>,
-        writer_chan: WriterChanFactory<F>,
-        port: uint) {
-
-        use core::cell::Cell;
-        use net::ip;
-        use net::tcp;
-        use uv;
-
-        // Indicate to the client task that the server is listening
-        let (begin_connect_port, begin_connect_chan) = comm::stream();
-        // The connection is sent from the server task to the receiver task
-        // to handle the connection
-        let (accept_port, accept_chan) = comm::stream();
-        // The main task will wait until the test is over to proceed
-        let (finish_port, finish_chan) = comm::stream();
-
-        let addr0 = ip::v4::parse_addr("127.0.0.1");
-
-        let begin_connect_chan = Cell(begin_connect_chan);
-        let accept_chan = Cell(accept_chan);
-
-        // The server task
-        let addr = copy addr0;
-        do task::spawn || {
-            let iotask = &uv::global_loop::get();
-            let begin_connect_chan = begin_connect_chan.take();
-            let accept_chan = accept_chan.take();
-            let listen_res = do tcp::listen(
-                copy addr, port, 128, iotask, |_kill_ch| {
-                    // Tell the sender to initiate the connection
-                    debug!("listening");
-                    begin_connect_chan.send(())
-                }) |new_conn, kill_ch| {
-
-                // Incoming connection. Send it to the receiver task to accept
-                let (res_port, res_chan) = comm::stream();
-                accept_chan.send((new_conn, res_chan));
-                // Wait until the connection is accepted
-                res_port.recv();
-
-                // Stop listening
-                kill_ch.send(None)
-            };
-
-            assert!(listen_res.is_ok());
-        }
-
-        // Client task
-        let addr = copy addr0;
-        do task::spawn || {
-            // Wait for the server to start listening
-            begin_connect_port.recv();
-
-            debug!("connecting");
-            let iotask = &uv::global_loop::get();
-            let connect_result = tcp::connect(copy addr, port, iotask);
-            assert!(connect_result.is_ok());
-            let sock = result::unwrap(connect_result);
-            let socket_buf: tcp::TcpSocketBuf = tcp::socket_buf(sock);
-
-            // TcpSocketBuf is a Writer!
-            let chan = writer_chan(socket_buf);
-
-            for int::range(0, 10) |i| {
-                debug!("sending %?", i);
-                chan.send(i)
-            }
-        }
-
-        // Receiver task
-        do task::spawn || {
-            // Wait for a connection
-            let (conn, res_chan) = accept_port.recv();
-
-            debug!("accepting connection");
-            let accept_result = tcp::accept(conn);
-            debug!("accepted");
-            assert!(accept_result.is_ok());
-            let sock = result::unwrap(accept_result);
-            res_chan.send(());
-
-            let socket_buf: tcp::TcpSocketBuf = tcp::socket_buf(sock);
-
-            // TcpSocketBuf is a Reader!
-            let port = reader_port(socket_buf);
-
-            for int::range(0, 10) |i| {
-                let j = port.recv();
-                debug!("received %?", j);
-                assert_eq!(i, j);
-            }
-
-            // The test is over!
-            finish_chan.send(());
-        }
-
-        finish_port.recv();
-    }
-
-    // Tests that the different backends behave the same when the
-    // binary streaming protocol is broken
-    mod broken_protocol {
-        use flatpipes::{BytePort, FlatPort};
-        use flatpipes::flatteners::PodUnflattener;
-        use flatpipes::pod;
-        use io_util::BufReader;
-
-        type PortLoader<P> =
-            ~fn(~[u8]) -> FlatPort<int, PodUnflattener<int>, P>;
-
-        fn reader_port_loader(bytes: ~[u8]
-                             ) -> pod::ReaderPort<int, BufReader> {
-            let reader = BufReader::new(bytes);
-            pod::reader_port(reader)
-        }
-
-        fn pipe_port_loader(bytes: ~[u8]
-                           ) -> pod::PipePort<int> {
-            let (port, chan) = comm::stream();
-            if !bytes.is_empty() {
-                chan.send(bytes);
-            }
-            pod::pipe_port(port)
-        }
-
-        fn test_try_recv_none1<P:BytePort>(loader: PortLoader<P>) {
-            let bytes = ~[];
-            let port = loader(bytes);
-            let res: Option<int> = port.try_recv();
-            assert!(res.is_none());
-        }
-
-        #[test]
-        fn test_try_recv_none1_reader() {
-            test_try_recv_none1(reader_port_loader);
-        }
-        #[test]
-        fn test_try_recv_none1_pipe() {
-            test_try_recv_none1(pipe_port_loader);
-        }
-
-        fn test_try_recv_none2<P:BytePort>(loader: PortLoader<P>) {
-            // The control word in the protocol is interrupted
-            let bytes = ~[0];
-            let port = loader(bytes);
-            let res: Option<int> = port.try_recv();
-            assert!(res.is_none());
-        }
-
-        #[test]
-        fn test_try_recv_none2_reader() {
-            test_try_recv_none2(reader_port_loader);
-        }
-        #[test]
-        fn test_try_recv_none2_pipe() {
-            test_try_recv_none2(pipe_port_loader);
-        }
-
-        fn test_try_recv_none3<P:BytePort>(loader: PortLoader<P>) {
-            static CONTINUE: [u8, ..4] = [0xAA, 0xBB, 0xCC, 0xDD];
-            // The control word is followed by garbage
-            let bytes = CONTINUE.to_vec() + ~[0];
-            let port = loader(bytes);
-            let res: Option<int> = port.try_recv();
-            assert!(res.is_none());
-        }
-
-        #[test]
-        fn test_try_recv_none3_reader() {
-            test_try_recv_none3(reader_port_loader);
-        }
-        #[test]
-        fn test_try_recv_none3_pipe() {
-            test_try_recv_none3(pipe_port_loader);
-        }
-
-        fn test_try_recv_none4<P:BytePort>(loader: PortLoader<P>) {
-            assert!(do task::try || {
-                static CONTINUE: [u8, ..4] = [0xAA, 0xBB, 0xCC, 0xDD];
-                // The control word is followed by a valid length,
-                // then undeserializable garbage
-                let len_bytes = do io::u64_to_be_bytes(
-                    1, sys::size_of::<u64>()) |len_bytes| {
-                    len_bytes.to_vec()
-                };
-                let bytes = CONTINUE.to_vec() + len_bytes + ~[0, 0, 0, 0];
-
-                let port = loader(bytes);
-
-                let _res: Option<int> = port.try_recv();
-            }.is_err());
-        }
-
-        #[test]
-        #[ignore(cfg(windows))]
-        fn test_try_recv_none4_reader() {
-            test_try_recv_none4(reader_port_loader);
-        }
-        #[test]
-        #[ignore(cfg(windows))]
-        fn test_try_recv_none4_pipe() {
-            test_try_recv_none4(pipe_port_loader);
-        }
-    }
-
-}
diff --git a/src/libstd/net.rs b/src/libstd/from_str.rs
index ca1cc123596..ebf6d212466 100644
--- a/src/libstd/net.rs
+++ b/src/libstd/from_str.rs
@@ -8,18 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-/*!
-Top-level module for network-related functionality.
+//! The trait for types that can be created from strings
 
-Basically, including this module gives you:
+use option::Option;
 
-* `net_tcp`
-* `net_ip`
-* `net_url`
-
-See each of those three modules for documentation on what they do.
-*/
-
-pub use tcp = net_tcp;
-pub use ip = net_ip;
-pub use url = net_url;
+pub trait FromStr {
+    fn from_str(s: &str) -> Option<Self>;
+}
diff --git a/src/libstd/fun_treemap.rs b/src/libstd/fun_treemap.rs
deleted file mode 100644
index 6b051fa21b1..00000000000
--- a/src/libstd/fun_treemap.rs
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
- * A functional key,value store that works on anything.
- *
- * This works using a binary search tree. In the first version, it's a
- * very naive algorithm, but it will probably be updated to be a
- * red-black tree or something else.
- *
- * This is copied and modified from treemap right now. It's missing a lot
- * of features.
- */
-
-use core::cmp::{Eq, Ord};
-use core::option::{Some, None};
-
-pub type Treemap<K, V> = @TreeNode<K, V>;
-
-enum TreeNode<K, V> {
-    Empty,
-    Node(@K, @V, @TreeNode<K, V>, @TreeNode<K, V>)
-}
-
-/// Create a treemap
-pub fn init<K, V>() -> Treemap<K, V> { @Empty }
-
-/// Insert a value into the map
-pub fn insert<K:Copy + Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K, v: V) -> Treemap<K, V> {
-    @match m {
-        @Empty => Node(@k, @v, @Empty, @Empty),
-        @Node(@copy kk, vv, left, right) => cond!(
-            (k <  kk) { Node(@kk, vv, insert(left, k, v), right) }
-            (k == kk) { Node(@kk, @v, left, right)               }
-            _         { Node(@kk, vv, left, insert(right, k, v)) }
-        )
-    }
-}
-
-/// Find a value based on the key
-pub fn find<K:Eq + Ord,V:Copy>(m: Treemap<K, V>, k: K) -> Option<V> {
-    match *m {
-        Empty => None,
-        Node(@ref kk, @copy v, left, right) => cond!(
-            (k == *kk) { Some(v)        }
-            (k <  *kk) { find(left, k)  }
-            _          { find(right, k) }
-        )
-    }
-}
-
-/// Visit all pairs in the map in order.
-pub fn traverse<K, V: Copy>(m: Treemap<K, V>, f: &fn(&K, &V)) {
-    match *m {
-        Empty => (),
-        // Previously, this had what looked like redundant
-        // matches to me, so I changed it. but that may be a
-        // de-optimization -- tjc
-        Node(@ref k, @ref v, left, right) => {
-            traverse(left, f);
-            f(k, v);
-            traverse(right, f);
-        }
-    }
-}
diff --git a/src/libstd/future.rs b/src/libstd/future.rs
deleted file mode 100644
index 02828b8eaee..00000000000
--- a/src/libstd/future.rs
+++ /dev/null
@@ -1,210 +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.
-
-/*!
- * A type representing values that may be computed concurrently and
- * operations for working with them.
- *
- * # Example
- *
- * ~~~
- * # fn fib(n: uint) -> uint {42};
- * # fn make_a_sandwich() {};
- * let mut delayed_fib = std::future::spawn (|| fib(5000) );
- * make_a_sandwich();
- * println(fmt!("fib(5000) = %?", delayed_fib.get()))
- * ~~~
- */
-
-use core::cast;
-use core::cell::Cell;
-use core::comm::{PortOne, oneshot, send_one, recv_one};
-use core::task;
-use core::util::replace;
-
-#[doc = "The future type"]
-pub struct Future<A> {
-    priv state: FutureState<A>,
-}
-
-// n.b. It should be possible to get rid of this.
-// Add a test, though -- tjc
-// FIXME(#2829) -- futures should not be copyable, because they close
-// over ~fn's that have pipes and so forth within!
-#[unsafe_destructor]
-impl<A> Drop for Future<A> {
-    fn finalize(&self) {}
-}
-
-priv enum FutureState<A> {
-    Pending(~fn() -> A),
-    Evaluating,
-    Forced(A)
-}
-
-/// Methods on the `future` type
-pub impl<A:Copy> Future<A> {
-    fn get(&mut self) -> A {
-        //! Get the value of the future.
-        *(self.get_ref())
-    }
-}
-
-pub impl<A> Future<A> {
-    fn get_ref<'a>(&'a mut self) -> &'a A {
-        /*!
-        * Executes the future's closure and then returns a borrowed
-        * pointer to the result.  The borrowed pointer lasts as long as
-        * the future.
-        */
-        unsafe {
-            {
-                match self.state {
-                    Forced(ref mut v) => { return cast::transmute(v); }
-                    Evaluating => fail!("Recursive forcing of future!"),
-                    Pending(_) => {}
-                }
-            }
-            {
-                let state = replace(&mut self.state, Evaluating);
-                match state {
-                    Forced(_) | Evaluating => fail!("Logic error."),
-                    Pending(f) => {
-                        self.state = Forced(f());
-                        cast::transmute(self.get_ref())
-                    }
-                }
-            }
-        }
-    }
-}
-
-pub fn from_value<A>(val: A) -> Future<A> {
-    /*!
-     * Create a future from a value.
-     *
-     * The value is immediately available and calling `get` later will
-     * not block.
-     */
-
-    Future {state: Forced(val)}
-}
-
-pub fn from_port<A:Owned>(port: PortOne<A>) -> Future<A> {
-    /*!
-     * Create a future from a port
-     *
-     * The first time that the value is requested the task will block
-     * waiting for the result to be received on the port.
-     */
-
-    let port = Cell(port);
-    do from_fn {
-        recv_one(port.take())
-    }
-}
-
-pub fn from_fn<A>(f: ~fn() -> A) -> Future<A> {
-    /*!
-     * Create a future from a function.
-     *
-     * The first time that the value is requested it will be retrieved by
-     * calling the function.  Note that this function is a local
-     * function. It is not spawned into another task.
-     */
-
-    Future {state: Pending(f)}
-}
-
-pub fn spawn<A:Owned>(blk: ~fn() -> A) -> Future<A> {
-    /*!
-     * Create a future from a unique closure.
-     *
-     * The closure will be run in a new task and its result used as the
-     * value of the future.
-     */
-
-    let (port, chan) = oneshot();
-
-    let chan = Cell(chan);
-    do task::spawn {
-        let chan = chan.take();
-        send_one(chan, blk());
-    }
-
-    return from_port(port);
-}
-
-#[allow(non_implicitly_copyable_typarams)]
-#[cfg(test)]
-mod test {
-    use future::*;
-
-    use core::cell::Cell;
-    use core::comm::{oneshot, send_one};
-    use core::task;
-
-    #[test]
-    fn test_from_value() {
-        let mut f = from_value(~"snail");
-        assert_eq!(f.get(), ~"snail");
-    }
-
-    #[test]
-    fn test_from_port() {
-        let (po, ch) = oneshot();
-        send_one(ch, ~"whale");
-        let mut f = from_port(po);
-        assert_eq!(f.get(), ~"whale");
-    }
-
-    #[test]
-    fn test_from_fn() {
-        let mut f = from_fn(|| ~"brail");
-        assert_eq!(f.get(), ~"brail");
-    }
-
-    #[test]
-    fn test_interface_get() {
-        let mut f = from_value(~"fail");
-        assert_eq!(f.get(), ~"fail");
-    }
-
-    #[test]
-    fn test_get_ref_method() {
-        let mut f = from_value(22);
-        assert_eq!(*f.get_ref(), 22);
-    }
-
-    #[test]
-    fn test_spawn() {
-        let mut f = spawn(|| ~"bale");
-        assert_eq!(f.get(), ~"bale");
-    }
-
-    #[test]
-    #[should_fail]
-    #[ignore(cfg(target_os = "win32"))]
-    fn test_futurefail() {
-        let mut f = spawn(|| fail!());
-        let _x: ~str = f.get();
-    }
-
-    #[test]
-    fn test_sendable_future() {
-        let expected = "schlorf";
-        let f = Cell(do spawn { expected });
-        do task::spawn {
-            let mut f = f.take();
-            let actual = f.get();
-            assert_eq!(actual, expected);
-        }
-    }
-}
diff --git a/src/libstd/gc.rs b/src/libstd/gc.rs
new file mode 100644
index 00000000000..611b95a7745
--- /dev/null
+++ b/src/libstd/gc.rs
@@ -0,0 +1,371 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[doc(hidden)];
+
+/*! Precise garbage collector
+
+The precise GC exposes two functions, gc and
+cleanup_stack_for_failure. The gc function is the entry point to the
+garbage collector itself. The cleanup_stack_for_failure is the entry
+point for GC-based cleanup.
+
+Precise GC depends on changes to LLVM's GC which add support for
+automatic rooting and addrspace-based metadata marking. Rather than
+explicitly rooting pointers with LLVM's gcroot intrinsic, the GC
+merely creates allocas for pointers, and allows an LLVM pass to
+automatically infer roots based on the allocas present in a function
+(and live at a given location). The compiler communicates the type of
+the pointer to LLVM by setting the addrspace of the pointer type. The
+compiler then emits a map from addrspace to tydesc, which LLVM then
+uses to match pointers with their tydesc. The GC reads the metadata
+table produced by LLVM, and uses it to determine which glue functions
+to call to free objects on their respective heaps.
+
+GC-based cleanup is a replacement for landing pads which relies on the
+GC infrastructure to find pointers on the stack to cleanup. Whereas
+the normal GC needs to walk task-local heap allocations, the cleanup
+code needs to walk exchange heap allocations and stack-allocations
+with destructors.
+
+*/
+
+use cast;
+use container::{Map, Set};
+use io;
+use libc::{size_t, uintptr_t};
+use option::{None, Option, Some};
+use ptr;
+use hashmap::HashSet;
+use stackwalk::walk_stack;
+use sys;
+
+pub use stackwalk::Word;
+
+// Mirrors rust_stack.h stk_seg
+pub struct StackSegment {
+    prev: *StackSegment,
+    next: *StackSegment,
+    end: uintptr_t,
+    // And other fields which we don't care about...
+}
+
+pub mod rustrt {
+    use libc::size_t;
+    use stackwalk::Word;
+    use super::StackSegment;
+
+    #[link_name = "rustrt"]
+    pub extern {
+        #[rust_stack]
+        pub unsafe fn rust_call_tydesc_glue(root: *Word,
+                                            tydesc: *Word,
+                                            field: size_t);
+
+        #[rust_stack]
+        pub unsafe fn rust_gc_metadata() -> *Word;
+
+        pub unsafe fn rust_get_stack_segment() -> *StackSegment;
+        pub unsafe fn rust_get_c_stack() -> *StackSegment;
+    }
+}
+
+unsafe fn bump<T, U>(ptr: *T, count: uint) -> *U {
+    return cast::transmute(ptr::offset(ptr, count));
+}
+
+unsafe fn align_to_pointer<T>(ptr: *T) -> *T {
+    let align = sys::min_align_of::<*T>();
+    let ptr: uint = cast::transmute(ptr);
+    let ptr = (ptr + (align - 1)) & -align;
+    return cast::transmute(ptr);
+}
+
+unsafe fn get_safe_point_count() -> uint {
+    let module_meta = rustrt::rust_gc_metadata();
+    return *module_meta;
+}
+
+struct SafePoint {
+    sp_meta: *Word,
+    fn_meta: *Word,
+}
+
+// Returns the safe point metadata for the given program counter, if
+// any.
+unsafe fn is_safe_point(pc: *Word) -> Option<SafePoint> {
+    let module_meta = rustrt::rust_gc_metadata();
+    let num_safe_points = *module_meta;
+    let safe_points: *Word = bump(module_meta, 1);
+
+    if ptr::is_null(pc) {
+        return None;
+    }
+
+    // FIXME (#2997): Use binary rather than linear search.
+    let mut spi = 0;
+    while spi < num_safe_points {
+        let sp: **Word = bump(safe_points, spi*3);
+        let sp_loc = *sp;
+        if sp_loc == pc {
+            return Some(SafePoint {
+                sp_meta: *bump(sp, 1),
+                fn_meta: *bump(sp, 2),
+            });
+        }
+        spi += 1;
+    }
+    return None;
+}
+
+type Visitor<'self> = &'self fn(root: **Word, tydesc: *Word) -> bool;
+
+// Walks the list of roots for the given safe point, and calls visitor
+// on each root.
+unsafe fn _walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) -> bool {
+    let fp_bytes: *u8 = cast::transmute(fp);
+    let sp_meta: *u32 = cast::transmute(sp.sp_meta);
+
+    let num_stack_roots = *sp_meta as uint;
+    let num_reg_roots = *ptr::offset(sp_meta, 1) as uint;
+
+    let stack_roots: *u32 = bump(sp_meta, 2);
+    let reg_roots: *u8 = bump(stack_roots, num_stack_roots);
+    let addrspaces: *Word = align_to_pointer(bump(reg_roots, num_reg_roots));
+    let tydescs: ***Word = bump(addrspaces, num_stack_roots);
+
+    // Stack roots
+    let mut sri = 0;
+    while sri < num_stack_roots {
+        if *ptr::offset(addrspaces, sri) >= 1 {
+            let root =
+                ptr::offset(fp_bytes, *ptr::offset(stack_roots, sri) as Word)
+                as **Word;
+            let tydescpp = ptr::offset(tydescs, sri);
+            let tydesc = if ptr::is_not_null(tydescpp) &&
+                ptr::is_not_null(*tydescpp) {
+                **tydescpp
+            } else {
+                ptr::null()
+            };
+            if !visitor(root, tydesc) { return false; }
+        }
+        sri += 1;
+    }
+
+    // Register roots
+    let mut rri = 0;
+    while rri < num_reg_roots {
+        if *ptr::offset(addrspaces, num_stack_roots + rri) == 1 {
+            // FIXME(#2997): Need to find callee saved registers on the stack.
+        }
+        rri += 1;
+    }
+    return true;
+}
+
+unsafe fn walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) -> bool {
+    _walk_safe_point(fp, sp, visitor)
+}
+
+// Is fp contained in segment?
+unsafe fn is_frame_in_segment(fp: *Word, segment: *StackSegment) -> bool {
+    let begin: Word = cast::transmute(segment);
+    let end: Word = cast::transmute((*segment).end);
+    let frame: Word = cast::transmute(fp);
+
+    return begin <= frame && frame <= end;
+}
+
+struct Segment { segment: *StackSegment, boundary: bool }
+
+// Find and return the segment containing the given frame pointer. At
+// stack segment boundaries, returns true for boundary, so that the
+// caller can do any special handling to identify where the correct
+// return address is in the stack frame.
+unsafe fn find_segment_for_frame(fp: *Word, segment: *StackSegment)
+    -> Segment {
+    // Check if frame is in either current frame or previous frame.
+    let in_segment = is_frame_in_segment(fp, segment);
+    let in_prev_segment = ptr::is_not_null((*segment).prev) &&
+        is_frame_in_segment(fp, (*segment).prev);
+
+    // If frame is not in either segment, walk down segment list until
+    // we find the segment containing this frame.
+    if !in_segment && !in_prev_segment {
+        let mut segment = segment;
+        while ptr::is_not_null((*segment).next) &&
+            is_frame_in_segment(fp, (*segment).next) {
+            segment = (*segment).next;
+        }
+        return Segment {segment: segment, boundary: false};
+    }
+
+    // If frame is in previous frame, then we're at a boundary.
+    if !in_segment && in_prev_segment {
+        return Segment {segment: (*segment).prev, boundary: true};
+    }
+
+    // Otherwise, we're somewhere on the inside of the frame.
+    return Segment {segment: segment, boundary: false};
+}
+
+type Memory = uint;
+
+static task_local_heap: Memory = 1;
+static exchange_heap:   Memory = 2;
+static stack:           Memory = 4;
+
+static need_cleanup:    Memory = exchange_heap | stack;
+
+// Walks stack, searching for roots of the requested type, and passes
+// each root to the visitor.
+unsafe fn _walk_gc_roots(mem: Memory, sentinel: **Word, visitor: Visitor) -> bool {
+    let mut segment = rustrt::rust_get_stack_segment();
+    let mut last_ret: *Word = ptr::null();
+    // To avoid collecting memory used by the GC itself, skip stack
+    // frames until past the root GC stack frame. The root GC stack
+    // frame is marked by a sentinel, which is a box pointer stored on
+    // the stack.
+    let mut reached_sentinel = ptr::is_null(sentinel);
+    for walk_stack |frame| {
+        let pc = last_ret;
+        let Segment {segment: next_segment, boundary: boundary} =
+            find_segment_for_frame(frame.fp, segment);
+        segment = next_segment;
+        // Each stack segment is bounded by a morestack frame. The
+        // morestack frame includes two return addresses, one for
+        // morestack itself, at the normal offset from the frame
+        // pointer, and then a second return address for the
+        // function prologue (which called morestack after
+        // determining that it had hit the end of the stack).
+        // Since morestack itself takes two parameters, the offset
+        // for this second return address is 3 greater than the
+        // return address for morestack.
+        let ret_offset = if boundary { 4 } else { 1 };
+        last_ret = *ptr::offset(frame.fp, ret_offset) as *Word;
+
+        if ptr::is_null(pc) {
+            loop;
+        }
+
+        let mut delay_reached_sentinel = reached_sentinel;
+        let sp = is_safe_point(pc);
+        match sp {
+          Some(sp_info) => {
+            for walk_safe_point(frame.fp, sp_info) |root, tydesc| {
+                // Skip roots until we see the sentinel.
+                if !reached_sentinel {
+                    if root == sentinel {
+                        delay_reached_sentinel = true;
+                    }
+                    loop;
+                }
+
+                // Skip null pointers, which can occur when a
+                // unique pointer has already been freed.
+                if ptr::is_null(*root) {
+                    loop;
+                }
+
+                if ptr::is_null(tydesc) {
+                    // Root is a generic box.
+                    let refcount = **root;
+                    if mem | task_local_heap != 0 && refcount != -1 {
+                        if !visitor(root, tydesc) { return false; }
+                    } else if mem | exchange_heap != 0 && refcount == -1 {
+                        if !visitor(root, tydesc) { return false; }
+                    }
+                } else {
+                    // Root is a non-immediate.
+                    if mem | stack != 0 {
+                        if !visitor(root, tydesc) { return false; }
+                    }
+                }
+            }
+          }
+          None => ()
+        }
+        reached_sentinel = delay_reached_sentinel;
+    }
+    return true;
+}
+
+unsafe fn walk_gc_roots(mem: Memory, sentinel: **Word, visitor: Visitor) -> bool {
+    _walk_gc_roots(mem, sentinel, visitor)
+}
+pub fn gc() {
+    unsafe {
+        // Abort when GC is disabled.
+        if get_safe_point_count() == 0 {
+            return;
+        }
+
+        for walk_gc_roots(task_local_heap, ptr::null()) |_root, _tydesc| {
+            // FIXME(#2997): Walk roots and mark them.
+            io::stdout().write([46]); // .
+        }
+    }
+}
+
+#[cfg(gc)]
+fn expect_sentinel() -> bool { true }
+
+#[cfg(nogc)]
+fn expect_sentinel() -> bool { false }
+
+// Entry point for GC-based cleanup. Walks stack looking for exchange
+// heap and stack allocations requiring drop, and runs all
+// destructors.
+//
+// This should only be called from fail!, as it will drop the roots
+// which are *live* on the stack, rather than dropping those that are
+// dead.
+pub fn cleanup_stack_for_failure() {
+    unsafe {
+        // Abort when GC is disabled.
+        if get_safe_point_count() == 0 {
+            return;
+        }
+
+        // Leave a sentinel on the stack to mark the current frame. The
+        // stack walker will ignore any frames above the sentinel, thus
+        // avoiding collecting any memory being used by the stack walker
+        // itself.
+        //
+        // However, when core itself is not compiled with GC, then none of
+        // the functions in core will have GC metadata, which means we
+        // won't be able to find the sentinel root on the stack. In this
+        // case, we can safely skip the sentinel since we won't find our
+        // own stack roots on the stack anyway.
+        let sentinel_box = ~0;
+        let sentinel: **Word = if expect_sentinel() {
+            cast::transmute(&sentinel_box)
+        } else {
+            ptr::null()
+        };
+
+        let mut roots = HashSet::new();
+        for walk_gc_roots(need_cleanup, sentinel) |root, tydesc| {
+            // Track roots to avoid double frees.
+            if roots.contains(&*root) {
+                loop;
+            }
+            roots.insert(*root);
+
+            if ptr::is_null(tydesc) {
+                // FIXME #4420: Destroy this box
+                // FIXME #4330: Destroy this box
+            } else {
+                rustrt::rust_call_tydesc_glue(*root, tydesc, 3 as size_t);
+            }
+        }
+    }
+}
diff --git a/src/libstd/getopts.rs b/src/libstd/getopts.rs
deleted file mode 100644
index 6a9a60baae6..00000000000
--- a/src/libstd/getopts.rs
+++ /dev/null
@@ -1,1381 +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.
-
-/*!
- * Simple getopt alternative.
- *
- * Construct a vector of options, either by using reqopt, optopt, and optflag
- * or by building them from components yourself, and pass them to getopts,
- * along with a vector of actual arguments (not including argv[0]). You'll
- * either get a failure code back, or a match. You'll have to verify whether
- * the amount of 'free' arguments in the match is what you expect. Use opt_*
- * accessors to get argument values out of the matches object.
- *
- * Single-character options are expected to appear on the command line with a
- * single preceding dash; multiple-character options are expected to be
- * proceeded by two dashes. Options that expect an argument accept their
- * argument following either a space or an equals sign. Single-character
- * options don't require the space.
- *
- * # Example
- *
- * The following example shows simple command line parsing for an application
- * that requires an input file to be specified, accepts an optional output
- * file name following -o, and accepts both -h and --help as optional flags.
- *
- * ```
- *    extern mod std;
- *    use std::getopts::*;
- *
- *    fn do_work(in: &str, out: Option<~str>) {
- *      io::println(in);
- *      io::println(match out {
- *        Some(x) => x,
- *        None => ~"No Output"
- *      });
- *    }
- *
- *    fn print_usage(program: &str, _opts: &[std::getopts::Opt]) {
- *      io::println(fmt!("Usage: %s [options]", program));
- *      io::println("-o\t\tOutput");
- *      io::println("-h --help\tUsage");
- *    }
- *
- *    fn main() {
- *        let args = os::args();
- *
- *        let program = copy args[0];
- *
- *        let opts = ~[
- *            optopt("o"),
- *            optflag("h"),
- *            optflag("help")
- *        ];
- *        let matches = match getopts(vec::tail(args), opts) {
- *            result::Ok(m) => { m }
- *            result::Err(f) => { fail!(fail_str(f)) }
- *        };
- *        if opt_present(&matches, "h") || opt_present(&matches, "help") {
- *            print_usage(program, opts);
- *            return;
- *        }
- *        let output = opt_maybe_str(&matches, "o");
- *        let input: &str = if !matches.free.is_empty() {
- *            copy matches.free[0]
- *        } else {
- *            print_usage(program, opts);
- *            return;
- *        };
- *        do_work(input, output);
- *    }
- * ```
- */
-
-use core::cmp::Eq;
-use core::result::{Err, Ok};
-use core::result;
-use core::option::{Some, None};
-use core::str;
-use core::vec;
-
-#[deriving(Eq)]
-pub enum Name {
-    Long(~str),
-    Short(char),
-}
-
-#[deriving(Eq)]
-pub enum HasArg { Yes, No, Maybe, }
-
-#[deriving(Eq)]
-pub enum Occur { Req, Optional, Multi, }
-
-/// A description of a possible option
-#[deriving(Eq)]
-pub struct Opt {
-    name: Name,
-    hasarg: HasArg,
-    occur: Occur
-}
-
-fn mkname(nm: &str) -> Name {
-    let unm = str::to_owned(nm);
-    return if nm.len() == 1u {
-            Short(str::char_at(unm, 0u))
-        } else { Long(unm) };
-}
-
-/// Create an option that is required and takes an argument
-pub fn reqopt(name: &str) -> Opt {
-    return Opt {name: mkname(name), hasarg: Yes, occur: Req};
-}
-
-/// Create an option that is optional and takes an argument
-pub fn optopt(name: &str) -> Opt {
-    return Opt {name: mkname(name), hasarg: Yes, occur: Optional};
-}
-
-/// Create an option that is optional and does not take an argument
-pub fn optflag(name: &str) -> Opt {
-    return Opt {name: mkname(name), hasarg: No, occur: Optional};
-}
-
-/// Create an option that is optional and does not take an argument
-pub fn optflagmulti(name: &str) -> Opt {
-    return Opt {name: mkname(name), hasarg: No, occur: Multi};
-}
-
-/// Create an option that is optional and takes an optional argument
-pub fn optflagopt(name: &str) -> Opt {
-    return Opt {name: mkname(name), hasarg: Maybe, occur: Optional};
-}
-
-/**
- * Create an option that is optional, takes an argument, and may occur
- * multiple times
- */
-pub fn optmulti(name: &str) -> Opt {
-    return Opt {name: mkname(name), hasarg: Yes, occur: Multi};
-}
-
-#[deriving(Eq)]
-enum Optval { Val(~str), Given, }
-
-/**
- * The result of checking command line arguments. Contains a vector
- * of matches and a vector of free strings.
- */
-#[deriving(Eq)]
-pub struct Matches {
-    opts: ~[Opt],
-    vals: ~[~[Optval]],
-    free: ~[~str]
-}
-
-fn is_arg(arg: &str) -> bool {
-    return arg.len() > 1 && arg[0] == '-' as u8;
-}
-
-fn name_str(nm: &Name) -> ~str {
-    return match *nm {
-      Short(ch) => str::from_char(ch),
-      Long(copy s) => s
-    };
-}
-
-fn find_opt(opts: &[Opt], nm: Name) -> Option<uint> {
-    vec::position(opts, |opt| opt.name == nm)
-}
-
-/**
- * The type returned when the command line does not conform to the
- * expected format. Pass this value to <fail_str> to get an error message.
- */
-#[deriving(Eq)]
-pub enum Fail_ {
-    ArgumentMissing(~str),
-    UnrecognizedOption(~str),
-    OptionMissing(~str),
-    OptionDuplicated(~str),
-    UnexpectedArgument(~str),
-}
-
-/// Convert a `fail_` enum into an error string
-pub fn fail_str(f: Fail_) -> ~str {
-    return match f {
-        ArgumentMissing(ref nm) => {
-            ~"Argument to option '" + *nm + ~"' missing."
-        }
-        UnrecognizedOption(ref nm) => {
-            ~"Unrecognized option: '" + *nm + ~"'."
-        }
-        OptionMissing(ref nm) => {
-            ~"Required option '" + *nm + ~"' missing."
-        }
-        OptionDuplicated(ref nm) => {
-            ~"Option '" + *nm + ~"' given more than once."
-        }
-        UnexpectedArgument(ref nm) => {
-            ~"Option " + *nm + ~" does not take an argument."
-        }
-    };
-}
-
-/**
- * The result of parsing a command line with a set of options
- * (result::t<Matches, Fail_>)
- */
-pub type Result = result::Result<Matches, Fail_>;
-
-/**
- * Parse command line arguments according to the provided options
- *
- * On success returns `ok(Opt)`. Use functions such as `opt_present`
- * `opt_str`, etc. to interrogate results.  Returns `err(Fail_)` on failure.
- * Use <fail_str> to get an error message.
- */
-pub fn getopts(args: &[~str], opts: &[Opt]) -> Result {
-    let n_opts = opts.len();
-    fn f(_x: uint) -> ~[Optval] { return ~[]; }
-    let mut vals = vec::from_fn(n_opts, f);
-    let mut free: ~[~str] = ~[];
-    let l = args.len();
-    let mut i = 0;
-    while i < l {
-        let cur = copy args[i];
-        let curlen = cur.len();
-        if !is_arg(cur) {
-            free.push(cur);
-        } else if cur == ~"--" {
-            let mut j = i + 1;
-            while j < l { free.push(copy args[j]); j += 1; }
-            break;
-        } else {
-            let mut names;
-            let mut i_arg = None;
-            if cur[1] == '-' as u8 {
-                let tail = str::slice(cur, 2, curlen).to_owned();
-                let mut tail_eq = ~[];
-                for str::each_splitn_char(tail, '=', 1) |s| { tail_eq.push(s.to_owned()) }
-                if tail_eq.len() <= 1 {
-                    names = ~[Long(tail)];
-                } else {
-                    names =
-                        ~[Long(copy tail_eq[0])];
-                    i_arg = Some(copy tail_eq[1]);
-                }
-            } else {
-                let mut j = 1;
-                let mut last_valid_opt_id = None;
-                names = ~[];
-                while j < curlen {
-                    let range = str::char_range_at(cur, j);
-                    let opt = Short(range.ch);
-
-                    /* In a series of potential options (eg. -aheJ), if we
-                       see one which takes an argument, we assume all
-                       subsequent characters make up the argument. This
-                       allows options such as -L/usr/local/lib/foo to be
-                       interpreted correctly
-                    */
-
-                    match find_opt(opts, copy opt) {
-                      Some(id) => last_valid_opt_id = Some(id),
-                      None => {
-                        let arg_follows =
-                            last_valid_opt_id.is_some() &&
-                            match opts[last_valid_opt_id.get()]
-                              .hasarg {
-
-                              Yes | Maybe => true,
-                              No => false
-                            };
-                        if arg_follows && j < curlen {
-                            i_arg = Some(cur.slice(j, curlen).to_owned());
-                            break;
-                        } else {
-                            last_valid_opt_id = None;
-                        }
-                      }
-                    }
-                    names.push(opt);
-                    j = range.next;
-                }
-            }
-            let mut name_pos = 0;
-            for names.each() |nm| {
-                name_pos += 1;
-                let optid = match find_opt(opts, copy *nm) {
-                  Some(id) => id,
-                  None => return Err(UnrecognizedOption(name_str(nm)))
-                };
-                match opts[optid].hasarg {
-                  No => {
-                    if !i_arg.is_none() {
-                        return Err(UnexpectedArgument(name_str(nm)));
-                    }
-                    vals[optid].push(Given);
-                  }
-                  Maybe => {
-                    if !i_arg.is_none() {
-                        vals[optid].push(Val((copy i_arg).get()));
-                    } else if name_pos < names.len() ||
-                                  i + 1 == l || is_arg(args[i + 1]) {
-                        vals[optid].push(Given);
-                    } else { i += 1; vals[optid].push(Val(copy args[i])); }
-                  }
-                  Yes => {
-                    if !i_arg.is_none() {
-                        vals[optid].push(Val((copy i_arg).get()));
-                    } else if i + 1 == l {
-                        return Err(ArgumentMissing(name_str(nm)));
-                    } else { i += 1; vals[optid].push(Val(copy args[i])); }
-                  }
-                }
-            }
-        }
-        i += 1;
-    }
-    i = 0u;
-    while i < n_opts {
-        let n = vals[i].len();
-        let occ = opts[i].occur;
-        if occ == Req {
-            if n == 0 {
-                return Err(OptionMissing(name_str(&(opts[i].name))));
-            }
-        }
-        if occ != Multi {
-            if n > 1 {
-                return Err(OptionDuplicated(name_str(&(opts[i].name))));
-            }
-        }
-        i += 1;
-    }
-    return Ok(Matches {opts: vec::to_owned(opts),
-               vals: vals,
-               free: free});
-}
-
-fn opt_vals(mm: &Matches, nm: &str) -> ~[Optval] {
-    return match find_opt(mm.opts, mkname(nm)) {
-      Some(id) => copy mm.vals[id],
-      None => {
-        error!("No option '%s' defined", nm);
-        fail!()
-      }
-    };
-}
-
-fn opt_val(mm: &Matches, nm: &str) -> Optval { copy opt_vals(mm, nm)[0] }
-
-/// Returns true if an option was matched
-pub fn opt_present(mm: &Matches, nm: &str) -> bool {
-    !opt_vals(mm, nm).is_empty()
-}
-
-/// Returns the number of times an option was matched
-pub fn opt_count(mm: &Matches, nm: &str) -> uint {
-    opt_vals(mm, nm).len()
-}
-
-/// Returns true if any of several options were matched
-pub fn opts_present(mm: &Matches, names: &[~str]) -> bool {
-    for names.each |nm| {
-        match find_opt(mm.opts, mkname(*nm)) {
-            Some(id) if !mm.vals[id].is_empty() => return true,
-            _ => (),
-        };
-    }
-    false
-}
-
-
-/**
- * Returns the string argument supplied to a matching option
- *
- * Fails if the option was not matched or if the match did not take an
- * argument
- */
-pub fn opt_str(mm: &Matches, nm: &str) -> ~str {
-    return match opt_val(mm, nm) { Val(copy s) => s, _ => fail!() };
-}
-
-/**
- * Returns the string argument supplied to one of several matching options
- *
- * Fails if the no option was provided from the given list, or if the no such
- * option took an argument
- */
-pub fn opts_str(mm: &Matches, names: &[~str]) -> ~str {
-    for names.each |nm| {
-        match opt_val(mm, *nm) {
-          Val(copy s) => return s,
-          _ => ()
-        }
-    }
-    fail!();
-}
-
-
-/**
- * Returns a vector of the arguments provided to all matches of the given
- * option.
- *
- * Used when an option accepts multiple values.
- */
-pub fn opt_strs(mm: &Matches, nm: &str) -> ~[~str] {
-    let mut acc: ~[~str] = ~[];
-    for vec::each(opt_vals(mm, nm)) |v| {
-        match *v { Val(copy s) => acc.push(s), _ => () }
-    }
-    return acc;
-}
-
-/// Returns the string argument supplied to a matching option or none
-pub fn opt_maybe_str(mm: &Matches, nm: &str) -> Option<~str> {
-    let vals = opt_vals(mm, nm);
-    if vec::len::<Optval>(vals) == 0u { return None::<~str>; }
-    return match vals[0] {
-        Val(copy s) => Some(s),
-        _ => None
-    };
-}
-
-
-/**
- * Returns the matching string, a default, or none
- *
- * Returns none if the option was not present, `def` if the option was
- * present but no argument was provided, and the argument if the option was
- * present and an argument was provided.
- */
-pub fn opt_default(mm: &Matches, nm: &str, def: &str) -> Option<~str> {
-    let vals = opt_vals(mm, nm);
-    if vec::len::<Optval>(vals) == 0u { return None::<~str>; }
-    return match vals[0] { Val(copy s) => Some::<~str>(s),
-                           _      => Some::<~str>(str::to_owned(def)) }
-}
-
-#[deriving(Eq)]
-pub enum FailType {
-    ArgumentMissing_,
-    UnrecognizedOption_,
-    OptionMissing_,
-    OptionDuplicated_,
-    UnexpectedArgument_,
-}
-
-/** A module which provides a way to specify descriptions and
- *  groups of short and long option names, together.
- */
-pub mod groups {
-    use getopts::{HasArg, Long, Maybe, Multi, No, Occur, Opt, Optional, Req};
-    use getopts::{Short, Yes};
-
-    use core::str;
-    use core::vec;
-
-    /** one group of options, e.g., both -h and --help, along with
-     * their shared description and properties
-     */
-    #[deriving(Eq)]
-    pub struct OptGroup {
-        short_name: ~str,
-        long_name: ~str,
-        hint: ~str,
-        desc: ~str,
-        hasarg: HasArg,
-        occur: Occur
-    }
-
-    /// Create a long option that is required and takes an argument
-    pub fn reqopt(short_name: &str, long_name: &str,
-                  desc: &str, hint: &str) -> OptGroup {
-        let len = short_name.len();
-        assert!(len == 1 || len == 0);
-        return OptGroup { short_name: str::to_owned(short_name),
-                long_name: str::to_owned(long_name),
-                hint: str::to_owned(hint),
-                desc: str::to_owned(desc),
-                hasarg: Yes,
-                occur: Req};
-    }
-
-    /// Create a long option that is optional and takes an argument
-    pub fn optopt(short_name: &str, long_name: &str,
-                  desc: &str, hint: &str) -> OptGroup {
-        let len = short_name.len();
-        assert!(len == 1 || len == 0);
-        return OptGroup {short_name: str::to_owned(short_name),
-                long_name: str::to_owned(long_name),
-                hint: str::to_owned(hint),
-                desc: str::to_owned(desc),
-                hasarg: Yes,
-                occur: Optional};
-    }
-
-    /// Create a long option that is optional and does not take an argument
-    pub fn optflag(short_name: &str, long_name: &str,
-                   desc: &str) -> OptGroup {
-        let len = short_name.len();
-        assert!(len == 1 || len == 0);
-        return OptGroup {short_name: str::to_owned(short_name),
-                long_name: str::to_owned(long_name),
-                hint: ~"",
-                desc: str::to_owned(desc),
-                hasarg: No,
-                occur: Optional};
-    }
-
-    /// Create a long option that is optional and takes an optional argument
-    pub fn optflagopt(short_name: &str, long_name: &str,
-                      desc: &str, hint: &str) -> OptGroup {
-        let len = short_name.len();
-        assert!(len == 1 || len == 0);
-        return OptGroup {short_name: str::to_owned(short_name),
-                long_name: str::to_owned(long_name),
-                hint: str::to_owned(hint),
-                desc: str::to_owned(desc),
-                hasarg: Maybe,
-                occur: Optional};
-    }
-
-    /**
-     * Create a long option that is optional, takes an argument, and may occur
-     * multiple times
-     */
-    pub fn optmulti(short_name: &str, long_name: &str,
-                    desc: &str, hint: &str) -> OptGroup {
-        let len = short_name.len();
-        assert!(len == 1 || len == 0);
-        return OptGroup {short_name: str::to_owned(short_name),
-                long_name: str::to_owned(long_name),
-                hint: str::to_owned(hint),
-                desc: str::to_owned(desc),
-                hasarg: Yes,
-                occur: Multi};
-    }
-
-    // translate OptGroup into Opt
-    // (both short and long names correspond to different Opts)
-    pub fn long_to_short(lopt: &OptGroup) -> ~[Opt] {
-        let OptGroup{short_name: short_name,
-                     long_name: long_name,
-                     hasarg: hasarg,
-                     occur: occur,
-                     _} = copy *lopt;
-
-        match (short_name.len(), long_name.len()) {
-           (0,0) => fail!("this long-format option was given no name"),
-
-           (0,_) => ~[Opt {name: Long((long_name)),
-                           hasarg: hasarg,
-                           occur: occur}],
-
-           (1,0) => ~[Opt {name: Short(str::char_at(short_name, 0)),
-                           hasarg: hasarg,
-                           occur: occur}],
-
-           (1,_) => ~[Opt {name: Short(str::char_at(short_name, 0)),
-                           hasarg: hasarg,
-                           occur:  occur},
-                      Opt {name:   Long((long_name)),
-                           hasarg: hasarg,
-                           occur:  occur}],
-
-           (_,_) => fail!("something is wrong with the long-form opt")
-        }
-    }
-
-    /*
-     * Parse command line args with the provided long format options
-     */
-    pub fn getopts(args: &[~str], opts: &[OptGroup]) -> ::getopts::Result {
-        ::getopts::getopts(args, vec::flat_map(opts, long_to_short))
-    }
-
-    /**
-     * Derive a usage message from a set of long options
-     */
-    pub fn usage(brief: &str, opts: &[OptGroup]) -> ~str {
-
-        let desc_sep = ~"\n" + str::repeat(" ", 24);
-
-        let rows = vec::map(opts, |optref| {
-            let OptGroup{short_name: short_name,
-                         long_name: long_name,
-                         hint: hint,
-                         desc: desc,
-                         hasarg: hasarg,
-                         _} = copy *optref;
-
-            let mut row = str::repeat(" ", 4);
-
-            // short option
-            row += match short_name.len() {
-                0 => ~"",
-                1 => ~"-" + short_name + " ",
-                _ => fail!("the short name should only be 1 ascii char long"),
-            };
-
-            // long option
-            row += match long_name.len() {
-                0 => ~"",
-                _ => ~"--" + long_name + " ",
-            };
-
-            // arg
-            row += match hasarg {
-                No    => ~"",
-                Yes   => hint,
-                Maybe => ~"[" + hint + ~"]",
-            };
-
-            // FIXME: #5516
-            // here we just need to indent the start of the description
-            let rowlen = row.len();
-            row += if rowlen < 24 {
-                str::repeat(" ", 24 - rowlen)
-            } else {
-                copy desc_sep
-            };
-
-            // Normalize desc to contain words separated by one space character
-            let mut desc_normalized_whitespace = ~"";
-            for str::each_word(desc) |word| {
-                desc_normalized_whitespace.push_str(word);
-                desc_normalized_whitespace.push_char(' ');
-            }
-
-            // FIXME: #5516
-            let mut desc_rows = ~[];
-            for str::each_split_within(desc_normalized_whitespace, 54) |substr| {
-                desc_rows.push(substr.to_owned());
-            }
-
-            // FIXME: #5516
-            // wrapped description
-            row += str::connect(desc_rows, desc_sep);
-
-            row
-        });
-
-        return str::to_owned(brief)    +
-               ~"\n\nOptions:\n"         +
-               str::connect(rows, "\n") +
-               ~"\n\n";
-    }
-} // end groups module
-
-#[cfg(test)]
-mod tests {
-
-    use getopts::groups::OptGroup;
-    use getopts::*;
-
-    use core::result::{Err, Ok};
-    use core::result;
-
-    fn check_fail_type(f: Fail_, ft: FailType) {
-        match f {
-          ArgumentMissing(_) => assert!(ft == ArgumentMissing_),
-          UnrecognizedOption(_) => assert!(ft == UnrecognizedOption_),
-          OptionMissing(_) => assert!(ft == OptionMissing_),
-          OptionDuplicated(_) => assert!(ft == OptionDuplicated_),
-          UnexpectedArgument(_) => assert!(ft == UnexpectedArgument_)
-        }
-    }
-
-
-    // Tests for reqopt
-    #[test]
-    fn test_reqopt_long() {
-        let args = ~[~"--test=20"];
-        let opts = ~[reqopt(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-            assert!((opt_present(m, ~"test")));
-            assert_eq!(opt_str(m, ~"test"), ~"20");
-          }
-          _ => { fail!("test_reqopt_long failed"); }
-        }
-    }
-
-    #[test]
-    fn test_reqopt_long_missing() {
-        let args = ~[~"blah"];
-        let opts = ~[reqopt(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, OptionMissing_),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_reqopt_long_no_arg() {
-        let args = ~[~"--test"];
-        let opts = ~[reqopt(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, ArgumentMissing_),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_reqopt_long_multi() {
-        let args = ~[~"--test=20", ~"--test=30"];
-        let opts = ~[reqopt(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, OptionDuplicated_),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_reqopt_short() {
-        let args = ~[~"-t", ~"20"];
-        let opts = ~[reqopt(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-            assert!((opt_present(m, ~"t")));
-            assert_eq!(opt_str(m, ~"t"), ~"20");
-          }
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_reqopt_short_missing() {
-        let args = ~[~"blah"];
-        let opts = ~[reqopt(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, OptionMissing_),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_reqopt_short_no_arg() {
-        let args = ~[~"-t"];
-        let opts = ~[reqopt(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, ArgumentMissing_),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_reqopt_short_multi() {
-        let args = ~[~"-t", ~"20", ~"-t", ~"30"];
-        let opts = ~[reqopt(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, OptionDuplicated_),
-          _ => fail!()
-        }
-    }
-
-
-    // Tests for optopt
-    #[test]
-    fn test_optopt_long() {
-        let args = ~[~"--test=20"];
-        let opts = ~[optopt(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-            assert!((opt_present(m, ~"test")));
-            assert_eq!(opt_str(m, ~"test"), ~"20");
-          }
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optopt_long_missing() {
-        let args = ~[~"blah"];
-        let opts = ~[optopt(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => assert!(!opt_present(m, ~"test")),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optopt_long_no_arg() {
-        let args = ~[~"--test"];
-        let opts = ~[optopt(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, ArgumentMissing_),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optopt_long_multi() {
-        let args = ~[~"--test=20", ~"--test=30"];
-        let opts = ~[optopt(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, OptionDuplicated_),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optopt_short() {
-        let args = ~[~"-t", ~"20"];
-        let opts = ~[optopt(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-            assert!((opt_present(m, ~"t")));
-            assert_eq!(opt_str(m, ~"t"), ~"20");
-          }
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optopt_short_missing() {
-        let args = ~[~"blah"];
-        let opts = ~[optopt(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => assert!(!opt_present(m, ~"t")),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optopt_short_no_arg() {
-        let args = ~[~"-t"];
-        let opts = ~[optopt(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, ArgumentMissing_),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optopt_short_multi() {
-        let args = ~[~"-t", ~"20", ~"-t", ~"30"];
-        let opts = ~[optopt(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, OptionDuplicated_),
-          _ => fail!()
-        }
-    }
-
-
-    // Tests for optflag
-    #[test]
-    fn test_optflag_long() {
-        let args = ~[~"--test"];
-        let opts = ~[optflag(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => assert!(opt_present(m, ~"test")),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optflag_long_missing() {
-        let args = ~[~"blah"];
-        let opts = ~[optflag(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => assert!(!opt_present(m, ~"test")),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optflag_long_arg() {
-        let args = ~[~"--test=20"];
-        let opts = ~[optflag(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => {
-            error!(fail_str(copy f));
-            check_fail_type(f, UnexpectedArgument_);
-          }
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optflag_long_multi() {
-        let args = ~[~"--test", ~"--test"];
-        let opts = ~[optflag(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, OptionDuplicated_),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optflag_short() {
-        let args = ~[~"-t"];
-        let opts = ~[optflag(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => assert!(opt_present(m, ~"t")),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optflag_short_missing() {
-        let args = ~[~"blah"];
-        let opts = ~[optflag(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => assert!(!opt_present(m, ~"t")),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optflag_short_arg() {
-        let args = ~[~"-t", ~"20"];
-        let opts = ~[optflag(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-            // The next variable after the flag is just a free argument
-
-            assert!(m.free[0] == ~"20");
-          }
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optflag_short_multi() {
-        let args = ~[~"-t", ~"-t"];
-        let opts = ~[optflag(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, OptionDuplicated_),
-          _ => fail!()
-        }
-    }
-
-    // Tests for optflagmulti
-    #[test]
-    fn test_optflagmulti_short1() {
-        let args = ~[~"-v"];
-        let opts = ~[optflagmulti(~"v")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-            assert_eq!(opt_count(m, ~"v"), 1);
-          }
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optflagmulti_short2a() {
-        let args = ~[~"-v", ~"-v"];
-        let opts = ~[optflagmulti(~"v")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-            assert_eq!(opt_count(m, ~"v"), 2);
-          }
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optflagmulti_short2b() {
-        let args = ~[~"-vv"];
-        let opts = ~[optflagmulti(~"v")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-            assert_eq!(opt_count(m, ~"v"), 2);
-          }
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optflagmulti_long1() {
-        let args = ~[~"--verbose"];
-        let opts = ~[optflagmulti(~"verbose")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-            assert_eq!(opt_count(m, ~"verbose"), 1);
-          }
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optflagmulti_long2() {
-        let args = ~[~"--verbose", ~"--verbose"];
-        let opts = ~[optflagmulti(~"verbose")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-            assert_eq!(opt_count(m, ~"verbose"), 2);
-          }
-          _ => fail!()
-        }
-    }
-
-    // Tests for optmulti
-    #[test]
-    fn test_optmulti_long() {
-        let args = ~[~"--test=20"];
-        let opts = ~[optmulti(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-            assert!((opt_present(m, ~"test")));
-            assert_eq!(opt_str(m, ~"test"), ~"20");
-          }
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optmulti_long_missing() {
-        let args = ~[~"blah"];
-        let opts = ~[optmulti(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => assert!(!opt_present(m, ~"test")),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optmulti_long_no_arg() {
-        let args = ~[~"--test"];
-        let opts = ~[optmulti(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, ArgumentMissing_),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optmulti_long_multi() {
-        let args = ~[~"--test=20", ~"--test=30"];
-        let opts = ~[optmulti(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-              assert!(opt_present(m, ~"test"));
-              assert_eq!(opt_str(m, ~"test"), ~"20");
-              let pair = opt_strs(m, ~"test");
-              assert!(pair[0] == ~"20");
-              assert!(pair[1] == ~"30");
-          }
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optmulti_short() {
-        let args = ~[~"-t", ~"20"];
-        let opts = ~[optmulti(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-            assert!((opt_present(m, ~"t")));
-            assert_eq!(opt_str(m, ~"t"), ~"20");
-          }
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optmulti_short_missing() {
-        let args = ~[~"blah"];
-        let opts = ~[optmulti(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => assert!(!opt_present(m, ~"t")),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optmulti_short_no_arg() {
-        let args = ~[~"-t"];
-        let opts = ~[optmulti(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, ArgumentMissing_),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_optmulti_short_multi() {
-        let args = ~[~"-t", ~"20", ~"-t", ~"30"];
-        let opts = ~[optmulti(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-            assert!((opt_present(m, ~"t")));
-            assert_eq!(opt_str(m, ~"t"), ~"20");
-            let pair = opt_strs(m, ~"t");
-            assert!(pair[0] == ~"20");
-            assert!(pair[1] == ~"30");
-          }
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_unrecognized_option_long() {
-        let args = ~[~"--untest"];
-        let opts = ~[optmulti(~"t")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, UnrecognizedOption_),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_unrecognized_option_short() {
-        let args = ~[~"-t"];
-        let opts = ~[optmulti(~"test")];
-        let rs = getopts(args, opts);
-        match rs {
-          Err(copy f) => check_fail_type(f, UnrecognizedOption_),
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_combined() {
-        let args =
-            ~[~"prog", ~"free1", ~"-s", ~"20", ~"free2",
-              ~"--flag", ~"--long=30", ~"-f", ~"-m", ~"40",
-              ~"-m", ~"50", ~"-n", ~"-A B", ~"-n", ~"-60 70"];
-        let opts =
-            ~[optopt(~"s"), optflag(~"flag"), reqopt(~"long"),
-             optflag(~"f"), optmulti(~"m"), optmulti(~"n"),
-             optopt(~"notpresent")];
-        let rs = getopts(args, opts);
-        match rs {
-          Ok(ref m) => {
-            assert!(m.free[0] == ~"prog");
-            assert!(m.free[1] == ~"free1");
-            assert_eq!(opt_str(m, ~"s"), ~"20");
-            assert!(m.free[2] == ~"free2");
-            assert!((opt_present(m, ~"flag")));
-            assert_eq!(opt_str(m, ~"long"), ~"30");
-            assert!((opt_present(m, ~"f")));
-            let pair = opt_strs(m, ~"m");
-            assert!(pair[0] == ~"40");
-            assert!(pair[1] == ~"50");
-            let pair = opt_strs(m, ~"n");
-            assert!(pair[0] == ~"-A B");
-            assert!(pair[1] == ~"-60 70");
-            assert!((!opt_present(m, ~"notpresent")));
-          }
-          _ => fail!()
-        }
-    }
-
-    #[test]
-    fn test_multi() {
-        let args = ~[~"-e", ~"foo", ~"--encrypt", ~"foo"];
-        let opts = ~[optopt(~"e"), optopt(~"encrypt"), optopt(~"f")];
-        let matches = &match getopts(args, opts) {
-          result::Ok(m) => m,
-          result::Err(_) => fail!()
-        };
-        assert!(opts_present(matches, ~[~"e"]));
-        assert!(opts_present(matches, ~[~"encrypt"]));
-        assert!(opts_present(matches, ~[~"encrypt", ~"e"]));
-        assert!(opts_present(matches, ~[~"e", ~"encrypt"]));
-        assert!(!opts_present(matches, ~[~"f"]));
-        assert!(!opts_present(matches, ~[~"thing"]));
-        assert!(!opts_present(matches, ~[]));
-
-        assert_eq!(opts_str(matches, ~[~"e"]), ~"foo");
-        assert_eq!(opts_str(matches, ~[~"encrypt"]), ~"foo");
-        assert_eq!(opts_str(matches, ~[~"e", ~"encrypt"]), ~"foo");
-        assert_eq!(opts_str(matches, ~[~"encrypt", ~"e"]), ~"foo");
-    }
-
-    #[test]
-    fn test_nospace() {
-        let args = ~[~"-Lfoo", ~"-M."];
-        let opts = ~[optmulti(~"L"), optmulti(~"M")];
-        let matches = &match getopts(args, opts) {
-          result::Ok(m) => m,
-          result::Err(_) => fail!()
-        };
-        assert!(opts_present(matches, ~[~"L"]));
-        assert_eq!(opts_str(matches, ~[~"L"]), ~"foo");
-        assert!(opts_present(matches, ~[~"M"]));
-        assert_eq!(opts_str(matches, ~[~"M"]), ~".");
-
-    }
-
-    #[test]
-    fn test_groups_reqopt() {
-        let opt = groups::reqopt(~"b", ~"banana", ~"some bananas", ~"VAL");
-        assert!(opt == OptGroup { short_name: ~"b",
-                        long_name: ~"banana",
-                        hint: ~"VAL",
-                        desc: ~"some bananas",
-                        hasarg: Yes,
-                        occur: Req })
-    }
-
-    #[test]
-    fn test_groups_optopt() {
-        let opt = groups::optopt(~"a", ~"apple", ~"some apples", ~"VAL");
-        assert!(opt == OptGroup { short_name: ~"a",
-                        long_name: ~"apple",
-                        hint: ~"VAL",
-                        desc: ~"some apples",
-                        hasarg: Yes,
-                        occur: Optional })
-    }
-
-    #[test]
-    fn test_groups_optflag() {
-        let opt = groups::optflag(~"k", ~"kiwi", ~"some kiwis");
-        assert!(opt == OptGroup { short_name: ~"k",
-                        long_name: ~"kiwi",
-                        hint: ~"",
-                        desc: ~"some kiwis",
-                        hasarg: No,
-                        occur: Optional })
-    }
-
-    #[test]
-    fn test_groups_optflagopt() {
-        let opt = groups::optflagopt(~"p", ~"pineapple",
-                                       ~"some pineapples", ~"VAL");
-        assert!(opt == OptGroup { short_name: ~"p",
-                        long_name: ~"pineapple",
-                        hint: ~"VAL",
-                        desc: ~"some pineapples",
-                        hasarg: Maybe,
-                        occur: Optional })
-    }
-
-    #[test]
-    fn test_groups_optmulti() {
-        let opt = groups::optmulti(~"l", ~"lime",
-                                     ~"some limes", ~"VAL");
-        assert!(opt == OptGroup { short_name: ~"l",
-                        long_name: ~"lime",
-                        hint: ~"VAL",
-                        desc: ~"some limes",
-                        hasarg: Yes,
-                        occur: Multi })
-    }
-
-    #[test]
-    fn test_groups_long_to_short() {
-        let short = ~[reqopt(~"b"), reqopt(~"banana")];
-        let verbose = groups::reqopt(~"b", ~"banana",
-                                       ~"some bananas", ~"VAL");
-
-        assert_eq!(groups::long_to_short(&verbose), short);
-    }
-
-    #[test]
-    fn test_groups_getopts() {
-        let short = ~[
-            reqopt(~"b"), reqopt(~"banana"),
-            optopt(~"a"), optopt(~"apple"),
-            optflag(~"k"), optflagopt(~"kiwi"),
-            optflagopt(~"p"),
-            optmulti(~"l")
-        ];
-
-        let verbose = ~[
-            groups::reqopt(~"b", ~"banana", ~"Desc", ~"VAL"),
-            groups::optopt(~"a", ~"apple", ~"Desc", ~"VAL"),
-            groups::optflag(~"k", ~"kiwi", ~"Desc"),
-            groups::optflagopt(~"p", ~"", ~"Desc", ~"VAL"),
-            groups::optmulti(~"l", ~"", ~"Desc", ~"VAL"),
-        ];
-
-        let sample_args = ~[~"-k", ~"15", ~"--apple", ~"1", ~"k",
-                            ~"-p", ~"16", ~"l", ~"35"];
-
-        // FIXME #4681: sort options here?
-        assert!(getopts(sample_args, short)
-            == groups::getopts(sample_args, verbose));
-    }
-
-    #[test]
-    fn test_groups_usage() {
-        let optgroups = ~[
-            groups::reqopt(~"b", ~"banana", ~"Desc", ~"VAL"),
-            groups::optopt(~"a", ~"012345678901234567890123456789",
-                             ~"Desc", ~"VAL"),
-            groups::optflag(~"k", ~"kiwi", ~"Desc"),
-            groups::optflagopt(~"p", ~"", ~"Desc", ~"VAL"),
-            groups::optmulti(~"l", ~"", ~"Desc", ~"VAL"),
-        ];
-
-        let expected =
-~"Usage: fruits
-
-Options:
-    -b --banana VAL     Desc
-    -a --012345678901234567890123456789 VAL
-                        Desc
-    -k --kiwi           Desc
-    -p [VAL]            Desc
-    -l VAL              Desc
-
-";
-
-        let generated_usage = groups::usage(~"Usage: fruits", optgroups);
-
-        debug!("expected: <<%s>>", expected);
-        debug!("generated: <<%s>>", generated_usage);
-        assert_eq!(generated_usage, expected);
-    }
-
-    #[test]
-    fn test_groups_usage_description_wrapping() {
-        // indentation should be 24 spaces
-        // lines wrap after 78: or rather descriptions wrap after 54
-
-        let optgroups = ~[
-           groups::optflag(~"k", ~"kiwi",
-           ~"This is a long description which won't be wrapped..+.."), // 54
-           groups::optflag(~"a", ~"apple",
-           ~"This is a long description which _will_ be wrapped..+.."), // 55
-        ];
-
-        let expected =
-~"Usage: fruits
-
-Options:
-    -k --kiwi           This is a long description which won't be wrapped..+..
-    -a --apple          This is a long description which _will_ be
-                        wrapped..+..
-
-";
-
-        let usage = groups::usage(~"Usage: fruits", optgroups);
-
-        debug!("expected: <<%s>>", expected);
-        debug!("generated: <<%s>>", usage);
-        assert!(usage == expected)
-    }
-}
diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs
new file mode 100644
index 00000000000..69312f3a97b
--- /dev/null
+++ b/src/libstd/hash.rs
@@ -0,0 +1,557 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+ * Implementation of SipHash 2-4
+ *
+ * See: http://131002.net/siphash/
+ *
+ * Consider this as a main "general-purpose" hash for all hashtables: it
+ * runs at good speed (competitive with spooky and city) and permits
+ * cryptographically strong _keyed_ hashing. Key your hashtables from a
+ * CPRNG like rand::rng.
+ */
+
+use container::Container;
+use old_iter::BaseIter;
+use rt::io::Writer;
+use to_bytes::IterBytes;
+use uint;
+
+// Alias `SipState` to `State`.
+pub use State = hash::SipState;
+
+/**
+ * Types that can meaningfully be hashed should implement this.
+ *
+ * Note that this trait is likely to change somewhat as it is
+ * closely related to `to_bytes::IterBytes` and in almost all
+ * cases presently the two are (and must be) used together.
+ *
+ * In general, most types only need to implement `IterBytes`,
+ * and the implementation of `Hash` below will take care of
+ * the rest. This is the recommended approach, since constructing
+ * good keyed hash functions is quite difficult.
+ */
+pub trait Hash {
+    /**
+     * Compute a "keyed" hash of the value implementing the trait,
+     * taking `k0` and `k1` as "keying" parameters that randomize or
+     * otherwise perturb the hash function in such a way that a
+     * hash table built using such "keyed hash functions" cannot
+     * be made to perform linearly by an attacker controlling the
+     * hashtable's contents.
+     *
+     * In practical terms, we implement this using the SipHash 2-4
+     * function and require most types to only implement the
+     * IterBytes trait, that feeds SipHash.
+     */
+    fn hash_keyed(&self, k0: u64, k1: u64) -> u64;
+}
+
+// When we have default methods, won't need this.
+pub trait HashUtil {
+    fn hash(&self) -> u64;
+}
+
+impl<A:Hash> HashUtil for A {
+    #[inline(always)]
+    fn hash(&self) -> u64 { self.hash_keyed(0,0) }
+}
+
+/// Streaming hash-functions should implement this.
+pub trait Streaming {
+    fn input(&mut self, &[u8]);
+    // These can be refactored some when we have default methods.
+    fn result_bytes(&mut self) -> ~[u8];
+    fn result_str(&mut self) -> ~str;
+    fn result_u64(&mut self) -> u64;
+    fn reset(&mut self);
+}
+
+impl<A:IterBytes> Hash for A {
+    #[inline(always)]
+    fn hash_keyed(&self, k0: u64, k1: u64) -> u64 {
+        let mut s = State::new(k0, k1);
+        for self.iter_bytes(true) |bytes| {
+            s.input(bytes);
+        }
+        s.result_u64()
+    }
+}
+
+fn hash_keyed_2<A: IterBytes,
+                B: IterBytes>(a: &A, b: &B, k0: u64, k1: u64) -> u64 {
+    let mut s = State::new(k0, k1);
+    for a.iter_bytes(true) |bytes| {
+        s.input(bytes);
+    }
+    for b.iter_bytes(true) |bytes| {
+        s.input(bytes);
+    }
+    s.result_u64()
+}
+
+fn hash_keyed_3<A: IterBytes,
+                B: IterBytes,
+                C: IterBytes>(a: &A, b: &B, c: &C, k0: u64, k1: u64) -> u64 {
+    let mut s = State::new(k0, k1);
+    for a.iter_bytes(true) |bytes| {
+        s.input(bytes);
+    }
+    for b.iter_bytes(true) |bytes| {
+        s.input(bytes);
+    }
+    for c.iter_bytes(true) |bytes| {
+        s.input(bytes);
+    }
+    s.result_u64()
+}
+
+fn hash_keyed_4<A: IterBytes,
+                B: IterBytes,
+                C: IterBytes,
+                D: IterBytes>(
+                a: &A,
+                b: &B,
+                c: &C,
+                d: &D,
+                k0: u64,
+                k1: u64)
+                -> u64 {
+    let mut s = State::new(k0, k1);
+    for a.iter_bytes(true) |bytes| {
+        s.input(bytes);
+    }
+    for b.iter_bytes(true) |bytes| {
+        s.input(bytes);
+    }
+    for c.iter_bytes(true) |bytes| {
+        s.input(bytes);
+    }
+    for d.iter_bytes(true) |bytes| {
+        s.input(bytes);
+    }
+    s.result_u64()
+}
+
+fn hash_keyed_5<A: IterBytes,
+                B: IterBytes,
+                C: IterBytes,
+                D: IterBytes,
+                E: IterBytes>(
+                a: &A,
+                b: &B,
+                c: &C,
+                d: &D,
+                e: &E,
+                k0: u64,
+                k1: u64)
+                -> u64 {
+    let mut s = State::new(k0, k1);
+    for a.iter_bytes(true) |bytes| {
+        s.input(bytes);
+    }
+    for b.iter_bytes(true) |bytes| {
+        s.input(bytes);
+    }
+    for c.iter_bytes(true) |bytes| {
+        s.input(bytes);
+    }
+    for d.iter_bytes(true) |bytes| {
+        s.input(bytes);
+    }
+    for e.iter_bytes(true) |bytes| {
+        s.input(bytes);
+    }
+    s.result_u64()
+}
+
+#[inline(always)]
+pub fn default_state() -> State {
+    State::new(0, 0)
+}
+
+struct SipState {
+    k0: u64,
+    k1: u64,
+    length: uint, // how many bytes we've processed
+    v0: u64,      // hash state
+    v1: u64,
+    v2: u64,
+    v3: u64,
+    tail: [u8, ..8], // unprocessed bytes
+    ntail: uint,  // how many bytes in tail are valid
+}
+
+impl SipState {
+    #[inline(always)]
+    fn new(key0: u64, key1: u64) -> SipState {
+        let mut state = SipState {
+            k0: key0,
+            k1: key1,
+            length: 0,
+            v0: 0,
+            v1: 0,
+            v2: 0,
+            v3: 0,
+            tail: [ 0, 0, 0, 0, 0, 0, 0, 0 ],
+            ntail: 0,
+        };
+        state.reset();
+        state
+    }
+}
+
+// sadly, these macro definitions can't appear later,
+// because they're needed in the following defs;
+// this design could be improved.
+
+macro_rules! u8to64_le (
+    ($buf:expr, $i:expr) =>
+    ($buf[0+$i] as u64 |
+     $buf[1+$i] as u64 << 8 |
+     $buf[2+$i] as u64 << 16 |
+     $buf[3+$i] as u64 << 24 |
+     $buf[4+$i] as u64 << 32 |
+     $buf[5+$i] as u64 << 40 |
+     $buf[6+$i] as u64 << 48 |
+     $buf[7+$i] as u64 << 56)
+)
+
+macro_rules! rotl (
+    ($x:expr, $b:expr) =>
+    (($x << $b) | ($x >> (64 - $b)))
+)
+
+macro_rules! compress (
+    ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
+    ({
+        $v0 += $v1; $v1 = rotl!($v1, 13); $v1 ^= $v0;
+        $v0 = rotl!($v0, 32);
+        $v2 += $v3; $v3 = rotl!($v3, 16); $v3 ^= $v2;
+        $v0 += $v3; $v3 = rotl!($v3, 21); $v3 ^= $v0;
+        $v2 += $v1; $v1 = rotl!($v1, 17); $v1 ^= $v2;
+        $v2 = rotl!($v2, 32);
+    })
+)
+
+
+impl Writer for SipState {
+    // Methods for io::writer
+    #[inline(always)]
+    fn write(&mut self, msg: &[u8]) {
+        let length = msg.len();
+        self.length += length;
+
+        let mut needed = 0u;
+
+        if self.ntail != 0 {
+            needed = 8 - self.ntail;
+
+            if length < needed {
+                let mut t = 0;
+                while t < length {
+                    self.tail[self.ntail+t] = msg[t];
+                    t += 1;
+                }
+                self.ntail += length;
+                return;
+            }
+
+            let mut t = 0;
+            while t < needed {
+                self.tail[self.ntail+t] = msg[t];
+                t += 1;
+            }
+
+            let m = u8to64_le!(self.tail, 0);
+
+            self.v3 ^= m;
+            compress!(self.v0, self.v1, self.v2, self.v3);
+            compress!(self.v0, self.v1, self.v2, self.v3);
+            self.v0 ^= m;
+
+            self.ntail = 0;
+        }
+
+        // Buffered tail is now flushed, process new input.
+        let len = length - needed;
+        let end = len & (!0x7);
+        let left = len & 0x7;
+
+        let mut i = needed;
+        while i < end {
+            let mi = u8to64_le!(msg, i);
+
+            self.v3 ^= mi;
+            compress!(self.v0, self.v1, self.v2, self.v3);
+            compress!(self.v0, self.v1, self.v2, self.v3);
+            self.v0 ^= mi;
+
+            i += 8;
+        }
+
+        let mut t = 0u;
+        while t < left {
+            self.tail[t] = msg[i+t];
+            t += 1
+        }
+        self.ntail = left;
+    }
+
+    fn flush(&mut self) {
+        // No-op
+    }
+}
+
+impl Streaming for SipState {
+    #[inline(always)]
+    fn input(&mut self, buf: &[u8]) {
+        self.write(buf);
+    }
+
+    #[inline(always)]
+    fn result_u64(&mut self) -> u64 {
+        let mut v0 = self.v0;
+        let mut v1 = self.v1;
+        let mut v2 = self.v2;
+        let mut v3 = self.v3;
+
+        let mut b : u64 = (self.length as u64 & 0xff) << 56;
+
+        if self.ntail > 0 { b |= self.tail[0] as u64 <<  0; }
+        if self.ntail > 1 { b |= self.tail[1] as u64 <<  8; }
+        if self.ntail > 2 { b |= self.tail[2] as u64 << 16; }
+        if self.ntail > 3 { b |= self.tail[3] as u64 << 24; }
+        if self.ntail > 4 { b |= self.tail[4] as u64 << 32; }
+        if self.ntail > 5 { b |= self.tail[5] as u64 << 40; }
+        if self.ntail > 6 { b |= self.tail[6] as u64 << 48; }
+
+        v3 ^= b;
+        compress!(v0, v1, v2, v3);
+        compress!(v0, v1, v2, v3);
+        v0 ^= b;
+
+        v2 ^= 0xff;
+        compress!(v0, v1, v2, v3);
+        compress!(v0, v1, v2, v3);
+        compress!(v0, v1, v2, v3);
+        compress!(v0, v1, v2, v3);
+
+        return (v0 ^ v1 ^ v2 ^ v3);
+    }
+
+    fn result_bytes(&mut self) -> ~[u8] {
+        let h = self.result_u64();
+        ~[(h >> 0) as u8,
+          (h >> 8) as u8,
+          (h >> 16) as u8,
+          (h >> 24) as u8,
+          (h >> 32) as u8,
+          (h >> 40) as u8,
+          (h >> 48) as u8,
+          (h >> 56) as u8,
+        ]
+    }
+
+    fn result_str(&mut self) -> ~str {
+        let r = self.result_bytes();
+        let mut s = ~"";
+        for r.each |b| {
+            s += uint::to_str_radix(*b as uint, 16u);
+        }
+        s
+    }
+
+    #[inline(always)]
+    fn reset(&mut self) {
+        self.length = 0;
+        self.v0 = self.k0 ^ 0x736f6d6570736575;
+        self.v1 = self.k1 ^ 0x646f72616e646f6d;
+        self.v2 = self.k0 ^ 0x6c7967656e657261;
+        self.v3 = self.k1 ^ 0x7465646279746573;
+        self.ntail = 0;
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use prelude::*;
+
+    #[test]
+    fn test_siphash() {
+        let vecs : [[u8, ..8], ..64] = [
+            [ 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, ],
+            [ 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, ],
+            [ 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, ],
+            [ 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, ],
+            [ 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, ],
+            [ 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, ],
+            [ 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, ],
+            [ 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, ],
+            [ 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, ],
+            [ 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, ],
+            [ 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, ],
+            [ 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, ],
+            [ 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, ],
+            [ 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, ],
+            [ 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, ],
+            [ 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, ],
+            [ 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, ],
+            [ 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, ],
+            [ 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, ],
+            [ 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, ],
+            [ 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, ],
+            [ 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, ],
+            [ 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, ],
+            [ 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, ],
+            [ 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, ],
+            [ 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, ],
+            [ 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, ],
+            [ 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, ],
+            [ 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, ],
+            [ 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, ],
+            [ 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, ],
+            [ 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, ],
+            [ 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, ],
+            [ 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, ],
+            [ 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, ],
+            [ 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, ],
+            [ 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, ],
+            [ 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, ],
+            [ 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, ],
+            [ 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, ],
+            [ 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, ],
+            [ 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, ],
+            [ 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, ],
+            [ 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, ],
+            [ 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, ],
+            [ 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, ],
+            [ 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, ],
+            [ 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, ],
+            [ 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, ],
+            [ 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, ],
+            [ 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, ],
+            [ 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, ],
+            [ 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, ],
+            [ 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, ],
+            [ 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, ],
+            [ 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, ],
+            [ 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, ],
+            [ 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, ],
+            [ 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, ],
+            [ 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, ],
+            [ 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, ],
+            [ 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, ],
+            [ 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, ],
+            [ 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, ]
+        ];
+
+        let k0 = 0x_07_06_05_04_03_02_01_00_u64;
+        let k1 = 0x_0f_0e_0d_0c_0b_0a_09_08_u64;
+        let mut buf : ~[u8] = ~[];
+        let mut t = 0;
+        let mut stream_inc = SipState::new(k0, k1);
+        let mut stream_full = SipState::new(k0, k1);
+
+        fn to_hex_str(r: &[u8, ..8]) -> ~str {
+            let mut s = ~"";
+            for (*r).each |b| {
+                s += uint::to_str_radix(*b as uint, 16u);
+            }
+            s
+        }
+
+        while t < 64 {
+            debug!("siphash test %?", t);
+            let vec = u8to64_le!(vecs[t], 0);
+            let out = buf.hash_keyed(k0, k1);
+            debug!("got %?, expected %?", out, vec);
+            assert_eq!(vec, out);
+
+            stream_full.reset();
+            stream_full.input(buf);
+            let f = stream_full.result_str();
+            let i = stream_inc.result_str();
+            let v = to_hex_str(&vecs[t]);
+            debug!("%d: (%s) => inc=%s full=%s", t, v, i, f);
+
+            assert!(f == i && f == v);
+
+            buf += ~[t as u8];
+            stream_inc.input(~[t as u8]);
+
+            t += 1;
+        }
+    }
+
+    #[test] #[cfg(target_arch = "arm")]
+    fn test_hash_uint() {
+        let val = 0xdeadbeef_deadbeef_u64;
+        assert!((val as u64).hash() != (val as uint).hash());
+        assert_eq!((val as u32).hash(), (val as uint).hash());
+    }
+    #[test] #[cfg(target_arch = "x86_64")]
+    fn test_hash_uint() {
+        let val = 0xdeadbeef_deadbeef_u64;
+        assert_eq!((val as u64).hash(), (val as uint).hash());
+        assert!((val as u32).hash() != (val as uint).hash());
+    }
+    #[test] #[cfg(target_arch = "x86")]
+    fn test_hash_uint() {
+        let val = 0xdeadbeef_deadbeef_u64;
+        assert!((val as u64).hash() != (val as uint).hash());
+        assert_eq!((val as u32).hash(), (val as uint).hash());
+    }
+
+    #[test]
+    fn test_hash_idempotent() {
+        let val64 = 0xdeadbeef_deadbeef_u64;
+        val64.hash() == val64.hash();
+        let val32 = 0xdeadbeef_u32;
+        val32.hash() == val32.hash();
+    }
+
+    #[test]
+    fn test_hash_no_bytes_dropped_64() {
+        let val = 0xdeadbeef_deadbeef_u64;
+
+        assert!(val.hash() != zero_byte(val, 0).hash());
+        assert!(val.hash() != zero_byte(val, 1).hash());
+        assert!(val.hash() != zero_byte(val, 2).hash());
+        assert!(val.hash() != zero_byte(val, 3).hash());
+        assert!(val.hash() != zero_byte(val, 4).hash());
+        assert!(val.hash() != zero_byte(val, 5).hash());
+        assert!(val.hash() != zero_byte(val, 6).hash());
+        assert!(val.hash() != zero_byte(val, 7).hash());
+
+        fn zero_byte(val: u64, byte: uint) -> u64 {
+            assert!(byte < 8);
+            val & !(0xff << (byte * 8))
+        }
+    }
+
+    #[test]
+    fn test_hash_no_bytes_dropped_32() {
+        let val = 0xdeadbeef_u32;
+
+        assert!(val.hash() != zero_byte(val, 0).hash());
+        assert!(val.hash() != zero_byte(val, 1).hash());
+        assert!(val.hash() != zero_byte(val, 2).hash());
+        assert!(val.hash() != zero_byte(val, 3).hash());
+
+        fn zero_byte(val: u32, byte: uint) -> u32 {
+            assert!(byte < 4);
+            val & !(0xff << (byte * 8))
+        }
+    }
+}
diff --git a/src/libstd/hashmap.rs b/src/libstd/hashmap.rs
new file mode 100644
index 00000000000..e6ccb7a1d6b
--- /dev/null
+++ b/src/libstd/hashmap.rs
@@ -0,0 +1,989 @@
+// 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.
+
+//! An unordered map and set type implemented as hash tables
+//!
+//! The tables use a keyed hash with new random keys generated for each container, so the ordering
+//! of a set of keys in a hash table is randomized.
+
+use container::{Container, Mutable, Map, Set};
+use cmp::{Eq, Equiv};
+use hash::Hash;
+use old_iter::BaseIter;
+use old_iter;
+use option::{None, Option, Some};
+use rand::RngUtil;
+use rand;
+use uint;
+use vec;
+use kinds::Copy;
+use util::{replace, unreachable};
+
+static INITIAL_CAPACITY: uint = 32u; // 2^5
+
+struct Bucket<K,V> {
+    hash: uint,
+    key: K,
+    value: V,
+}
+
+pub struct HashMap<K,V> {
+    priv k0: u64,
+    priv k1: u64,
+    priv resize_at: uint,
+    priv size: uint,
+    priv buckets: ~[Option<Bucket<K, V>>],
+}
+
+// We could rewrite FoundEntry to have type Option<&Bucket<K, V>>
+// which would be nifty
+enum SearchResult {
+    FoundEntry(uint), FoundHole(uint), TableFull
+}
+
+#[inline(always)]
+fn resize_at(capacity: uint) -> uint {
+    ((capacity as float) * 3. / 4.) as uint
+}
+
+pub fn linear_map_with_capacity<K:Eq + Hash,V>(
+    initial_capacity: uint) -> HashMap<K, V> {
+    let mut r = rand::task_rng();
+    linear_map_with_capacity_and_keys(r.gen(), r.gen(),
+                                      initial_capacity)
+}
+
+fn linear_map_with_capacity_and_keys<K:Eq + Hash,V>(
+    k0: u64, k1: u64,
+    initial_capacity: uint) -> HashMap<K, V> {
+    HashMap {
+        k0: k0, k1: k1,
+        resize_at: resize_at(initial_capacity),
+        size: 0,
+        buckets: vec::from_fn(initial_capacity, |_| None)
+    }
+}
+
+priv impl<K:Hash + Eq,V> HashMap<K, V> {
+    #[inline(always)]
+    fn to_bucket(&self, h: uint) -> uint {
+        // A good hash function with entropy spread over all of the
+        // bits is assumed. SipHash is more than good enough.
+        h % self.buckets.len()
+    }
+
+    #[inline(always)]
+    fn next_bucket(&self, idx: uint, len_buckets: uint) -> uint {
+        let n = (idx + 1) % len_buckets;
+        debug!("next_bucket(%?, %?) = %?", idx, len_buckets, n);
+        n
+    }
+
+    #[inline(always)]
+    fn bucket_sequence(&self, hash: uint,
+                       op: &fn(uint) -> bool) -> bool {
+        let start_idx = self.to_bucket(hash);
+        let len_buckets = self.buckets.len();
+        let mut idx = start_idx;
+        loop {
+            if !op(idx) { return false; }
+            idx = self.next_bucket(idx, len_buckets);
+            if idx == start_idx {
+                return true;
+            }
+        }
+    }
+
+    #[inline(always)]
+    fn bucket_for_key(&self, k: &K) -> SearchResult {
+        let hash = k.hash_keyed(self.k0, self.k1) as uint;
+        self.bucket_for_key_with_hash(hash, k)
+    }
+
+    #[inline(always)]
+    fn bucket_for_key_equiv<Q:Hash + Equiv<K>>(&self, k: &Q)
+                                               -> SearchResult {
+        let hash = k.hash_keyed(self.k0, self.k1) as uint;
+        self.bucket_for_key_with_hash_equiv(hash, k)
+    }
+
+    #[inline(always)]
+    fn bucket_for_key_with_hash(&self,
+                                hash: uint,
+                                k: &K)
+                             -> SearchResult {
+        for self.bucket_sequence(hash) |i| {
+            match self.buckets[i] {
+                Some(ref bkt) => if bkt.hash == hash && *k == bkt.key {
+                    return FoundEntry(i);
+                },
+                None => return FoundHole(i)
+            }
+        }
+        TableFull
+    }
+
+    #[inline(always)]
+    fn bucket_for_key_with_hash_equiv<Q:Equiv<K>>(&self,
+                                                  hash: uint,
+                                                  k: &Q)
+                                               -> SearchResult {
+        for self.bucket_sequence(hash) |i| {
+            match self.buckets[i] {
+                Some(ref bkt) => {
+                    if bkt.hash == hash && k.equiv(&bkt.key) {
+                        return FoundEntry(i);
+                    }
+                },
+                None => return FoundHole(i)
+            }
+        }
+        TableFull
+    }
+
+    /// Expand the capacity of the array to the next power of two
+    /// and re-insert each of the existing buckets.
+    #[inline(always)]
+    fn expand(&mut self) {
+        let new_capacity = self.buckets.len() * 2;
+        self.resize(new_capacity);
+    }
+
+    /// Expands the capacity of the array and re-insert each of the
+    /// existing buckets.
+    fn resize(&mut self, new_capacity: uint) {
+        self.resize_at = resize_at(new_capacity);
+
+        let old_buckets = replace(&mut self.buckets,
+                                  vec::from_fn(new_capacity, |_| None));
+
+        self.size = 0;
+        do vec::consume(old_buckets) |_, bucket| {
+            self.insert_opt_bucket(bucket);
+        }
+    }
+
+    fn insert_opt_bucket(&mut self, bucket: Option<Bucket<K, V>>) {
+        match bucket {
+            Some(Bucket{hash: hash, key: key, value: value}) => {
+                self.insert_internal(hash, key, value);
+            }
+            None => {}
+        }
+    }
+
+    #[inline(always)]
+    fn value_for_bucket<'a>(&'a self, idx: uint) -> &'a V {
+        match self.buckets[idx] {
+            Some(ref bkt) => &bkt.value,
+            None => fail!("HashMap::find: internal logic error"),
+        }
+    }
+
+    #[inline(always)]
+    fn mut_value_for_bucket<'a>(&'a mut self, idx: uint) -> &'a mut V {
+        match self.buckets[idx] {
+            Some(ref mut bkt) => &mut bkt.value,
+            None => unreachable()
+        }
+    }
+
+    /// Inserts the key value pair into the buckets.
+    /// Assumes that there will be a bucket.
+    /// True if there was no previous entry with that key
+    fn insert_internal(&mut self, hash: uint, k: K, v: V) -> Option<V> {
+        match self.bucket_for_key_with_hash(hash, &k) {
+            TableFull => { fail!("Internal logic error"); }
+            FoundHole(idx) => {
+                debug!("insert fresh (%?->%?) at idx %?, hash %?",
+                       k, v, idx, hash);
+                self.buckets[idx] = Some(Bucket{hash: hash, key: k,
+                                                value: v});
+                self.size += 1;
+                None
+            }
+            FoundEntry(idx) => {
+                debug!("insert overwrite (%?->%?) at idx %?, hash %?",
+                       k, v, idx, hash);
+                match self.buckets[idx] {
+                    None => { fail!("insert_internal: Internal logic error") }
+                    Some(ref mut b) => {
+                        b.hash = hash;
+                        b.key = k;
+                        Some(replace(&mut b.value, v))
+                    }
+                }
+            }
+        }
+    }
+
+    fn pop_internal(&mut self, hash: uint, k: &K) -> Option<V> {
+        // Removing from an open-addressed hashtable
+        // is, well, painful.  The problem is that
+        // the entry may lie on the probe path for other
+        // entries, so removing it would make you think that
+        // those probe paths are empty.
+        //
+        // To address this we basically have to keep walking,
+        // re-inserting entries we find until we reach an empty
+        // bucket.  We know we will eventually reach one because
+        // we insert one ourselves at the beginning (the removed
+        // entry).
+        //
+        // I found this explanation elucidating:
+        // http://www.maths.lse.ac.uk/Courses/MA407/del-hash.pdf
+        let mut idx = match self.bucket_for_key_with_hash(hash, k) {
+            TableFull | FoundHole(_) => return None,
+            FoundEntry(idx) => idx
+        };
+
+        let len_buckets = self.buckets.len();
+        let bucket = replace(&mut self.buckets[idx], None);
+
+        let value = match bucket {
+            None => None,
+            Some(Bucket{value, _}) => {
+                Some(value)
+            },
+        };
+
+        /* re-inserting buckets may cause changes in size, so remember
+        what our new size is ahead of time before we start insertions */
+        let size = self.size - 1;
+        idx = self.next_bucket(idx, len_buckets);
+        while self.buckets[idx].is_some() {
+            let bucket = replace(&mut self.buckets[idx], None);
+            self.insert_opt_bucket(bucket);
+            idx = self.next_bucket(idx, len_buckets);
+        }
+        self.size = size;
+
+        value
+    }
+
+    fn search(&self, hash: uint,
+              op: &fn(x: &Option<Bucket<K, V>>) -> bool) {
+        let _ = self.bucket_sequence(hash, |i| op(&self.buckets[i]));
+    }
+}
+
+impl<K:Hash + Eq,V> Container for HashMap<K, V> {
+    /// Return the number of elements in the map
+    fn len(&const self) -> uint { self.size }
+
+    /// Return true if the map contains no elements
+    fn is_empty(&const self) -> bool { self.len() == 0 }
+}
+
+impl<K:Hash + Eq,V> Mutable for HashMap<K, V> {
+    /// Clear the map, removing all key-value pairs.
+    fn clear(&mut self) {
+        for uint::range(0, self.buckets.len()) |idx| {
+            self.buckets[idx] = None;
+        }
+        self.size = 0;
+    }
+}
+
+impl<K:Hash + Eq,V> Map<K, V> for HashMap<K, V> {
+    /// Return true if the map contains a value for the specified key
+    fn contains_key(&self, k: &K) -> bool {
+        match self.bucket_for_key(k) {
+            FoundEntry(_) => {true}
+            TableFull | FoundHole(_) => {false}
+        }
+    }
+
+    /// Visit all key-value pairs
+    fn each<'a>(&'a self, blk: &fn(&K, &'a V) -> bool) -> bool {
+        for self.buckets.each |bucket| {
+            for bucket.each |pair| {
+                if !blk(&pair.key, &pair.value) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /// Visit all keys
+    fn each_key(&self, blk: &fn(k: &K) -> bool) -> bool {
+        self.each(|k, _| blk(k))
+    }
+
+    /// Visit all values
+    fn each_value<'a>(&'a self, blk: &fn(v: &'a V) -> bool) -> bool {
+        self.each(|_, v| blk(v))
+    }
+
+    /// Iterate over the map and mutate the contained values
+    fn mutate_values(&mut self, blk: &fn(&K, &mut V) -> bool) -> bool {
+        for uint::range(0, self.buckets.len()) |i| {
+            match self.buckets[i] {
+              Some(Bucket{key: ref key, value: ref mut value, _}) => {
+                if !blk(key, value) { return false; }
+              }
+              None => ()
+            }
+        }
+        return true;
+    }
+
+    /// Return a reference to the value corresponding to the key
+    fn find<'a>(&'a self, k: &K) -> Option<&'a V> {
+        match self.bucket_for_key(k) {
+            FoundEntry(idx) => Some(self.value_for_bucket(idx)),
+            TableFull | FoundHole(_) => None,
+        }
+    }
+
+    /// Return a mutable reference to the value corresponding to the key
+    fn find_mut<'a>(&'a mut self, k: &K) -> Option<&'a mut V> {
+        let idx = match self.bucket_for_key(k) {
+            FoundEntry(idx) => idx,
+            TableFull | FoundHole(_) => return None
+        };
+        Some(self.mut_value_for_bucket(idx))
+    }
+
+    /// Insert a key-value pair into the map. An existing value for a
+    /// key is replaced by the new value. Return true if the key did
+    /// not already exist in the map.
+    fn insert(&mut self, k: K, v: V) -> bool {
+        self.swap(k, v).is_none()
+    }
+
+    /// Remove a key-value pair from the map. Return true if the key
+    /// was present in the map, otherwise false.
+    fn remove(&mut self, k: &K) -> bool {
+        self.pop(k).is_some()
+    }
+
+    /// Insert a key-value pair from the map. If the key already had a value
+    /// present in the map, that value is returned. Otherwise None is returned.
+    fn swap(&mut self, k: K, v: V) -> Option<V> {
+        // this could be faster.
+
+        if self.size >= self.resize_at {
+            // n.b.: We could also do this after searching, so
+            // that we do not resize if this call to insert is
+            // simply going to update a key in place.  My sense
+            // though is that it's worse to have to search through
+            // buckets to find the right spot twice than to just
+            // resize in this corner case.
+            self.expand();
+        }
+
+        let hash = k.hash_keyed(self.k0, self.k1) as uint;
+        self.insert_internal(hash, k, v)
+    }
+
+    /// Removes a key from the map, returning the value at the key if the key
+    /// was previously in the map.
+    fn pop(&mut self, k: &K) -> Option<V> {
+        let hash = k.hash_keyed(self.k0, self.k1) as uint;
+        self.pop_internal(hash, k)
+    }
+}
+
+pub impl<K: Hash + Eq, V> HashMap<K, V> {
+    /// Create an empty HashMap
+    fn new() -> HashMap<K, V> {
+        HashMap::with_capacity(INITIAL_CAPACITY)
+    }
+
+    /// Create an empty HashMap with space for at least `n` elements in
+    /// the hash table.
+    fn with_capacity(capacity: uint) -> HashMap<K, V> {
+        linear_map_with_capacity(capacity)
+    }
+
+    /// Reserve space for at least `n` elements in the hash table.
+    fn reserve_at_least(&mut self, n: uint) {
+        if n > self.buckets.len() {
+            let buckets = n * 4 / 3 + 1;
+            self.resize(uint::next_power_of_two(buckets));
+        }
+    }
+
+    /// Return the value corresponding to the key in the map, or insert
+    /// and return the value if it doesn't exist.
+    fn find_or_insert<'a>(&'a mut self, k: K, v: V) -> &'a V {
+        if self.size >= self.resize_at {
+            // n.b.: We could also do this after searching, so
+            // that we do not resize if this call to insert is
+            // simply going to update a key in place.  My sense
+            // though is that it's worse to have to search through
+            // buckets to find the right spot twice than to just
+            // resize in this corner case.
+            self.expand();
+        }
+
+        let hash = k.hash_keyed(self.k0, self.k1) as uint;
+        let idx = match self.bucket_for_key_with_hash(hash, &k) {
+            TableFull => fail!("Internal logic error"),
+            FoundEntry(idx) => idx,
+            FoundHole(idx) => {
+                self.buckets[idx] = Some(Bucket{hash: hash, key: k,
+                                     value: v});
+                self.size += 1;
+                idx
+            },
+        };
+
+        self.value_for_bucket(idx)
+    }
+
+    /// Return the value corresponding to the key in the map, or create,
+    /// insert, and return a new value if it doesn't exist.
+    fn find_or_insert_with<'a>(&'a mut self, k: K, f: &fn(&K) -> V) -> &'a V {
+        if self.size >= self.resize_at {
+            // n.b.: We could also do this after searching, so
+            // that we do not resize if this call to insert is
+            // simply going to update a key in place.  My sense
+            // though is that it's worse to have to search through
+            // buckets to find the right spot twice than to just
+            // resize in this corner case.
+            self.expand();
+        }
+
+        let hash = k.hash_keyed(self.k0, self.k1) as uint;
+        let idx = match self.bucket_for_key_with_hash(hash, &k) {
+            TableFull => fail!("Internal logic error"),
+            FoundEntry(idx) => idx,
+            FoundHole(idx) => {
+                let v = f(&k);
+                self.buckets[idx] = Some(Bucket{hash: hash, key: k,
+                                     value: v});
+                self.size += 1;
+                idx
+            },
+        };
+
+        self.value_for_bucket(idx)
+    }
+
+    fn consume(&mut self, f: &fn(K, V)) {
+        let buckets = replace(&mut self.buckets, ~[]);
+        self.size = 0;
+
+        do vec::consume(buckets) |_, bucket| {
+            match bucket {
+                None => {},
+                Some(Bucket{key, value, _}) => {
+                    f(key, value)
+                }
+            }
+        }
+    }
+
+    fn get<'a>(&'a self, k: &K) -> &'a V {
+        match self.find(k) {
+            Some(v) => v,
+            None => fail!("No entry found for key: %?", k),
+        }
+    }
+
+    /// Return true if the map contains a value for the specified key,
+    /// using equivalence
+    fn contains_key_equiv<Q:Hash + Equiv<K>>(&self, key: &Q) -> bool {
+        match self.bucket_for_key_equiv(key) {
+            FoundEntry(_) => {true}
+            TableFull | FoundHole(_) => {false}
+        }
+    }
+
+    /// Return the value corresponding to the key in the map, using
+    /// equivalence
+    fn find_equiv<'a, Q:Hash + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
+        match self.bucket_for_key_equiv(k) {
+            FoundEntry(idx) => Some(self.value_for_bucket(idx)),
+            TableFull | FoundHole(_) => None,
+        }
+    }
+}
+
+pub impl<K: Hash + Eq, V: Copy> HashMap<K, V> {
+    /// Like `find`, but returns a copy of the value.
+    fn find_copy(&self, k: &K) -> Option<V> {
+        self.find(k).map_consume(|v| copy *v)
+    }
+
+    /// Like `get`, but returns a copy of the value.
+    fn get_copy(&self, k: &K) -> V {
+        copy *self.get(k)
+    }
+}
+
+impl<K:Hash + Eq,V:Eq> Eq for HashMap<K, V> {
+    fn eq(&self, other: &HashMap<K, V>) -> bool {
+        if self.len() != other.len() { return false; }
+
+        for self.each |key, value| {
+            match other.find(key) {
+                None => return false,
+                Some(v) => if value != v { return false },
+            }
+        }
+
+        true
+    }
+
+    fn ne(&self, other: &HashMap<K, V>) -> bool { !self.eq(other) }
+}
+
+pub struct HashSet<T> {
+    priv map: HashMap<T, ()>
+}
+
+impl<T:Hash + Eq> BaseIter<T> for HashSet<T> {
+    /// Visit all values in order
+    fn each(&self, f: &fn(&T) -> bool) -> bool { self.map.each_key(f) }
+    fn size_hint(&self) -> Option<uint> { Some(self.len()) }
+}
+
+impl<T:Hash + Eq> Eq for HashSet<T> {
+    fn eq(&self, other: &HashSet<T>) -> bool { self.map == other.map }
+    fn ne(&self, other: &HashSet<T>) -> bool { self.map != other.map }
+}
+
+impl<T:Hash + Eq> Container for HashSet<T> {
+    /// Return the number of elements in the set
+    fn len(&const self) -> uint { self.map.len() }
+
+    /// Return true if the set contains no elements
+    fn is_empty(&const self) -> bool { self.map.is_empty() }
+}
+
+impl<T:Hash + Eq> Mutable for HashSet<T> {
+    /// Clear the set, removing all values.
+    fn clear(&mut self) { self.map.clear() }
+}
+
+impl<T:Hash + Eq> Set<T> for HashSet<T> {
+    /// Return true if the set contains a value
+    fn contains(&self, value: &T) -> bool { self.map.contains_key(value) }
+
+    /// Add a value to the set. Return true if the value was not already
+    /// present in the set.
+    fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
+
+    /// Remove a value from the set. Return true if the value was
+    /// present in the set.
+    fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
+
+    /// Return true if the set has no elements in common with `other`.
+    /// This is equivalent to checking for an empty intersection.
+    fn is_disjoint(&self, other: &HashSet<T>) -> bool {
+        old_iter::all(self, |v| !other.contains(v))
+    }
+
+    /// Return true if the set is a subset of another
+    fn is_subset(&self, other: &HashSet<T>) -> bool {
+        old_iter::all(self, |v| other.contains(v))
+    }
+
+    /// Return true if the set is a superset of another
+    fn is_superset(&self, other: &HashSet<T>) -> bool {
+        other.is_subset(self)
+    }
+
+    /// Visit the values representing the difference
+    fn difference(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
+        self.each(|v| other.contains(v) || f(v))
+    }
+
+    /// Visit the values representing the symmetric difference
+    fn symmetric_difference(&self,
+                            other: &HashSet<T>,
+                            f: &fn(&T) -> bool) -> bool {
+        self.difference(other, f) && other.difference(self, f)
+    }
+
+    /// Visit the values representing the intersection
+    fn intersection(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
+        self.each(|v| !other.contains(v) || f(v))
+    }
+
+    /// Visit the values representing the union
+    fn union(&self, other: &HashSet<T>, f: &fn(&T) -> bool) -> bool {
+        self.each(f) && other.each(|v| self.contains(v) || f(v))
+    }
+}
+
+pub impl <T:Hash + Eq> HashSet<T> {
+    /// Create an empty HashSet
+    fn new() -> HashSet<T> {
+        HashSet::with_capacity(INITIAL_CAPACITY)
+    }
+
+    /// Create an empty HashSet with space for at least `n` elements in
+    /// the hash table.
+    fn with_capacity(capacity: uint) -> HashSet<T> {
+        HashSet { map: HashMap::with_capacity(capacity) }
+    }
+
+    /// Reserve space for at least `n` elements in the hash table.
+    fn reserve_at_least(&mut self, n: uint) {
+        self.map.reserve_at_least(n)
+    }
+
+    /// Consumes all of the elements in the set, emptying it out
+    fn consume(&mut self, f: &fn(T)) {
+        self.map.consume(|k, _| f(k))
+    }
+
+    fn contains_equiv<Q:Hash + Equiv<T>>(&self, value: &Q) -> bool {
+      self.map.contains_key_equiv(value)
+    }
+}
+
+#[cfg(test)]
+mod test_map {
+    use container::{Container, Map, Set};
+    use option::{None, Some};
+    use super::*;
+    use uint;
+
+    #[test]
+    fn test_insert() {
+        let mut m = HashMap::new();
+        assert!(m.insert(1, 2));
+        assert!(m.insert(2, 4));
+        assert_eq!(*m.get(&1), 2);
+        assert_eq!(*m.get(&2), 4);
+    }
+
+    #[test]
+    fn test_find_mut() {
+        let mut m = HashMap::new();
+        assert!(m.insert(1, 12));
+        assert!(m.insert(2, 8));
+        assert!(m.insert(5, 14));
+        let new = 100;
+        match m.find_mut(&5) {
+            None => fail!(), Some(x) => *x = new
+        }
+        assert_eq!(m.find(&5), Some(&new));
+    }
+
+    #[test]
+    fn test_insert_overwrite() {
+        let mut m = HashMap::new();
+        assert!(m.insert(1, 2));
+        assert_eq!(*m.get(&1), 2);
+        assert!(!m.insert(1, 3));
+        assert_eq!(*m.get(&1), 3);
+    }
+
+    #[test]
+    fn test_insert_conflicts() {
+        let mut m = linear_map_with_capacity(4);
+        assert!(m.insert(1, 2));
+        assert!(m.insert(5, 3));
+        assert!(m.insert(9, 4));
+        assert_eq!(*m.get(&9), 4);
+        assert_eq!(*m.get(&5), 3);
+        assert_eq!(*m.get(&1), 2);
+    }
+
+    #[test]
+    fn test_conflict_remove() {
+        let mut m = linear_map_with_capacity(4);
+        assert!(m.insert(1, 2));
+        assert!(m.insert(5, 3));
+        assert!(m.insert(9, 4));
+        assert!(m.remove(&1));
+        assert_eq!(*m.get(&9), 4);
+        assert_eq!(*m.get(&5), 3);
+    }
+
+    #[test]
+    fn test_is_empty() {
+        let mut m = linear_map_with_capacity(4);
+        assert!(m.insert(1, 2));
+        assert!(!m.is_empty());
+        assert!(m.remove(&1));
+        assert!(m.is_empty());
+    }
+
+    #[test]
+    fn test_pop() {
+        let mut m = HashMap::new();
+        m.insert(1, 2);
+        assert_eq!(m.pop(&1), Some(2));
+        assert_eq!(m.pop(&1), None);
+    }
+
+    #[test]
+    fn test_swap() {
+        let mut m = HashMap::new();
+        assert_eq!(m.swap(1, 2), None);
+        assert_eq!(m.swap(1, 3), Some(2));
+        assert_eq!(m.swap(1, 4), Some(3));
+    }
+
+    #[test]
+    fn test_find_or_insert() {
+        let mut m = HashMap::new::<int, int>();
+        assert_eq!(m.find_or_insert(1, 2), &2);
+        assert_eq!(m.find_or_insert(1, 3), &2);
+    }
+
+    #[test]
+    fn test_find_or_insert_with() {
+        let mut m = HashMap::new::<int, int>();
+        assert_eq!(m.find_or_insert_with(1, |_| 2), &2);
+        assert_eq!(m.find_or_insert_with(1, |_| 3), &2);
+    }
+
+    #[test]
+    fn test_consume() {
+        let mut m = HashMap::new();
+        assert!(m.insert(1, 2));
+        assert!(m.insert(2, 3));
+        let mut m2 = HashMap::new();
+        do m.consume |k, v| {
+            m2.insert(k, v);
+        }
+        assert_eq!(m.len(), 0);
+        assert_eq!(m2.len(), 2);
+        assert_eq!(m2.get(&1), &2);
+        assert_eq!(m2.get(&2), &3);
+    }
+
+    #[test]
+    fn test_iterate() {
+        let mut m = linear_map_with_capacity(4);
+        for uint::range(0, 32) |i| {
+            assert!(m.insert(i, i*2));
+        }
+        let mut observed = 0;
+        for m.each |k, v| {
+            assert_eq!(*v, *k * 2);
+            observed |= (1 << *k);
+        }
+        assert_eq!(observed, 0xFFFF_FFFF);
+    }
+
+    #[test]
+    fn test_find() {
+        let mut m = HashMap::new();
+        assert!(m.find(&1).is_none());
+        m.insert(1, 2);
+        match m.find(&1) {
+            None => fail!(),
+            Some(v) => assert!(*v == 2)
+        }
+    }
+
+    #[test]
+    fn test_eq() {
+        let mut m1 = HashMap::new();
+        m1.insert(1, 2);
+        m1.insert(2, 3);
+        m1.insert(3, 4);
+
+        let mut m2 = HashMap::new();
+        m2.insert(1, 2);
+        m2.insert(2, 3);
+
+        assert!(m1 != m2);
+
+        m2.insert(3, 4);
+
+        assert_eq!(m1, m2);
+    }
+
+    #[test]
+    fn test_expand() {
+        let mut m = HashMap::new();
+
+        assert_eq!(m.len(), 0);
+        assert!(m.is_empty());
+
+        let mut i = 0u;
+        let old_resize_at = m.resize_at;
+        while old_resize_at == m.resize_at {
+            m.insert(i, i);
+            i += 1;
+        }
+
+        assert_eq!(m.len(), i);
+        assert!(!m.is_empty());
+    }
+}
+
+#[cfg(test)]
+mod test_set {
+    use super::*;
+    use container::{Container, Map, Set};
+    use vec;
+
+    #[test]
+    fn test_disjoint() {
+        let mut xs = HashSet::new();
+        let mut ys = HashSet::new();
+        assert!(xs.is_disjoint(&ys));
+        assert!(ys.is_disjoint(&xs));
+        assert!(xs.insert(5));
+        assert!(ys.insert(11));
+        assert!(xs.is_disjoint(&ys));
+        assert!(ys.is_disjoint(&xs));
+        assert!(xs.insert(7));
+        assert!(xs.insert(19));
+        assert!(xs.insert(4));
+        assert!(ys.insert(2));
+        assert!(ys.insert(-11));
+        assert!(xs.is_disjoint(&ys));
+        assert!(ys.is_disjoint(&xs));
+        assert!(ys.insert(7));
+        assert!(!xs.is_disjoint(&ys));
+        assert!(!ys.is_disjoint(&xs));
+    }
+
+    #[test]
+    fn test_subset_and_superset() {
+        let mut a = HashSet::new();
+        assert!(a.insert(0));
+        assert!(a.insert(5));
+        assert!(a.insert(11));
+        assert!(a.insert(7));
+
+        let mut b = HashSet::new();
+        assert!(b.insert(0));
+        assert!(b.insert(7));
+        assert!(b.insert(19));
+        assert!(b.insert(250));
+        assert!(b.insert(11));
+        assert!(b.insert(200));
+
+        assert!(!a.is_subset(&b));
+        assert!(!a.is_superset(&b));
+        assert!(!b.is_subset(&a));
+        assert!(!b.is_superset(&a));
+
+        assert!(b.insert(5));
+
+        assert!(a.is_subset(&b));
+        assert!(!a.is_superset(&b));
+        assert!(!b.is_subset(&a));
+        assert!(b.is_superset(&a));
+    }
+
+    #[test]
+    fn test_intersection() {
+        let mut a = HashSet::new();
+        let mut b = HashSet::new();
+
+        assert!(a.insert(11));
+        assert!(a.insert(1));
+        assert!(a.insert(3));
+        assert!(a.insert(77));
+        assert!(a.insert(103));
+        assert!(a.insert(5));
+        assert!(a.insert(-5));
+
+        assert!(b.insert(2));
+        assert!(b.insert(11));
+        assert!(b.insert(77));
+        assert!(b.insert(-9));
+        assert!(b.insert(-42));
+        assert!(b.insert(5));
+        assert!(b.insert(3));
+
+        let mut i = 0;
+        let expected = [3, 5, 11, 77];
+        for a.intersection(&b) |x| {
+            assert!(vec::contains(expected, x));
+            i += 1
+        }
+        assert_eq!(i, expected.len());
+    }
+
+    #[test]
+    fn test_difference() {
+        let mut a = HashSet::new();
+        let mut b = HashSet::new();
+
+        assert!(a.insert(1));
+        assert!(a.insert(3));
+        assert!(a.insert(5));
+        assert!(a.insert(9));
+        assert!(a.insert(11));
+
+        assert!(b.insert(3));
+        assert!(b.insert(9));
+
+        let mut i = 0;
+        let expected = [1, 5, 11];
+        for a.difference(&b) |x| {
+            assert!(vec::contains(expected, x));
+            i += 1
+        }
+        assert_eq!(i, expected.len());
+    }
+
+    #[test]
+    fn test_symmetric_difference() {
+        let mut a = HashSet::new();
+        let mut b = HashSet::new();
+
+        assert!(a.insert(1));
+        assert!(a.insert(3));
+        assert!(a.insert(5));
+        assert!(a.insert(9));
+        assert!(a.insert(11));
+
+        assert!(b.insert(-2));
+        assert!(b.insert(3));
+        assert!(b.insert(9));
+        assert!(b.insert(14));
+        assert!(b.insert(22));
+
+        let mut i = 0;
+        let expected = [-2, 1, 5, 11, 14, 22];
+        for a.symmetric_difference(&b) |x| {
+            assert!(vec::contains(expected, x));
+            i += 1
+        }
+        assert_eq!(i, expected.len());
+    }
+
+    #[test]
+    fn test_union() {
+        let mut a = HashSet::new();
+        let mut b = HashSet::new();
+
+        assert!(a.insert(1));
+        assert!(a.insert(3));
+        assert!(a.insert(5));
+        assert!(a.insert(9));
+        assert!(a.insert(11));
+        assert!(a.insert(16));
+        assert!(a.insert(19));
+        assert!(a.insert(24));
+
+        assert!(b.insert(-2));
+        assert!(b.insert(1));
+        assert!(b.insert(5));
+        assert!(b.insert(9));
+        assert!(b.insert(13));
+        assert!(b.insert(19));
+
+        let mut i = 0;
+        let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
+        for a.union(&b) |x| {
+            assert!(vec::contains(expected, x));
+            i += 1
+        }
+        assert_eq!(i, expected.len());
+    }
+}
diff --git a/src/libstd/io.rs b/src/libstd/io.rs
new file mode 100644
index 00000000000..aa312742e3e
--- /dev/null
+++ b/src/libstd/io.rs
@@ -0,0 +1,2105 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+The `io` module contains basic input and output routines.
+
+A quick summary:
+
+## `Reader` and `Writer` traits
+
+These traits define the minimal set of methods that anything that can do
+input and output should implement.
+
+## `ReaderUtil` and `WriterUtil` traits
+
+Richer methods that allow you to do more. `Reader` only lets you read a certain
+number of bytes into a buffer, while `ReaderUtil` allows you to read a whole
+line, for example.
+
+Generally, these richer methods are probably the ones you want to actually
+use in day-to-day Rust.
+
+Furthermore, because there is an implementation of `ReaderUtil` for
+`<T: Reader>`, when your input or output code implements `Reader`, you get
+all of these methods for free.
+
+## `print` and `println`
+
+These very useful functions are defined here. You generally don't need to
+import them, though, as the prelude already does.
+
+## `stdin`, `stdout`, and `stderr`
+
+These functions return references to the classic three file descriptors. They
+implement `Reader` and `Writer`, where appropriate.
+
+*/
+
+use result::Result;
+
+use container::Container;
+use int;
+use libc;
+use libc::{c_int, c_long, c_void, size_t, ssize_t};
+use libc::consts::os::posix88::*;
+use os;
+use cast;
+use path::Path;
+use ops::Drop;
+use old_iter::{BaseIter, CopyableIter};
+use ptr;
+use result;
+use str;
+use str::StrSlice;
+use to_str::ToStr;
+use uint;
+use vec;
+use vec::{OwnedVector, OwnedCopyableVector};
+
+#[allow(non_camel_case_types)] // not sure what to do about this
+pub type fd_t = c_int;
+
+pub mod rustrt {
+    use libc;
+
+    #[abi = "cdecl"]
+    #[link_name = "rustrt"]
+    pub extern {
+        unsafe fn rust_get_stdin() -> *libc::FILE;
+        unsafe fn rust_get_stdout() -> *libc::FILE;
+        unsafe fn rust_get_stderr() -> *libc::FILE;
+    }
+}
+
+// Reading
+
+// FIXME (#2004): This is all buffered. We might need an unbuffered variant
+// as well
+/**
+* The SeekStyle enum describes the relationship between the position
+* we'd like to seek to from our current position. It's used as an argument
+* to the `seek` method defined on the `Reader` trait.
+*
+* There are three seek styles:
+*
+* 1. `SeekSet` means that the new position should become our position.
+* 2. `SeekCur` means that we should seek from the current position.
+* 3. `SeekEnd` means that we should seek from the end.
+*
+* # Examples
+*
+* None right now.
+*/
+pub enum SeekStyle { SeekSet, SeekEnd, SeekCur, }
+
+
+/**
+* The core Reader trait. All readers must implement this trait.
+*
+* # Examples
+*
+* None right now.
+*/
+pub trait Reader {
+    // FIXME (#2004): Seekable really should be orthogonal.
+
+    // FIXME (#2982): This should probably return an error.
+    /**
+    * Reads bytes and puts them into `bytes`, advancing the cursor. Returns the
+    * number of bytes read.
+    *
+    * The number of bytes to be read is `len` or the end of the file,
+    * whichever comes first.
+    *
+    * The buffer must be at least `len` bytes long.
+    *
+    * `read` is conceptually similar to C's `fread` function.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read(&self, bytes: &mut [u8], len: uint) -> uint;
+
+    /**
+    * Reads a single byte, advancing the cursor.
+    *
+    * In the case of an EOF or an error, returns a negative value.
+    *
+    * `read_byte` is conceptually similar to C's `getc` function.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_byte(&self) -> int;
+
+    /**
+    * Returns a boolean value: are we currently at EOF?
+    *
+    * `eof` is conceptually similar to C's `feof` function.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn eof(&self) -> bool;
+
+    /**
+    * Seek to a given `position` in the stream.
+    *
+    * Takes an optional SeekStyle, which affects how we seek from the
+    * position. See `SeekStyle` docs for more details.
+    *
+    * `seek` is conceptually similar to C's `fseek` function.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn seek(&self, position: int, style: SeekStyle);
+
+    /**
+    * Returns the current position within the stream.
+    *
+    * `tell` is conceptually similar to C's `ftell` function.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn tell(&self) -> uint;
+}
+
+impl Reader for @Reader {
+    fn read(&self, bytes: &mut [u8], len: uint) -> uint {
+        self.read(bytes, len)
+    }
+    fn read_byte(&self) -> int {
+        self.read_byte()
+    }
+    fn eof(&self) -> bool {
+        self.eof()
+    }
+    fn seek(&self, position: int, style: SeekStyle) {
+        self.seek(position, style)
+    }
+    fn tell(&self) -> uint {
+        self.tell()
+    }
+}
+
+/**
+* The `ReaderUtil` trait is a home for many of the utility functions
+* a particular Reader should implement.
+*
+* The default `Reader` trait is focused entirely on bytes. `ReaderUtil` is based
+* on higher-level concepts like 'chars' and 'lines.'
+*
+* # Examples:
+*
+* None right now.
+*/
+pub trait ReaderUtil {
+
+    /**
+    * Reads `len` number of bytes, and gives you a new vector back.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_bytes(&self, len: uint) -> ~[u8];
+
+    /**
+    * Reads up until a specific byte is seen or EOF.
+    *
+    * The `include` parameter specifies if the character should be included
+    * in the returned string.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_until(&self, c: u8, include: bool) -> ~str;
+
+    /**
+    * Reads up until the first '\n' or EOF.
+    *
+    * The '\n' is not included in the result.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_line(&self) -> ~str;
+
+    /**
+    * Reads `n` chars.
+    *
+    * Assumes that those chars are UTF-8 encoded.
+    *
+    * The '\n' is not included in the result.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_chars(&self, n: uint) -> ~[char];
+
+    /**
+    * Reads a single UTF-8 encoded char.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_char(&self) -> char;
+
+    /**
+    * Reads up until the first null byte or EOF.
+    *
+    * The null byte is not returned.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_c_str(&self) -> ~str;
+
+    /**
+    * Reads all remaining data in the stream.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_whole_stream(&self) -> ~[u8];
+
+    /**
+    * Iterate over every byte until EOF or the iterator breaks.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn each_byte(&self, it: &fn(int) -> bool) -> bool;
+
+    /**
+    * Iterate over every char until EOF or the iterator breaks.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn each_char(&self, it: &fn(char) -> bool) -> bool;
+
+    /**
+    * Iterate over every line until EOF or the iterator breaks.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn each_line(&self, it: &fn(&str) -> bool) -> bool;
+
+    /**
+    * Reads all of the lines in the stream.
+    *
+    * Returns a vector of those lines.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_lines(&self) -> ~[~str];
+
+    /**
+    * Reads `n` little-endian unsigned integer bytes.
+    *
+    * `n` must be between 1 and 8, inclusive.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_le_uint_n(&self, nbytes: uint) -> u64;
+
+    /**
+    * Reads `n` little-endian signed integer bytes.
+    *
+    * `n` must be between 1 and 8, inclusive.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_le_int_n(&self, nbytes: uint) -> i64;
+
+    /**
+    * Reads `n` big-endian unsigned integer bytes.
+    *
+    * `n` must be between 1 and 8, inclusive.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_be_uint_n(&self, nbytes: uint) -> u64;
+
+    /**
+    * Reads `n` big-endian signed integer bytes.
+    *
+    * `n` must be between 1 and 8, inclusive.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_be_int_n(&self, nbytes: uint) -> i64;
+
+    /**
+    * Reads a little-endian unsigned integer.
+    *
+    * The number of bytes returned is system-dependant.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_le_uint(&self) -> uint;
+
+    /**
+    * Reads a little-endian integer.
+    *
+    * The number of bytes returned is system-dependant.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_le_int(&self) -> int;
+
+    /**
+    * Reads a big-endian unsigned integer.
+    *
+    * The number of bytes returned is system-dependant.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_be_uint(&self) -> uint;
+
+    /**
+    * Reads a big-endian integer.
+    *
+    * The number of bytes returned is system-dependant.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_be_int(&self) -> int;
+
+    /**
+    * Reads a big-endian `u64`.
+    *
+    * `u64`s are 8 bytes long.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_be_u64(&self) -> u64;
+
+    /**
+    * Reads a big-endian `u32`.
+    *
+    * `u32`s are 4 bytes long.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_be_u32(&self) -> u32;
+
+    /**
+    * Reads a big-endian `u16`.
+    *
+    * `u16`s are 2 bytes long.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_be_u16(&self) -> u16;
+
+    /**
+    * Reads a big-endian `i64`.
+    *
+    * `i64`s are 8 bytes long.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_be_i64(&self) -> i64;
+
+    /**
+    * Reads a big-endian `i32`.
+    *
+    * `i32`s are 4 bytes long.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_be_i32(&self) -> i32;
+
+    /**
+    * Reads a big-endian `i16`.
+    *
+    * `i16`s are 2 bytes long.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_be_i16(&self) -> i16;
+
+    /**
+    * Reads a big-endian `f64`.
+    *
+    * `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_be_f64(&self) -> f64;
+
+    /**
+    * Reads a big-endian `f32`.
+    *
+    * `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_be_f32(&self) -> f32;
+
+    /**
+    * Reads a little-endian `u64`.
+    *
+    * `u64`s are 8 bytes long.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_le_u64(&self) -> u64;
+
+    /**
+    * Reads a little-endian `u32`.
+    *
+    * `u32`s are 4 bytes long.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_le_u32(&self) -> u32;
+
+    /**
+    * Reads a little-endian `u16`.
+    *
+    * `u16`s are 2 bytes long.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_le_u16(&self) -> u16;
+
+    /**
+    * Reads a little-endian `i64`.
+    *
+    * `i64`s are 8 bytes long.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_le_i64(&self) -> i64;
+
+    /**
+    * Reads a little-endian `i32`.
+    *
+    * `i32`s are 4 bytes long.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_le_i32(&self) -> i32;
+
+    /**
+    * Reads a little-endian `i16`.
+    *
+    * `i16`s are 2 bytes long.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_le_i16(&self) -> i16;
+
+    /**
+    * Reads a little-endian `f64`.
+    *
+    * `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_le_f64(&self) -> f64;
+
+    /**
+    * Reads a little-endian `f32`.
+    *
+    * `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_le_f32(&self) -> f32;
+
+    /**
+    * Read a u8.
+    *
+    * `u8`s are 1 byte.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_u8(&self) -> u8;
+
+    /**
+    * Read an i8.
+    *
+    * `i8`s are 1 byte.
+    *
+    * # Examples
+    *
+    * None right now.
+    */
+    fn read_i8(&self) -> i8;
+}
+
+impl<T:Reader> ReaderUtil for T {
+
+    fn read_bytes(&self,len: uint) -> ~[u8] {
+        let mut bytes = vec::with_capacity(len);
+        unsafe { vec::raw::set_len(&mut bytes, len); }
+
+        let count = self.read(bytes, len);
+
+        unsafe { vec::raw::set_len(&mut bytes, count); }
+        bytes
+    }
+
+    fn read_until(&self, c: u8, include: bool) -> ~str {
+        let mut bytes = ~[];
+        loop {
+            let ch = self.read_byte();
+            if ch == -1 || ch == c as int {
+                if include && ch == c as int {
+                    bytes.push(ch as u8);
+                }
+                break;
+            }
+            bytes.push(ch as u8);
+        }
+        str::from_bytes(bytes)
+    }
+
+    fn read_line(&self) -> ~str {
+        self.read_until('\n' as u8, false)
+    }
+
+    fn read_chars(&self, n: uint) -> ~[char] {
+        // returns the (consumed offset, n_req), appends characters to &chars
+        fn chars_from_bytes<T:Reader>(bytes: &~[u8], chars: &mut ~[char])
+            -> (uint, uint) {
+            let mut i = 0;
+            let bytes_len = bytes.len();
+            while i < bytes_len {
+                let b0 = bytes[i];
+                let w = str::utf8_char_width(b0);
+                let end = i + w;
+                i += 1;
+                assert!((w > 0));
+                if w == 1 {
+                    chars.push(b0 as char);
+                    loop;
+                }
+                // can't satisfy this char with the existing data
+                if end > bytes_len {
+                    return (i - 1, end - bytes_len);
+                }
+                let mut val = 0;
+                while i < end {
+                    let next = bytes[i] as int;
+                    i += 1;
+                    assert!((next > -1));
+                    assert_eq!(next & 192, 128);
+                    val <<= 6;
+                    val += (next & 63) as uint;
+                }
+                // See str::char_at
+                val += ((b0 << ((w + 1) as u8)) as uint)
+                    << (w - 1) * 6 - w - 1u;
+                chars.push(val as char);
+            }
+            return (i, 0);
+        }
+        let mut bytes = ~[];
+        let mut chars = ~[];
+        // might need more bytes, but reading n will never over-read
+        let mut nbread = n;
+        while nbread > 0 {
+            let data = self.read_bytes(nbread);
+            if data.is_empty() {
+                // eof - FIXME (#2004): should we do something if
+                // we're split in a unicode char?
+                break;
+            }
+            bytes.push_all(data);
+            let (offset, nbreq) = chars_from_bytes::<T>(&bytes, &mut chars);
+            let ncreq = n - chars.len();
+            // again we either know we need a certain number of bytes
+            // to complete a character, or we make sure we don't
+            // over-read by reading 1-byte per char needed
+            nbread = if ncreq > nbreq { ncreq } else { nbreq };
+            if nbread > 0 {
+                bytes = vec::slice(bytes, offset, bytes.len()).to_vec();
+            }
+        }
+        chars
+    }
+
+    fn read_char(&self) -> char {
+        let c = self.read_chars(1);
+        if c.len() == 0 {
+            return -1 as char; // FIXME will this stay valid? // #2004
+        }
+        assert_eq!(c.len(), 1);
+        return c[0];
+    }
+
+    fn read_c_str(&self) -> ~str {
+        self.read_until(0u8, false)
+    }
+
+    fn read_whole_stream(&self) -> ~[u8] {
+        let mut bytes: ~[u8] = ~[];
+        while !self.eof() { bytes.push_all(self.read_bytes(2048u)); }
+        bytes
+    }
+
+    fn each_byte(&self, it: &fn(int) -> bool) -> bool {
+        while !self.eof() {
+            if !it(self.read_byte()) { return false; }
+        }
+        return true;
+    }
+
+    fn each_char(&self, it: &fn(char) -> bool) -> bool {
+        while !self.eof() {
+            if !it(self.read_char()) { return false; }
+        }
+        return true;
+    }
+
+    fn each_line(&self, it: &fn(s: &str) -> bool) -> bool {
+        while !self.eof() {
+            // include the \n, so that we can distinguish an entirely empty
+            // line read after "...\n", and the trailing empty line in
+            // "...\n\n".
+            let mut line = self.read_until('\n' as u8, true);
+
+            // blank line at the end of the reader is ignored
+            if self.eof() && line.is_empty() { break; }
+
+            // trim the \n, so that each_line is consistent with read_line
+            let n = str::len(line);
+            if line[n-1] == '\n' as u8 {
+                unsafe { str::raw::set_len(&mut line, n-1); }
+            }
+
+            if !it(line) { return false; }
+        }
+        return true;
+    }
+
+    fn read_lines(&self) -> ~[~str] {
+        do vec::build |push| {
+            for self.each_line |line| {
+                push(str::to_owned(line));
+            }
+        }
+    }
+
+    // FIXME int reading methods need to deal with eof - issue #2004
+
+    fn read_le_uint_n(&self, nbytes: uint) -> u64 {
+        assert!(nbytes > 0 && nbytes <= 8);
+
+        let mut val = 0u64, pos = 0, i = nbytes;
+        while i > 0 {
+            val += (self.read_u8() as u64) << pos;
+            pos += 8;
+            i -= 1;
+        }
+        val
+    }
+
+    fn read_le_int_n(&self, nbytes: uint) -> i64 {
+        extend_sign(self.read_le_uint_n(nbytes), nbytes)
+    }
+
+    fn read_be_uint_n(&self, nbytes: uint) -> u64 {
+        assert!(nbytes > 0 && nbytes <= 8);
+
+        let mut val = 0u64, i = nbytes;
+        while i > 0 {
+            i -= 1;
+            val += (self.read_u8() as u64) << i * 8;
+        }
+        val
+    }
+
+    fn read_be_int_n(&self, nbytes: uint) -> i64 {
+        extend_sign(self.read_be_uint_n(nbytes), nbytes)
+    }
+
+    fn read_le_uint(&self) -> uint {
+        self.read_le_uint_n(uint::bytes) as uint
+    }
+
+    fn read_le_int(&self) -> int {
+        self.read_le_int_n(int::bytes) as int
+    }
+
+    fn read_be_uint(&self) -> uint {
+        self.read_be_uint_n(uint::bytes) as uint
+    }
+
+    fn read_be_int(&self) -> int {
+        self.read_be_int_n(int::bytes) as int
+    }
+
+    fn read_be_u64(&self) -> u64 {
+        self.read_be_uint_n(8) as u64
+    }
+
+    fn read_be_u32(&self) -> u32 {
+        self.read_be_uint_n(4) as u32
+    }
+
+    fn read_be_u16(&self) -> u16 {
+        self.read_be_uint_n(2) as u16
+    }
+
+    fn read_be_i64(&self) -> i64 {
+        self.read_be_int_n(8) as i64
+    }
+
+    fn read_be_i32(&self) -> i32 {
+        self.read_be_int_n(4) as i32
+    }
+
+    fn read_be_i16(&self) -> i16 {
+        self.read_be_int_n(2) as i16
+    }
+
+    fn read_be_f64(&self) -> f64 {
+        unsafe {
+            cast::transmute::<u64, f64>(self.read_be_u64())
+        }
+    }
+
+    fn read_be_f32(&self) -> f32 {
+        unsafe {
+            cast::transmute::<u32, f32>(self.read_be_u32())
+        }
+    }
+
+    fn read_le_u64(&self) -> u64 {
+        self.read_le_uint_n(8) as u64
+    }
+
+    fn read_le_u32(&self) -> u32 {
+        self.read_le_uint_n(4) as u32
+    }
+
+    fn read_le_u16(&self) -> u16 {
+        self.read_le_uint_n(2) as u16
+    }
+
+    fn read_le_i64(&self) -> i64 {
+        self.read_le_int_n(8) as i64
+    }
+
+    fn read_le_i32(&self) -> i32 {
+        self.read_le_int_n(4) as i32
+    }
+
+    fn read_le_i16(&self) -> i16 {
+        self.read_le_int_n(2) as i16
+    }
+
+    fn read_le_f64(&self) -> f64 {
+        unsafe {
+            cast::transmute::<u64, f64>(self.read_le_u64())
+        }
+    }
+
+    fn read_le_f32(&self) -> f32 {
+        unsafe {
+            cast::transmute::<u32, f32>(self.read_le_u32())
+        }
+    }
+
+    fn read_u8(&self) -> u8 {
+        self.read_byte() as u8
+    }
+
+    fn read_i8(&self) -> i8 {
+        self.read_byte() as i8
+    }
+}
+
+fn extend_sign(val: u64, nbytes: uint) -> i64 {
+    let shift = (8 - nbytes) * 8;
+    (val << shift) as i64 >> shift
+}
+
+// Reader implementations
+
+fn convert_whence(whence: SeekStyle) -> i32 {
+    return match whence {
+      SeekSet => 0i32,
+      SeekCur => 1i32,
+      SeekEnd => 2i32
+    };
+}
+
+impl Reader for *libc::FILE {
+    fn read(&self, bytes: &mut [u8], len: uint) -> uint {
+        unsafe {
+            do vec::as_mut_buf(bytes) |buf_p, buf_len| {
+                assert!(buf_len >= len);
+
+                let count = libc::fread(buf_p as *mut c_void, 1u as size_t,
+                                        len as size_t, *self) as uint;
+                if count < len {
+                  match libc::ferror(*self) {
+                    0 => (),
+                    _ => {
+                      error!("error reading buffer");
+                      error!("%s", os::last_os_error());
+                      fail!();
+                    }
+                  }
+                }
+
+                count
+            }
+        }
+    }
+    fn read_byte(&self) -> int {
+        unsafe {
+            libc::fgetc(*self) as int
+        }
+    }
+    fn eof(&self) -> bool {
+        unsafe {
+            return libc::feof(*self) != 0 as c_int;
+        }
+    }
+    fn seek(&self, offset: int, whence: SeekStyle) {
+        unsafe {
+            assert!(libc::fseek(*self,
+                                     offset as c_long,
+                                     convert_whence(whence)) == 0 as c_int);
+        }
+    }
+    fn tell(&self) -> uint {
+        unsafe {
+            return libc::ftell(*self) as uint;
+        }
+    }
+}
+
+struct Wrapper<T, C> {
+    base: T,
+    cleanup: C,
+}
+
+// A forwarding impl of reader that also holds on to a resource for the
+// duration of its lifetime.
+// FIXME there really should be a better way to do this // #2004
+impl<R:Reader,C> Reader for Wrapper<R, C> {
+    fn read(&self, bytes: &mut [u8], len: uint) -> uint {
+        self.base.read(bytes, len)
+    }
+    fn read_byte(&self) -> int { self.base.read_byte() }
+    fn eof(&self) -> bool { self.base.eof() }
+    fn seek(&self, off: int, whence: SeekStyle) {
+        self.base.seek(off, whence)
+    }
+    fn tell(&self) -> uint { self.base.tell() }
+}
+
+pub struct FILERes {
+    f: *libc::FILE,
+}
+
+impl Drop for FILERes {
+    fn finalize(&self) {
+        unsafe {
+            libc::fclose(self.f);
+        }
+    }
+}
+
+pub fn FILERes(f: *libc::FILE) -> FILERes {
+    FILERes {
+        f: f
+    }
+}
+
+pub fn FILE_reader(f: *libc::FILE, cleanup: bool) -> @Reader {
+    if cleanup {
+        @Wrapper { base: f, cleanup: FILERes(f) } as @Reader
+    } else {
+        @f as @Reader
+    }
+}
+
+// FIXME (#2004): this should either be an trait-less impl, a set of
+// top-level functions that take a reader, or a set of default methods on
+// reader (which can then be called reader)
+
+/**
+* Gives a `Reader` that allows you to read values from standard input.
+*
+* # Examples
+* ~~~
+* let stdin = core::io::stdin();
+* let line = stdin.read_line();
+* core::io::print(line);
+* ~~~
+*/
+pub fn stdin() -> @Reader {
+    unsafe {
+        @rustrt::rust_get_stdin() as @Reader
+    }
+}
+
+pub fn file_reader(path: &Path) -> Result<@Reader, ~str> {
+    unsafe {
+        let f = os::as_c_charp(path.to_str(), |pathbuf| {
+            os::as_c_charp("r", |modebuf|
+                libc::fopen(pathbuf, modebuf)
+            )
+        });
+        return if f as uint == 0u { result::Err(~"error opening "
+                                                + path.to_str()) }
+        else {
+            result::Ok(FILE_reader(f, true))
+        }
+    }
+}
+
+
+// Byte readers
+pub struct BytesReader<'self> {
+    bytes: &'self [u8],
+    pos: @mut uint
+}
+
+impl<'self> Reader for BytesReader<'self> {
+    fn read(&self, bytes: &mut [u8], len: uint) -> uint {
+        let count = uint::min(len, self.bytes.len() - *self.pos);
+
+        let view = vec::slice(self.bytes, *self.pos, self.bytes.len());
+        vec::bytes::copy_memory(bytes, view, count);
+
+        *self.pos += count;
+
+        count
+    }
+
+    fn read_byte(&self) -> int {
+        if *self.pos == self.bytes.len() {
+            return -1;
+        }
+
+        let b = self.bytes[*self.pos];
+        *self.pos += 1u;
+        b as int
+    }
+
+    fn eof(&self) -> bool {
+        *self.pos == self.bytes.len()
+    }
+
+    fn seek(&self, offset: int, whence: SeekStyle) {
+        let pos = *self.pos;
+        *self.pos = seek_in_buf(offset, pos, self.bytes.len(), whence);
+    }
+
+    fn tell(&self) -> uint {
+        *self.pos
+    }
+}
+
+pub fn with_bytes_reader<T>(bytes: &[u8], f: &fn(@Reader) -> T) -> T {
+    f(@BytesReader {
+        bytes: bytes,
+        pos: @mut 0
+    } as @Reader)
+}
+
+pub fn with_str_reader<T>(s: &str, f: &fn(@Reader) -> T) -> T {
+    str::byte_slice(s, |bytes| with_bytes_reader(bytes, f))
+}
+
+// Writing
+pub enum FileFlag { Append, Create, Truncate, NoFlag, }
+
+// What type of writer are we?
+#[deriving(Eq)]
+pub enum WriterType { Screen, File }
+
+// FIXME (#2004): Seekable really should be orthogonal.
+// FIXME (#2004): eventually u64
+/// The raw underlying writer trait. All writers must implement this.
+pub trait Writer {
+
+    /// Write all of the given bytes.
+    fn write(&self, v: &[u8]);
+
+    /// Move the current position within the stream. The second parameter
+    /// determines the position that the first parameter is relative to.
+    fn seek(&self, int, SeekStyle);
+
+    /// Return the current position within the stream.
+    fn tell(&self) -> uint;
+
+    /// Flush the output buffer for this stream (if there is one).
+    fn flush(&self) -> int;
+
+    /// Determine if this Writer is writing to a file or not.
+    fn get_type(&self) -> WriterType;
+}
+
+impl Writer for @Writer {
+    fn write(&self, v: &[u8]) { self.write(v) }
+    fn seek(&self, a: int, b: SeekStyle) { self.seek(a, b) }
+    fn tell(&self) -> uint { self.tell() }
+    fn flush(&self) -> int { self.flush() }
+    fn get_type(&self) -> WriterType { self.get_type() }
+}
+
+impl<W:Writer,C> Writer for Wrapper<W, C> {
+    fn write(&self, bs: &[u8]) { self.base.write(bs); }
+    fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); }
+    fn tell(&self) -> uint { self.base.tell() }
+    fn flush(&self) -> int { self.base.flush() }
+    fn get_type(&self) -> WriterType { File }
+}
+
+impl Writer for *libc::FILE {
+    fn write(&self, v: &[u8]) {
+        unsafe {
+            do vec::as_const_buf(v) |vbuf, len| {
+                let nout = libc::fwrite(vbuf as *c_void,
+                                        1,
+                                        len as size_t,
+                                        *self);
+                if nout != len as size_t {
+                    error!("error writing buffer");
+                    error!("%s", os::last_os_error());
+                    fail!();
+                }
+            }
+        }
+    }
+    fn seek(&self, offset: int, whence: SeekStyle) {
+        unsafe {
+            assert!(libc::fseek(*self,
+                                     offset as c_long,
+                                     convert_whence(whence)) == 0 as c_int);
+        }
+    }
+    fn tell(&self) -> uint {
+        unsafe {
+            libc::ftell(*self) as uint
+        }
+    }
+    fn flush(&self) -> int {
+        unsafe {
+            libc::fflush(*self) as int
+        }
+    }
+    fn get_type(&self) -> WriterType {
+        unsafe {
+            let fd = libc::fileno(*self);
+            if libc::isatty(fd) == 0 { File   }
+            else                     { Screen }
+        }
+    }
+}
+
+pub fn FILE_writer(f: *libc::FILE, cleanup: bool) -> @Writer {
+    if cleanup {
+        @Wrapper { base: f, cleanup: FILERes(f) } as @Writer
+    } else {
+        @f as @Writer
+    }
+}
+
+impl Writer for fd_t {
+    fn write(&self, v: &[u8]) {
+        unsafe {
+            let mut count = 0u;
+            do vec::as_const_buf(v) |vbuf, len| {
+                while count < len {
+                    let vb = ptr::const_offset(vbuf, count) as *c_void;
+                    let nout = libc::write(*self, vb, len as size_t);
+                    if nout < 0 as ssize_t {
+                        error!("error writing buffer");
+                        error!("%s", os::last_os_error());
+                        fail!();
+                    }
+                    count += nout as uint;
+                }
+            }
+        }
+    }
+    fn seek(&self, _offset: int, _whence: SeekStyle) {
+        error!("need 64-bit foreign calls for seek, sorry");
+        fail!();
+    }
+    fn tell(&self) -> uint {
+        error!("need 64-bit foreign calls for tell, sorry");
+        fail!();
+    }
+    fn flush(&self) -> int { 0 }
+    fn get_type(&self) -> WriterType {
+        unsafe {
+            if libc::isatty(*self) == 0 { File } else { Screen }
+        }
+    }
+}
+
+pub struct FdRes {
+    fd: fd_t,
+}
+
+impl Drop for FdRes {
+    fn finalize(&self) {
+        unsafe {
+            libc::close(self.fd);
+        }
+    }
+}
+
+pub fn FdRes(fd: fd_t) -> FdRes {
+    FdRes {
+        fd: fd
+    }
+}
+
+pub fn fd_writer(fd: fd_t, cleanup: bool) -> @Writer {
+    if cleanup {
+        @Wrapper { base: fd, cleanup: FdRes(fd) } as @Writer
+    } else {
+        @fd as @Writer
+    }
+}
+
+
+pub fn mk_file_writer(path: &Path, flags: &[FileFlag])
+                   -> Result<@Writer, ~str> {
+    #[cfg(windows)]
+    fn wb() -> c_int {
+      (O_WRONLY | libc::consts::os::extra::O_BINARY) as c_int
+    }
+
+    #[cfg(unix)]
+    fn wb() -> c_int { O_WRONLY as c_int }
+
+    let mut fflags: c_int = wb();
+    for flags.each |f| {
+        match *f {
+          Append => fflags |= O_APPEND as c_int,
+          Create => fflags |= O_CREAT as c_int,
+          Truncate => fflags |= O_TRUNC as c_int,
+          NoFlag => ()
+        }
+    }
+    let fd = unsafe {
+        do os::as_c_charp(path.to_str()) |pathbuf| {
+            libc::open(pathbuf, fflags,
+                       (S_IRUSR | S_IWUSR) as c_int)
+        }
+    };
+    if fd < (0 as c_int) {
+        result::Err(fmt!("error opening %s: %s", path.to_str(),
+                         os::last_os_error()))
+    } else {
+        result::Ok(fd_writer(fd, true))
+    }
+}
+
+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] = ~[], i = size, 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;
+}
+
+// FIXME: #3048 combine trait+impl (or just move these to
+// default methods on writer)
+/// Generic utility functions defined on writers.
+pub trait WriterUtil {
+
+    /// Write a single utf-8 encoded char.
+    fn write_char(&self, ch: char);
+
+    /// Write every char in the given str, encoded as utf-8.
+    fn write_str(&self, s: &str);
+
+    /// Write the given str, as utf-8, followed by '\n'.
+    fn write_line(&self, s: &str);
+
+    /// Write the result of passing n through `int::to_str_bytes`.
+    fn write_int(&self, n: int);
+
+    /// Write the result of passing n through `uint::to_str_bytes`.
+    fn write_uint(&self, n: uint);
+
+    /// Write a little-endian uint (number of bytes depends on system).
+    fn write_le_uint(&self, n: uint);
+
+    /// Write a little-endian int (number of bytes depends on system).
+    fn write_le_int(&self, n: int);
+
+    /// Write a big-endian uint (number of bytes depends on system).
+    fn write_be_uint(&self, n: uint);
+
+    /// Write a big-endian int (number of bytes depends on system).
+    fn write_be_int(&self, n: int);
+
+    /// Write a big-endian u64 (8 bytes).
+    fn write_be_u64(&self, n: u64);
+
+    /// Write a big-endian u32 (4 bytes).
+    fn write_be_u32(&self, n: u32);
+
+    /// Write a big-endian u16 (2 bytes).
+    fn write_be_u16(&self, n: u16);
+
+    /// Write a big-endian i64 (8 bytes).
+    fn write_be_i64(&self, n: i64);
+
+    /// Write a big-endian i32 (4 bytes).
+    fn write_be_i32(&self, n: i32);
+
+    /// Write a big-endian i16 (2 bytes).
+    fn write_be_i16(&self, n: i16);
+
+    /// Write a big-endian IEEE754 double-precision floating-point (8 bytes).
+    fn write_be_f64(&self, f: f64);
+
+    /// Write a big-endian IEEE754 single-precision floating-point (4 bytes).
+    fn write_be_f32(&self, f: f32);
+
+    /// Write a little-endian u64 (8 bytes).
+    fn write_le_u64(&self, n: u64);
+
+    /// Write a little-endian u32 (4 bytes).
+    fn write_le_u32(&self, n: u32);
+
+    /// Write a little-endian u16 (2 bytes).
+    fn write_le_u16(&self, n: u16);
+
+    /// Write a little-endian i64 (8 bytes).
+    fn write_le_i64(&self, n: i64);
+
+    /// Write a little-endian i32 (4 bytes).
+    fn write_le_i32(&self, n: i32);
+
+    /// Write a little-endian i16 (2 bytes).
+    fn write_le_i16(&self, n: i16);
+
+    /// Write a little-endian IEEE754 double-precision floating-point
+    /// (8 bytes).
+    fn write_le_f64(&self, f: f64);
+
+    /// Write a litten-endian IEEE754 single-precision floating-point
+    /// (4 bytes).
+    fn write_le_f32(&self, f: f32);
+
+    /// Write a u8 (1 byte).
+    fn write_u8(&self, n: u8);
+
+    /// Write a i8 (1 byte).
+    fn write_i8(&self, n: i8);
+}
+
+impl<T:Writer> WriterUtil for T {
+    fn write_char(&self, ch: char) {
+        if (ch as uint) < 128u {
+            self.write(&[ch as u8]);
+        } else {
+            self.write_str(str::from_char(ch));
+        }
+    }
+    fn write_str(&self, s: &str) { str::byte_slice(s, |v| self.write(v)) }
+    fn write_line(&self, s: &str) {
+        self.write_str(s);
+        self.write_str(&"\n");
+    }
+    fn write_int(&self, n: int) {
+        int::to_str_bytes(n, 10u, |bytes| self.write(bytes))
+    }
+    fn write_uint(&self, n: uint) {
+        uint::to_str_bytes(n, 10u, |bytes| self.write(bytes))
+    }
+    fn write_le_uint(&self, n: uint) {
+        u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v))
+    }
+    fn write_le_int(&self, n: int) {
+        u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v))
+    }
+    fn write_be_uint(&self, n: uint) {
+        u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v))
+    }
+    fn write_be_int(&self, n: int) {
+        u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v))
+    }
+    fn write_be_u64(&self, n: u64) {
+        u64_to_be_bytes(n, 8u, |v| self.write(v))
+    }
+    fn write_be_u32(&self, n: u32) {
+        u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
+    }
+    fn write_be_u16(&self, n: u16) {
+        u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
+    }
+    fn write_be_i64(&self, n: i64) {
+        u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
+    }
+    fn write_be_i32(&self, n: i32) {
+        u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
+    }
+    fn write_be_i16(&self, n: i16) {
+        u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
+    }
+    fn write_be_f64(&self, f:f64) {
+        unsafe {
+            self.write_be_u64(cast::transmute(f))
+        }
+    }
+    fn write_be_f32(&self, f:f32) {
+        unsafe {
+            self.write_be_u32(cast::transmute(f))
+        }
+    }
+    fn write_le_u64(&self, n: u64) {
+        u64_to_le_bytes(n, 8u, |v| self.write(v))
+    }
+    fn write_le_u32(&self, n: u32) {
+        u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
+    }
+    fn write_le_u16(&self, n: u16) {
+        u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
+    }
+    fn write_le_i64(&self, n: i64) {
+        u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
+    }
+    fn write_le_i32(&self, n: i32) {
+        u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
+    }
+    fn write_le_i16(&self, n: i16) {
+        u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
+    }
+    fn write_le_f64(&self, f:f64) {
+        unsafe {
+            self.write_le_u64(cast::transmute(f))
+        }
+    }
+    fn write_le_f32(&self, f:f32) {
+        unsafe {
+            self.write_le_u32(cast::transmute(f))
+        }
+    }
+
+    fn write_u8(&self, n: u8) { self.write([n]) }
+    fn write_i8(&self, n: i8) { self.write([n as u8]) }
+
+}
+
+#[allow(non_implicitly_copyable_typarams)]
+pub fn file_writer(path: &Path, flags: &[FileFlag]) -> Result<@Writer, ~str> {
+    mk_file_writer(path, flags).chain(|w| result::Ok(w))
+}
+
+
+// FIXME: fileflags // #2004
+pub fn buffered_file_writer(path: &Path) -> Result<@Writer, ~str> {
+    unsafe {
+        let f = do os::as_c_charp(path.to_str()) |pathbuf| {
+            do os::as_c_charp("w") |modebuf| {
+                libc::fopen(pathbuf, modebuf)
+            }
+        };
+        return if f as uint == 0u {
+            result::Err(~"error opening " + path.to_str())
+        } else {
+            result::Ok(FILE_writer(f, true))
+        }
+    }
+}
+
+// FIXME (#2004) it would be great if this could be a const
+// FIXME (#2004) why are these different from the way stdin() is
+// implemented?
+
+
+/**
+* Gives a `Writer` which allows you to write to the standard output.
+*
+* # Examples
+* ~~~
+* let stdout = core::io::stdout();
+* stdout.write_str("hello\n");
+* ~~~
+*/
+pub fn stdout() -> @Writer { fd_writer(libc::STDOUT_FILENO as c_int, false) }
+
+/**
+* Gives a `Writer` which allows you to write to standard error.
+*
+* # Examples
+* ~~~
+* let stderr = core::io::stderr();
+* stderr.write_str("hello\n");
+* ~~~
+*/
+pub fn stderr() -> @Writer { fd_writer(libc::STDERR_FILENO as c_int, false) }
+
+/**
+* Prints a string to standard output.
+*
+* This string will not have an implicit newline at the end. If you want
+* an implicit newline, please see `println`.
+*
+* # Examples
+* ~~~
+* // print is imported into the prelude, and so is always available.
+* print("hello");
+* ~~~
+*/
+pub fn print(s: &str) {
+    stdout().write_str(s);
+}
+
+/**
+* Prints a string to standard output, followed by a newline.
+*
+* If you do not want an implicit newline, please see `print`.
+*
+* # Examples
+* ~~~
+* // println is imported into the prelude, and so is always available.
+* println("hello");
+* ~~~
+*/
+pub fn println(s: &str) {
+    stdout().write_line(s);
+}
+
+pub struct BytesWriter {
+    bytes: @mut ~[u8],
+    pos: @mut uint,
+}
+
+impl Writer for BytesWriter {
+    fn write(&self, v: &[u8]) {
+        let v_len = v.len();
+
+        let bytes = &mut *self.bytes;
+        let count = uint::max(bytes.len(), *self.pos + v_len);
+        vec::reserve(bytes, count);
+
+        unsafe {
+            // Silly stage0 borrow check workaround...
+            let casted: &mut ~[u8] = cast::transmute_copy(&bytes);
+            vec::raw::set_len(casted, count);
+
+            let view = vec::mut_slice(*bytes, *self.pos, count);
+            vec::bytes::copy_memory(view, v, v_len);
+        }
+
+        *self.pos += v_len;
+    }
+
+    fn seek(&self, offset: int, whence: SeekStyle) {
+        let pos = *self.pos;
+        let len = vec::uniq_len(&const *self.bytes);
+        *self.pos = seek_in_buf(offset, pos, len, whence);
+    }
+
+    fn tell(&self) -> uint {
+        *self.pos
+    }
+
+    fn flush(&self) -> int {
+        0
+    }
+
+    fn get_type(&self) -> WriterType {
+        File
+    }
+}
+
+pub fn BytesWriter() -> BytesWriter {
+    BytesWriter {
+        bytes: @mut ~[],
+        pos: @mut 0
+    }
+}
+
+pub fn with_bytes_writer(f: &fn(@Writer)) -> ~[u8] {
+    let wr = @BytesWriter();
+    f(wr as @Writer);
+    let @BytesWriter { bytes, _ } = wr;
+    copy *bytes
+}
+
+pub fn with_str_writer(f: &fn(@Writer)) -> ~str {
+    let mut v = with_bytes_writer(f);
+
+    // Make sure the vector has a trailing null and is proper utf8.
+    v.push(0);
+    assert!(str::is_utf8(v));
+
+    unsafe {
+        ::cast::transmute(v)
+    }
+}
+
+// Utility functions
+pub fn seek_in_buf(offset: int, pos: uint, len: uint, whence: SeekStyle) ->
+   uint {
+    let mut bpos = pos as int;
+    let blen = len as int;
+    match whence {
+      SeekSet => bpos = offset,
+      SeekCur => bpos += offset,
+      SeekEnd => bpos = blen + offset
+    }
+    if bpos < 0 { bpos = 0; } else if bpos > blen { bpos = blen; }
+    return bpos as uint;
+}
+
+#[allow(non_implicitly_copyable_typarams)]
+pub fn read_whole_file_str(file: &Path) -> Result<~str, ~str> {
+    result::chain(read_whole_file(file), |bytes| {
+        if str::is_utf8(bytes) {
+            result::Ok(str::from_bytes(bytes))
+       } else {
+           result::Err(file.to_str() + ~" is not UTF-8")
+       }
+    })
+}
+
+// FIXME (#2004): implement this in a low-level way. Going through the
+// abstractions is pointless.
+#[allow(non_implicitly_copyable_typarams)]
+pub fn read_whole_file(file: &Path) -> Result<~[u8], ~str> {
+    result::chain(file_reader(file), |rdr| {
+        result::Ok(rdr.read_whole_stream())
+    })
+}
+
+// fsync related
+
+pub mod fsync {
+    use io::{FILERes, FdRes, fd_t};
+    use kinds::Copy;
+    use libc;
+    use ops::Drop;
+    use option::{None, Option, Some};
+    use os;
+
+    pub enum Level {
+        // whatever fsync does on that platform
+        FSync,
+
+        // fdatasync on linux, similiar or more on other platforms
+        FDataSync,
+
+        // full fsync
+        //
+        // You must additionally sync the parent directory as well!
+        FullFSync,
+    }
+
+
+    // Artifacts that need to fsync on destruction
+    pub struct Res<t> {
+        arg: Arg<t>,
+    }
+
+    #[unsafe_destructor]
+    impl<T:Copy> Drop for Res<T> {
+        fn finalize(&self) {
+            match self.arg.opt_level {
+                None => (),
+                Some(level) => {
+                  // fail hard if not succesful
+                  assert!(((self.arg.fsync_fn)(self.arg.val, level)
+                    != -1));
+                }
+            }
+        }
+    }
+
+    pub fn Res<t: Copy>(arg: Arg<t>) -> Res<t>{
+        Res {
+            arg: arg
+        }
+    }
+
+    pub struct Arg<t> {
+        val: t,
+        opt_level: Option<Level>,
+        fsync_fn: @fn(f: t, Level) -> int,
+    }
+
+    // fsync file after executing blk
+    // FIXME (#2004) find better way to create resources within lifetime of
+    // outer res
+    pub fn FILE_res_sync(file: &FILERes, opt_level: Option<Level>,
+                         blk: &fn(v: Res<*libc::FILE>)) {
+        blk(Res(Arg {
+            val: file.f, opt_level: opt_level,
+            fsync_fn: |file, l| {
+                unsafe {
+                    os::fsync_fd(libc::fileno(file), l) as int
+                }
+            }
+        }));
+    }
+
+    // fsync fd after executing blk
+    pub fn fd_res_sync(fd: &FdRes, opt_level: Option<Level>,
+                       blk: &fn(v: Res<fd_t>)) {
+        blk(Res(Arg {
+            val: fd.fd, opt_level: opt_level,
+            fsync_fn: |fd, l| os::fsync_fd(fd, l) as int
+        }));
+    }
+
+    // Type of objects that may want to fsync
+    pub trait FSyncable { fn fsync(&self, l: Level) -> int; }
+
+    // Call o.fsync after executing blk
+    pub fn obj_sync(o: @FSyncable, opt_level: Option<Level>,
+                    blk: &fn(v: Res<@FSyncable>)) {
+        blk(Res(Arg {
+            val: o, opt_level: opt_level,
+            fsync_fn: |o, l| o.fsync(l)
+        }));
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use i32;
+    use io::{BytesWriter, SeekCur, SeekEnd, SeekSet};
+    use io;
+    use path::Path;
+    use result;
+    use str;
+    use u64;
+    use vec;
+
+    #[test]
+    fn test_simple() {
+        let tmpfile = &Path("tmp/lib-io-test-simple.tmp");
+        debug!(tmpfile);
+        let frood: ~str =
+            ~"A hoopy frood who really knows where his towel is.";
+        debug!(copy frood);
+        {
+            let out: @io::Writer =
+                result::get(
+                    &io::file_writer(tmpfile, ~[io::Create, io::Truncate]));
+            out.write_str(frood);
+        }
+        let inp: @io::Reader = result::get(&io::file_reader(tmpfile));
+        let frood2: ~str = inp.read_c_str();
+        debug!(copy frood2);
+        assert_eq!(frood, frood2);
+    }
+
+    #[test]
+    fn test_readchars_empty() {
+        do io::with_str_reader(~"") |inp| {
+            let res : ~[char] = inp.read_chars(128);
+            assert_eq!(res.len(), 0);
+        }
+    }
+
+    #[test]
+    fn test_read_line_utf8() {
+        do io::with_str_reader(~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤") |inp| {
+            let line = inp.read_line();
+            assert_eq!(line, ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤");
+        }
+    }
+
+    #[test]
+    fn test_read_lines() {
+        do io::with_str_reader(~"a\nb\nc\n") |inp| {
+            assert_eq!(inp.read_lines(), ~[~"a", ~"b", ~"c"]);
+        }
+
+        do io::with_str_reader(~"a\nb\nc") |inp| {
+            assert_eq!(inp.read_lines(), ~[~"a", ~"b", ~"c"]);
+        }
+
+        do io::with_str_reader(~"") |inp| {
+            assert!(inp.read_lines().is_empty());
+        }
+    }
+
+    #[test]
+    fn test_readchars_wide() {
+        let wide_test = ~"生锈的汤匙切肉汤hello生锈的汤匙切肉汤";
+        let ivals : ~[int] = ~[
+            29983, 38152, 30340, 27748,
+            21273, 20999, 32905, 27748,
+            104, 101, 108, 108, 111,
+            29983, 38152, 30340, 27748,
+            21273, 20999, 32905, 27748];
+        fn check_read_ln(len : uint, s: &str, ivals: &[int]) {
+            do io::with_str_reader(s) |inp| {
+                let res : ~[char] = inp.read_chars(len);
+                if len <= ivals.len() {
+                    assert_eq!(res.len(), len);
+                }
+                assert!(vec::slice(ivals, 0u, res.len()) ==
+                             vec::map(res, |x| *x as int));
+            }
+        }
+        let mut i = 0;
+        while i < 8 {
+            check_read_ln(i, wide_test, ivals);
+            i += 1;
+        }
+        // check a long read for good measure
+        check_read_ln(128, wide_test, ivals);
+    }
+
+    #[test]
+    fn test_readchar() {
+        do io::with_str_reader(~"生") |inp| {
+            let res : char = inp.read_char();
+            assert_eq!(res as int, 29983);
+        }
+    }
+
+    #[test]
+    fn test_readchar_empty() {
+        do io::with_str_reader(~"") |inp| {
+            let res : char = inp.read_char();
+            assert_eq!(res as int, -1);
+        }
+    }
+
+    #[test]
+    fn file_reader_not_exist() {
+        match io::file_reader(&Path("not a file")) {
+          result::Err(copy e) => {
+            assert_eq!(e, ~"error opening not a file");
+          }
+          result::Ok(_) => fail!()
+        }
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_read_buffer_too_small() {
+        let path = &Path("tmp/lib-io-test-read-buffer-too-small.tmp");
+        // ensure the file exists
+        io::file_writer(path, [io::Create]).get();
+
+        let file = io::file_reader(path).get();
+        let mut buf = vec::from_elem(5, 0);
+        file.read(buf, 6); // this should fail because buf is too small
+    }
+
+    #[test]
+    fn test_read_buffer_big_enough() {
+        let path = &Path("tmp/lib-io-test-read-buffer-big-enough.tmp");
+        // ensure the file exists
+        io::file_writer(path, [io::Create]).get();
+
+        let file = io::file_reader(path).get();
+        let mut buf = vec::from_elem(5, 0);
+        file.read(buf, 4); // this should succeed because buf is big enough
+    }
+
+    #[test]
+    fn test_write_empty() {
+        let file = io::file_writer(&Path("tmp/lib-io-test-write-empty.tmp"),
+                                   [io::Create]).get();
+        file.write([]);
+    }
+
+    #[test]
+    fn file_writer_bad_name() {
+        match io::file_writer(&Path("?/?"), ~[]) {
+          result::Err(copy e) => {
+            assert!(str::starts_with(e, "error opening"));
+          }
+          result::Ok(_) => fail!()
+        }
+    }
+
+    #[test]
+    fn buffered_file_writer_bad_name() {
+        match io::buffered_file_writer(&Path("?/?")) {
+          result::Err(copy e) => {
+            assert!(str::starts_with(e, "error opening"));
+          }
+          result::Ok(_) => fail!()
+        }
+    }
+
+    #[test]
+    fn bytes_buffer_overwrite() {
+        let wr = BytesWriter();
+        wr.write(~[0u8, 1u8, 2u8, 3u8]);
+        assert!(*wr.bytes == ~[0u8, 1u8, 2u8, 3u8]);
+        wr.seek(-2, SeekCur);
+        wr.write(~[4u8, 5u8, 6u8, 7u8]);
+        assert!(*wr.bytes == ~[0u8, 1u8, 4u8, 5u8, 6u8, 7u8]);
+        wr.seek(-2, SeekEnd);
+        wr.write(~[8u8]);
+        wr.seek(1, SeekSet);
+        wr.write(~[9u8]);
+        assert!(*wr.bytes == ~[0u8, 9u8, 4u8, 5u8, 8u8, 7u8]);
+    }
+
+    #[test]
+    fn test_read_write_le() {
+        let path = Path("tmp/lib-io-test-read-write-le.tmp");
+        let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
+
+        // write the ints to the file
+        {
+            let file = io::file_writer(&path, [io::Create]).get();
+            for uints.each |i| {
+                file.write_le_u64(*i);
+            }
+        }
+
+        // then read them back and check that they are the same
+        {
+            let file = io::file_reader(&path).get();
+            for uints.each |i| {
+                assert_eq!(file.read_le_u64(), *i);
+            }
+        }
+    }
+
+    #[test]
+    fn test_read_write_be() {
+        let path = Path("tmp/lib-io-test-read-write-be.tmp");
+        let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
+
+        // write the ints to the file
+        {
+            let file = io::file_writer(&path, [io::Create]).get();
+            for uints.each |i| {
+                file.write_be_u64(*i);
+            }
+        }
+
+        // then read them back and check that they are the same
+        {
+            let file = io::file_reader(&path).get();
+            for uints.each |i| {
+                assert_eq!(file.read_be_u64(), *i);
+            }
+        }
+    }
+
+    #[test]
+    fn test_read_be_int_n() {
+        let path = Path("tmp/lib-io-test-read-be-int-n.tmp");
+        let ints = [i32::min_value, -123456, -42, -5, 0, 1, i32::max_value];
+
+        // write the ints to the file
+        {
+            let file = io::file_writer(&path, [io::Create]).get();
+            for ints.each |i| {
+                file.write_be_i32(*i);
+            }
+        }
+
+        // then read them back and check that they are the same
+        {
+            let file = io::file_reader(&path).get();
+            for ints.each |i| {
+                // this tests that the sign extension is working
+                // (comparing the values as i32 would not test this)
+                assert_eq!(file.read_be_int_n(4), *i as i64);
+            }
+        }
+    }
+
+    #[test]
+    fn test_read_f32() {
+        let path = Path("tmp/lib-io-test-read-f32.tmp");
+        //big-endian floating-point 8.1250
+        let buf = ~[0x41, 0x02, 0x00, 0x00];
+
+        {
+            let file = io::file_writer(&path, [io::Create]).get();
+            file.write(buf);
+        }
+
+        {
+            let file = io::file_reader(&path).get();
+            let f = file.read_be_f32();
+            assert_eq!(f, 8.1250);
+        }
+    }
+
+#[test]
+    fn test_read_write_f32() {
+        let path = Path("tmp/lib-io-test-read-write-f32.tmp");
+        let f:f32 = 8.1250;
+
+        {
+            let file = io::file_writer(&path, [io::Create]).get();
+            file.write_be_f32(f);
+            file.write_le_f32(f);
+        }
+
+        {
+            let file = io::file_reader(&path).get();
+            assert_eq!(file.read_be_f32(), 8.1250);
+            assert_eq!(file.read_le_f32(), 8.1250);
+        }
+    }
+}
diff --git a/src/libstd/io_util.rs b/src/libstd/io_util.rs
deleted file mode 100644
index 7d43663cc80..00000000000
--- a/src/libstd/io_util.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use core::io::{Reader, BytesReader};
-use core::io;
-
-pub struct BufReader {
-    buf: ~[u8],
-    pos: @mut uint
-}
-
-pub impl BufReader {
-    pub fn new(v: ~[u8]) -> BufReader {
-        BufReader {
-            buf: v,
-            pos: @mut 0
-        }
-    }
-
-    priv fn as_bytes_reader<A>(&self, f: &fn(&BytesReader) -> A) -> A {
-        // Recreating the BytesReader state every call since
-        // I can't get the borrowing to work correctly
-        let bytes_reader = BytesReader {
-            bytes: ::core::util::id::<&[u8]>(self.buf),
-            pos: @mut *self.pos
-        };
-
-        let res = f(&bytes_reader);
-
-        // FIXME #4429: This isn't correct if f fails
-        *self.pos = *bytes_reader.pos;
-
-        return res;
-    }
-}
-
-impl Reader for BufReader {
-    fn read(&self, bytes: &mut [u8], len: uint) -> uint {
-        self.as_bytes_reader(|r| r.read(bytes, len) )
-    }
-    fn read_byte(&self) -> int {
-        self.as_bytes_reader(|r| r.read_byte() )
-    }
-    fn eof(&self) -> bool {
-        self.as_bytes_reader(|r| r.eof() )
-    }
-    fn seek(&self, offset: int, whence: io::SeekStyle) {
-        self.as_bytes_reader(|r| r.seek(offset, whence) )
-    }
-    fn tell(&self) -> uint {
-        self.as_bytes_reader(|r| r.tell() )
-    }
-}
diff --git a/src/libstd/iter.rs b/src/libstd/iter.rs
new file mode 100644
index 00000000000..57a076bb082
--- /dev/null
+++ b/src/libstd/iter.rs
@@ -0,0 +1,326 @@
+// 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.
+
+/*! Composable internal iterators
+
+Internal iterators are functions implementing the protocol used by the `for` loop.
+
+An internal iterator takes `fn(...) -> bool` as a parameter, with returning `false` used to signal
+breaking out of iteration. The adaptors in the module work with any such iterator, not just ones
+tied to specific traits. For example:
+
+~~~~
+println(iter::to_vec(|f| uint::range(0, 20, f)).to_str());
+~~~~
+
+An external iterator object implementing the interface in the `iterator` module can be used as an
+internal iterator by calling the `advance` method. For example:
+
+~~~~
+use core::iterator::*;
+
+let xs = [0u, 1, 2, 3, 4, 5];
+let ys = [30, 40, 50, 60];
+let mut it = xs.iter().chain(ys.iter());
+for it.advance |&x: &uint| {
+    println(x.to_str());
+}
+~~~~
+
+Internal iterators provide a subset of the functionality of an external iterator. It's not possible
+to interleave them to implement algorithms like `zip`, `union` and `merge`. However, they're often
+much easier to implement.
+
+*/
+
+use cmp::Ord;
+use option::{Option, Some, None};
+use vec::OwnedVector;
+use num::{One, Zero};
+use ops::{Add, Mul};
+
+pub trait Times {
+    fn times(&self, it: &fn() -> bool) -> bool;
+}
+
+/**
+ * Transform an internal iterator into an owned vector.
+ *
+ * # Example:
+ *
+ * ~~~
+ * let xs = ~[1, 2, 3];
+ * let ys = do iter::to_vec |f| { xs.each(|x| f(*x)) };
+ * assert_eq!(xs, ys);
+ * ~~~
+ */
+#[inline(always)]
+pub fn to_vec<T>(iter: &fn(f: &fn(T) -> bool) -> bool) -> ~[T] {
+    let mut v = ~[];
+    for iter |x| { v.push(x) }
+    v
+}
+
+/**
+ * Return true if `predicate` is true for any values yielded by an internal iterator.
+ *
+ * Example:
+ *
+ * ~~~~
+ * let xs = ~[1u, 2, 3, 4, 5];
+ * assert!(any(|&x: &uint| x > 2, |f| xs.each(f)));
+ * assert!(!any(|&x: &uint| x > 5, |f| xs.each(f)));
+ * ~~~~
+ */
+#[inline(always)]
+pub fn any<T>(predicate: &fn(T) -> bool,
+              iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
+    for iter |x| {
+        if predicate(x) {
+            return true;
+        }
+    }
+    return false;
+}
+
+/**
+ * Return true if `predicate` is true for all values yielded by an internal iterator.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f)));
+ * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f)));
+ * ~~~~
+ */
+#[inline(always)]
+pub fn all<T>(predicate: &fn(T) -> bool,
+              iter: &fn(f: &fn(T) -> bool) -> bool) -> bool {
+    // If we ever break, iter will return false, so this will only return true
+    // if predicate returns true for everything.
+    iter(|x| predicate(x))
+}
+
+/**
+ * Return the first element where `predicate` returns `true`. Return `None` if no element is found.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * let xs = ~[1u, 2, 3, 4, 5, 6];
+ * assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4);
+ * ~~~~
+ */
+#[inline(always)]
+pub fn find<T>(predicate: &fn(&T) -> bool,
+               iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
+    for iter |x| {
+        if predicate(&x) {
+            return Some(x);
+        }
+    }
+    None
+}
+
+/**
+ * Return the largest item yielded by an iterator. Return `None` if the iterator is empty.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
+ * assert_eq!(max(|f| xs.each(f)).unwrap(), &15);
+ * ~~~~
+ */
+#[inline]
+pub fn max<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
+    let mut result = None;
+    for iter |x| {
+        match result {
+            Some(ref mut y) => {
+                if x > *y {
+                    *y = x;
+                }
+            }
+            None => result = Some(x)
+        }
+    }
+    result
+}
+
+/**
+ * Return the smallest item yielded by an iterator. Return `None` if the iterator is empty.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
+ * assert_eq!(max(|f| xs.each(f)).unwrap(), &-5);
+ * ~~~~
+ */
+#[inline]
+pub fn min<T: Ord>(iter: &fn(f: &fn(T) -> bool) -> bool) -> Option<T> {
+    let mut result = None;
+    for iter |x| {
+        match result {
+            Some(ref mut y) => {
+                if x < *y {
+                    *y = x;
+                }
+            }
+            None => result = Some(x)
+        }
+    }
+    result
+}
+
+/**
+ * Reduce an iterator to an accumulated value.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
+ * ~~~~
+ */
+#[inline]
+pub fn fold<T, U>(start: T, iter: &fn(f: &fn(U) -> bool) -> bool, f: &fn(&mut T, U)) -> T {
+    let mut result = start;
+    for iter |x| {
+        f(&mut result, x);
+    }
+    result
+}
+
+/**
+ * Reduce an iterator to an accumulated value.
+ *
+ * `fold_ref` is usable in some generic functions where `fold` is too lenient to type-check, but it
+ * forces the iterator to yield borrowed pointers.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
+ *     fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
+ * }
+ * ~~~~
+ */
+#[inline]
+pub fn fold_ref<T, U>(start: T, iter: &fn(f: &fn(&U) -> bool) -> bool, f: &fn(&mut T, &U)) -> T {
+    let mut result = start;
+    for iter |x| {
+        f(&mut result, x);
+    }
+    result
+}
+
+/**
+ * Return the sum of the items yielding by an iterator.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * let xs: ~[int] = ~[1, 2, 3, 4];
+ * assert_eq!(do sum |f| { xs.each(f) }, 10);
+ * ~~~~
+ */
+#[inline(always)]
+pub fn sum<T: Zero + Add<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
+    fold_ref(Zero::zero::<T>(), iter, |a, x| *a = a.add(x))
+}
+
+/**
+ * Return the product of the items yielded by an iterator.
+ *
+ * # Example:
+ *
+ * ~~~~
+ * let xs: ~[int] = ~[1, 2, 3, 4];
+ * assert_eq!(do product |f| { xs.each(f) }, 24);
+ * ~~~~
+ */
+#[inline(always)]
+pub fn product<T: One + Mul<T, T>>(iter: &fn(f: &fn(&T) -> bool) -> bool) -> T {
+    fold_ref(One::one::<T>(), iter, |a, x| *a = a.mul(x))
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use prelude::*;
+
+    #[test]
+    fn test_to_vec() {
+        let xs = ~[1, 2, 3];
+        let ys = do to_vec |f| { xs.each(|x| f(*x)) };
+        assert_eq!(xs, ys);
+    }
+
+    #[test]
+    fn test_any() {
+        let xs = ~[1u, 2, 3, 4, 5];
+        assert!(any(|&x: &uint| x > 2, |f| xs.each(f)));
+        assert!(!any(|&x: &uint| x > 5, |f| xs.each(f)));
+    }
+
+    #[test]
+    fn test_all() {
+        assert!(all(|x: uint| x < 6, |f| uint::range(1, 6, f)));
+        assert!(!all(|x: uint| x < 5, |f| uint::range(1, 6, f)));
+    }
+
+    #[test]
+    fn test_find() {
+        let xs = ~[1u, 2, 3, 4, 5, 6];
+        assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4);
+    }
+
+    #[test]
+    fn test_max() {
+        let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
+        assert_eq!(max(|f| xs.each(f)).unwrap(), &15);
+    }
+
+    #[test]
+    fn test_min() {
+        let xs = ~[8, 2, 3, 1, -5, 9, 11, 15];
+        assert_eq!(min(|f| xs.each(f)).unwrap(), &-5);
+    }
+
+    #[test]
+    fn test_fold() {
+        assert_eq!(fold(0i, |f| int::range(1, 5, f), |a, x| *a += x), 10);
+    }
+
+    #[test]
+    fn test_sum() {
+        let xs: ~[int] = ~[1, 2, 3, 4];
+        assert_eq!(do sum |f| { xs.each(f) }, 10);
+    }
+
+    #[test]
+    fn test_empty_sum() {
+        let xs: ~[int] = ~[];
+        assert_eq!(do sum |f| { xs.each(f) }, 0);
+    }
+
+    #[test]
+    fn test_product() {
+        let xs: ~[int] = ~[1, 2, 3, 4];
+        assert_eq!(do product |f| { xs.each(f) }, 24);
+    }
+
+    #[test]
+    fn test_empty_product() {
+        let xs: ~[int] = ~[];
+        assert_eq!(do product |f| { xs.each(f) }, 1);
+    }
+}
diff --git a/src/libstd/iterator.rs b/src/libstd/iterator.rs
new file mode 100644
index 00000000000..a5679e6dbff
--- /dev/null
+++ b/src/libstd/iterator.rs
@@ -0,0 +1,719 @@
+// 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.
+
+/*! Composable external iterators
+
+The `Iterator` trait defines an interface for objects which implement iteration as a state machine.
+
+Algorithms like `zip` are provided as `Iterator` implementations which wrap other objects
+implementing the `Iterator` trait.
+
+*/
+
+use prelude::*;
+use num::{Zero, One};
+
+pub trait Iterator<A> {
+    /// Advance the iterator and return the next value. Return `None` when the end is reached.
+    fn next(&mut self) -> Option<A>;
+}
+
+/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
+/// implementations of the `Iterator` trait.
+///
+/// In the future these will be default methods instead of a utility trait.
+pub trait IteratorUtil<A> {
+    fn chain<U: Iterator<A>>(self, other: U) -> ChainIterator<Self, U>;
+    fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<Self, U>;
+    // FIXME: #5898: should be called map
+    fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, Self>;
+    fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, Self>;
+    fn filter_map<'r,  B>(self, f: &'r fn(A) -> Option<B>) -> FilterMapIterator<'r, A, B, Self>;
+    fn enumerate(self) -> EnumerateIterator<Self>;
+    fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, Self>;
+    fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, Self>;
+    fn skip(self, n: uint) -> SkipIterator<Self>;
+    fn take(self, n: uint) -> TakeIterator<Self>;
+    fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option<B>)
+        -> ScanIterator<'r, A, B, Self, St>;
+    fn advance(&mut self, f: &fn(A) -> bool) -> bool;
+    fn to_vec(&mut self) -> ~[A];
+    fn nth(&mut self, n: uint) -> Option<A>;
+    fn last(&mut self) -> Option<A>;
+    fn fold<B>(&mut self, start: B, f: &fn(B, A) -> B) -> B;
+    fn count(&mut self) -> uint;
+    fn all(&mut self, f: &fn(&A) -> bool) -> bool;
+    fn any(&mut self, f: &fn(&A) -> bool) -> bool;
+}
+
+/// Iterator adaptors provided for every `Iterator` implementation. The adaptor objects are also
+/// implementations of the `Iterator` trait.
+///
+/// In the future these will be default methods instead of a utility trait.
+impl<A, T: Iterator<A>> IteratorUtil<A> for T {
+    #[inline(always)]
+    fn chain<U: Iterator<A>>(self, other: U) -> ChainIterator<T, U> {
+        ChainIterator{a: self, b: other, flag: false}
+    }
+
+    #[inline(always)]
+    fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> {
+        ZipIterator{a: self, b: other}
+    }
+
+    // FIXME: #5898: should be called map
+    #[inline(always)]
+    fn transform<'r, B>(self, f: &'r fn(A) -> B) -> MapIterator<'r, A, B, T> {
+        MapIterator{iter: self, f: f}
+    }
+
+    #[inline(always)]
+    fn filter<'r>(self, predicate: &'r fn(&A) -> bool) -> FilterIterator<'r, A, T> {
+        FilterIterator{iter: self, predicate: predicate}
+    }
+
+    #[inline(always)]
+    fn filter_map<'r, B>(self, f: &'r fn(A) -> Option<B>) -> FilterMapIterator<'r, A, B, T> {
+        FilterMapIterator { iter: self, f: f }
+    }
+
+    #[inline(always)]
+    fn enumerate(self) -> EnumerateIterator<T> {
+        EnumerateIterator{iter: self, count: 0}
+    }
+
+    #[inline(always)]
+    fn skip_while<'r>(self, predicate: &'r fn(&A) -> bool) -> SkipWhileIterator<'r, A, T> {
+        SkipWhileIterator{iter: self, flag: false, predicate: predicate}
+    }
+
+    #[inline(always)]
+    fn take_while<'r>(self, predicate: &'r fn(&A) -> bool) -> TakeWhileIterator<'r, A, T> {
+        TakeWhileIterator{iter: self, flag: false, predicate: predicate}
+    }
+
+    #[inline(always)]
+    fn skip(self, n: uint) -> SkipIterator<T> {
+        SkipIterator{iter: self, n: n}
+    }
+
+    #[inline(always)]
+    fn take(self, n: uint) -> TakeIterator<T> {
+        TakeIterator{iter: self, n: n}
+    }
+
+    #[inline(always)]
+    fn scan<'r, St, B>(self, initial_state: St, f: &'r fn(&mut St, A) -> Option<B>)
+        -> ScanIterator<'r, A, B, T, St> {
+        ScanIterator{iter: self, f: f, state: initial_state}
+    }
+
+    /// A shim implementing the `for` loop iteration protocol for iterator objects
+    #[inline]
+    fn advance(&mut self, f: &fn(A) -> bool) -> bool {
+        loop {
+            match self.next() {
+                Some(x) => {
+                    if !f(x) { return false; }
+                }
+                None => { return true; }
+            }
+        }
+    }
+
+    #[inline(always)]
+    fn to_vec(&mut self) -> ~[A] {
+        iter::to_vec::<A>(|f| self.advance(f))
+    }
+
+    /// Return the `n`th item yielded by an iterator.
+    #[inline(always)]
+    fn nth(&mut self, mut n: uint) -> Option<A> {
+        loop {
+            match self.next() {
+                Some(x) => if n == 0 { return Some(x) },
+                None => return None
+            }
+            n -= 1;
+        }
+    }
+
+    /// Return the last item yielded by an iterator.
+    #[inline(always)]
+    fn last(&mut self) -> Option<A> {
+        let mut last = None;
+        for self.advance |x| { last = Some(x); }
+        last
+    }
+
+    /// Reduce an iterator to an accumulated value
+    #[inline]
+    fn fold<B>(&mut self, init: B, f: &fn(B, A) -> B) -> B {
+        let mut accum = init;
+        loop {
+            match self.next() {
+                Some(x) => { accum = f(accum, x); }
+                None    => { break; }
+            }
+        }
+        return accum;
+    }
+
+    /// Count the number of items yielded by an iterator
+    #[inline(always)]
+    fn count(&mut self) -> uint { self.fold(0, |cnt, _x| cnt + 1) }
+
+    #[inline(always)]
+    fn all(&mut self, f: &fn(&A) -> bool) -> bool {
+        for self.advance |x| { if !f(&x) { return false; } }
+        return true;
+    }
+
+    #[inline(always)]
+    fn any(&mut self, f: &fn(&A) -> bool) -> bool {
+        for self.advance |x| { if f(&x) { return true; } }
+        return false;
+    }
+}
+
+pub trait AdditiveIterator<A> {
+    fn sum(&mut self) -> A;
+}
+
+impl<A: Add<A, A> + Zero, T: Iterator<A>> AdditiveIterator<A> for T {
+    #[inline(always)]
+    fn sum(&mut self) -> A { self.fold(Zero::zero::<A>(), |s, x| s + x) }
+}
+
+pub trait MultiplicativeIterator<A> {
+    fn product(&mut self) -> A;
+}
+
+impl<A: Mul<A, A> + One, T: Iterator<A>> MultiplicativeIterator<A> for T {
+    #[inline(always)]
+    fn product(&mut self) -> A { self.fold(One::one::<A>(), |p, x| p * x) }
+}
+
+pub trait OrdIterator<A> {
+    fn max(&mut self) -> Option<A>;
+    fn min(&mut self) -> Option<A>;
+}
+
+impl<A: Ord, T: Iterator<A>> OrdIterator<A> for T {
+    #[inline(always)]
+    fn max(&mut self) -> Option<A> {
+        self.fold(None, |max, x| {
+            match max {
+                None    => Some(x),
+                Some(y) => Some(cmp::max(x, y))
+            }
+        })
+    }
+
+    #[inline(always)]
+    fn min(&mut self) -> Option<A> {
+        self.fold(None, |min, x| {
+            match min {
+                None    => Some(x),
+                Some(y) => Some(cmp::min(x, y))
+            }
+        })
+    }
+}
+
+pub struct ChainIterator<T, U> {
+    priv a: T,
+    priv b: U,
+    priv flag: bool
+}
+
+impl<A, T: Iterator<A>, U: Iterator<A>> Iterator<A> for ChainIterator<T, U> {
+    #[inline]
+    fn next(&mut self) -> Option<A> {
+        if self.flag {
+            self.b.next()
+        } else {
+            match self.a.next() {
+                Some(x) => return Some(x),
+                _ => ()
+            }
+            self.flag = true;
+            self.b.next()
+        }
+    }
+}
+
+pub struct ZipIterator<T, U> {
+    priv a: T,
+    priv b: U
+}
+
+impl<A, B, T: Iterator<A>, U: Iterator<B>> Iterator<(A, B)> for ZipIterator<T, U> {
+    #[inline]
+    fn next(&mut self) -> Option<(A, B)> {
+        match (self.a.next(), self.b.next()) {
+            (Some(x), Some(y)) => Some((x, y)),
+            _ => None
+        }
+    }
+}
+
+pub struct MapIterator<'self, A, B, T> {
+    priv iter: T,
+    priv f: &'self fn(A) -> B
+}
+
+impl<'self, A, B, T: Iterator<A>> Iterator<B> for MapIterator<'self, A, B, T> {
+    #[inline]
+    fn next(&mut self) -> Option<B> {
+        match self.iter.next() {
+            Some(a) => Some((self.f)(a)),
+            _ => None
+        }
+    }
+}
+
+pub struct FilterIterator<'self, A, T> {
+    priv iter: T,
+    priv predicate: &'self fn(&A) -> bool
+}
+
+impl<'self, A, T: Iterator<A>> Iterator<A> for FilterIterator<'self, A, T> {
+    #[inline]
+    fn next(&mut self) -> Option<A> {
+        for self.iter.advance |x| {
+            if (self.predicate)(&x) {
+                return Some(x);
+            } else {
+                loop
+            }
+        }
+        None
+    }
+}
+
+pub struct FilterMapIterator<'self, A, B, T> {
+    priv iter: T,
+    priv f: &'self fn(A) -> Option<B>
+}
+
+impl<'self, A, B, T: Iterator<A>> Iterator<B> for FilterMapIterator<'self, A, B, T> {
+    #[inline]
+    fn next(&mut self) -> Option<B> {
+        for self.iter.advance |x| {
+            match (self.f)(x) {
+                Some(y) => return Some(y),
+                None => ()
+            }
+        }
+        None
+    }
+}
+
+pub struct EnumerateIterator<T> {
+    priv iter: T,
+    priv count: uint
+}
+
+impl<A, T: Iterator<A>> Iterator<(uint, A)> for EnumerateIterator<T> {
+    #[inline]
+    fn next(&mut self) -> Option<(uint, A)> {
+        match self.iter.next() {
+            Some(a) => {
+                let ret = Some((self.count, a));
+                self.count += 1;
+                ret
+            }
+            _ => None
+        }
+    }
+}
+
+pub struct SkipWhileIterator<'self, A, T> {
+    priv iter: T,
+    priv flag: bool,
+    priv predicate: &'self fn(&A) -> bool
+}
+
+impl<'self, A, T: Iterator<A>> Iterator<A> for SkipWhileIterator<'self, A, T> {
+    #[inline]
+    fn next(&mut self) -> Option<A> {
+        let mut next = self.iter.next();
+        if self.flag {
+            next
+        } else {
+            loop {
+                match next {
+                    Some(x) => {
+                        if (self.predicate)(&x) {
+                            next = self.iter.next();
+                            loop
+                        } else {
+                            self.flag = true;
+                            return Some(x)
+                        }
+                    }
+                    None => return None
+                }
+            }
+        }
+    }
+}
+
+pub struct TakeWhileIterator<'self, A, T> {
+    priv iter: T,
+    priv flag: bool,
+    priv predicate: &'self fn(&A) -> bool
+}
+
+impl<'self, A, T: Iterator<A>> Iterator<A> for TakeWhileIterator<'self, A, T> {
+    #[inline]
+    fn next(&mut self) -> Option<A> {
+        if self.flag {
+            None
+        } else {
+            match self.iter.next() {
+                Some(x) => {
+                    if (self.predicate)(&x) {
+                        Some(x)
+                    } else {
+                        self.flag = true;
+                        None
+                    }
+                }
+                None => None
+            }
+        }
+    }
+}
+
+pub struct SkipIterator<T> {
+    priv iter: T,
+    priv n: uint
+}
+
+impl<A, T: Iterator<A>> Iterator<A> for SkipIterator<T> {
+    #[inline]
+    fn next(&mut self) -> Option<A> {
+        let mut next = self.iter.next();
+        if self.n == 0 {
+            next
+        } else {
+            let n = self.n;
+            for n.times {
+                match next {
+                    Some(_) => {
+                        next = self.iter.next();
+                        loop
+                    }
+                    None => {
+                        self.n = 0;
+                        return None
+                    }
+                }
+            }
+            self.n = 0;
+            next
+        }
+    }
+}
+
+pub struct TakeIterator<T> {
+    priv iter: T,
+    priv n: uint
+}
+
+impl<A, T: Iterator<A>> Iterator<A> for TakeIterator<T> {
+    #[inline]
+    fn next(&mut self) -> Option<A> {
+        let next = self.iter.next();
+        if self.n != 0 {
+            self.n -= 1;
+            next
+        } else {
+            None
+        }
+    }
+}
+
+pub struct ScanIterator<'self, A, B, T, St> {
+    priv iter: T,
+    priv f: &'self fn(&mut St, A) -> Option<B>,
+    state: St
+}
+
+impl<'self, A, B, T: Iterator<A>, St> Iterator<B> for ScanIterator<'self, A, B, T, St> {
+    #[inline]
+    fn next(&mut self) -> Option<B> {
+        self.iter.next().chain(|a| (self.f)(&mut self.state, a))
+    }
+}
+
+pub struct UnfoldrIterator<'self, A, St> {
+    priv f: &'self fn(&mut St) -> Option<A>,
+    state: St
+}
+
+pub impl<'self, A, St> UnfoldrIterator<'self, A, St> {
+    #[inline]
+    fn new(f: &'self fn(&mut St) -> Option<A>, initial_state: St)
+        -> UnfoldrIterator<'self, A, St> {
+        UnfoldrIterator {
+            f: f,
+            state: initial_state
+        }
+    }
+}
+
+impl<'self, A, St> Iterator<A> for UnfoldrIterator<'self, A, St> {
+    #[inline]
+    fn next(&mut self) -> Option<A> {
+        (self.f)(&mut self.state)
+    }
+}
+
+/// An infinite iterator starting at `start` and advancing by `step` with each iteration
+pub struct Counter<A> {
+    state: A,
+    step: A
+}
+
+pub impl<A> Counter<A> {
+    #[inline(always)]
+    fn new(start: A, step: A) -> Counter<A> {
+        Counter{state: start, step: step}
+    }
+}
+
+impl<A: Add<A, A> + Clone> Iterator<A> for Counter<A> {
+    #[inline(always)]
+    fn next(&mut self) -> Option<A> {
+        let result = self.state.clone();
+        self.state = self.state.add(&self.step); // FIXME: #6050
+        Some(result)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use prelude::*;
+
+    #[test]
+    fn test_counter_to_vec() {
+        let mut it = Counter::new(0, 5).take(10);
+        let xs = iter::to_vec(|f| it.advance(f));
+        assert_eq!(xs, ~[0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
+    }
+
+    #[test]
+    fn test_iterator_chain() {
+        let xs = [0u, 1, 2, 3, 4, 5];
+        let ys = [30u, 40, 50, 60];
+        let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60];
+        let mut it = xs.iter().chain(ys.iter());
+        let mut i = 0;
+        for it.advance |&x: &uint| {
+            assert_eq!(x, expected[i]);
+            i += 1;
+        }
+        assert_eq!(i, expected.len());
+
+        let ys = Counter::new(30u, 10).take(4);
+        let mut it = xs.iter().transform(|&x| x).chain(ys);
+        let mut i = 0;
+        for it.advance |x: uint| {
+            assert_eq!(x, expected[i]);
+            i += 1;
+        }
+        assert_eq!(i, expected.len());
+    }
+
+    #[test]
+    fn test_filter_map() {
+        let mut it = Counter::new(0u, 1u).take(10)
+            .filter_map(|x: uint| if x.is_even() { Some(x*x) } else { None });
+        assert_eq!(it.to_vec(), ~[0*0, 2*2, 4*4, 6*6, 8*8]);
+    }
+
+    #[test]
+    fn test_iterator_enumerate() {
+        let xs = [0u, 1, 2, 3, 4, 5];
+        let mut it = xs.iter().enumerate();
+        for it.advance |(i, &x): (uint, &uint)| {
+            assert_eq!(i, x);
+        }
+    }
+
+    #[test]
+    fn test_iterator_take_while() {
+        let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19];
+        let ys = [0u, 1, 2, 3, 5, 13];
+        let mut it = xs.iter().take_while(|&x| *x < 15u);
+        let mut i = 0;
+        for it.advance |&x: &uint| {
+            assert_eq!(x, ys[i]);
+            i += 1;
+        }
+        assert_eq!(i, ys.len());
+    }
+
+    #[test]
+    fn test_iterator_skip_while() {
+        let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19];
+        let ys = [15, 16, 17, 19];
+        let mut it = xs.iter().skip_while(|&x| *x < 15u);
+        let mut i = 0;
+        for it.advance |&x: &uint| {
+            assert_eq!(x, ys[i]);
+            i += 1;
+        }
+        assert_eq!(i, ys.len());
+    }
+
+    #[test]
+    fn test_iterator_skip() {
+        let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19, 20, 30];
+        let ys = [13, 15, 16, 17, 19, 20, 30];
+        let mut it = xs.iter().skip(5);
+        let mut i = 0;
+        for it.advance |&x: &uint| {
+            assert_eq!(x, ys[i]);
+            i += 1;
+        }
+        assert_eq!(i, ys.len());
+    }
+
+    #[test]
+    fn test_iterator_take() {
+        let xs = [0u, 1, 2, 3, 5, 13, 15, 16, 17, 19];
+        let ys = [0u, 1, 2, 3, 5];
+        let mut it = xs.iter().take(5);
+        let mut i = 0;
+        for it.advance |&x: &uint| {
+            assert_eq!(x, ys[i]);
+            i += 1;
+        }
+        assert_eq!(i, ys.len());
+    }
+
+    #[test]
+    fn test_iterator_scan() {
+        // test the type inference
+        fn add(old: &mut int, new: &uint) -> Option<float> {
+            *old += *new as int;
+            Some(*old as float)
+        }
+        let xs = [0u, 1, 2, 3, 4];
+        let ys = [0f, 1f, 3f, 6f, 10f];
+
+        let mut it = xs.iter().scan(0, add);
+        let mut i = 0;
+        for it.advance |x| {
+            assert_eq!(x, ys[i]);
+            i += 1;
+        }
+        assert_eq!(i, ys.len());
+    }
+
+    #[test]
+    fn test_unfoldr() {
+        fn count(st: &mut uint) -> Option<uint> {
+            if *st < 10 {
+                let ret = Some(*st);
+                *st += 1;
+                ret
+            } else {
+                None
+            }
+        }
+
+        let mut it = UnfoldrIterator::new(count, 0);
+        let mut i = 0;
+        for it.advance |counted| {
+            assert_eq!(counted, i);
+            i += 1;
+        }
+        assert_eq!(i, 10);
+    }
+
+    #[test]
+    fn test_iterator_nth() {
+        let v = &[0, 1, 2, 3, 4];
+        for uint::range(0, v.len()) |i| {
+            assert_eq!(v.iter().nth(i).unwrap(), &v[i]);
+        }
+    }
+
+    #[test]
+    fn test_iterator_last() {
+        let v = &[0, 1, 2, 3, 4];
+        assert_eq!(v.iter().last().unwrap(), &4);
+        assert_eq!(v.slice(0, 1).iter().last().unwrap(), &0);
+    }
+
+    #[test]
+    fn test_iterator_count() {
+        let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+        assert_eq!(v.slice(0, 4).iter().count(), 4);
+        assert_eq!(v.slice(0, 10).iter().count(), 10);
+        assert_eq!(v.slice(0, 0).iter().count(), 0);
+    }
+
+    #[test]
+    fn test_iterator_sum() {
+        let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+        assert_eq!(v.slice(0, 4).iter().transform(|&x| x).sum(), 6);
+        assert_eq!(v.iter().transform(|&x| x).sum(), 55);
+        assert_eq!(v.slice(0, 0).iter().transform(|&x| x).sum(), 0);
+    }
+
+    #[test]
+    fn test_iterator_product() {
+        let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+        assert_eq!(v.slice(0, 4).iter().transform(|&x| x).product(), 0);
+        assert_eq!(v.slice(1, 5).iter().transform(|&x| x).product(), 24);
+        assert_eq!(v.slice(0, 0).iter().transform(|&x| x).product(), 1);
+    }
+
+    #[test]
+    fn test_iterator_max() {
+        let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+        assert_eq!(v.slice(0, 4).iter().transform(|&x| x).max(), Some(3));
+        assert_eq!(v.iter().transform(|&x| x).max(), Some(10));
+        assert_eq!(v.slice(0, 0).iter().transform(|&x| x).max(), None);
+    }
+
+    #[test]
+    fn test_iterator_min() {
+        let v = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+        assert_eq!(v.slice(0, 4).iter().transform(|&x| x).min(), Some(0));
+        assert_eq!(v.iter().transform(|&x| x).min(), Some(0));
+        assert_eq!(v.slice(0, 0).iter().transform(|&x| x).min(), None);
+    }
+
+    #[test]
+    fn test_all() {
+        let v = ~&[1, 2, 3, 4, 5];
+        assert!(v.iter().all(|&x| *x < 10));
+        assert!(!v.iter().all(|&x| x.is_even()));
+        assert!(!v.iter().all(|&x| *x > 100));
+        assert!(v.slice(0, 0).iter().all(|_| fail!()));
+    }
+
+    #[test]
+    fn test_any() {
+        let v = ~&[1, 2, 3, 4, 5];
+        assert!(v.iter().any(|&x| *x < 10));
+        assert!(v.iter().any(|&x| x.is_even()));
+        assert!(!v.iter().any(|&x| *x > 100));
+        assert!(!v.slice(0, 0).iter().any(|_| fail!()));
+    }
+}
diff --git a/src/libstd/json.rs b/src/libstd/json.rs
deleted file mode 100644
index 44e965b5c43..00000000000
--- a/src/libstd/json.rs
+++ /dev/null
@@ -1,1958 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Rust JSON serialization library
-// Copyright (c) 2011 Google Inc.
-#[forbid(non_camel_case_types)];
-
-//! json serialization
-
-use core::io::{WriterUtil, ReaderUtil};
-use core::hashmap::HashMap;
-
-use serialize::Encodable;
-use serialize;
-use sort::Sort;
-
-/// Represents a json value
-pub enum Json {
-    Number(float),
-    String(~str),
-    Boolean(bool),
-    List(List),
-    Object(~Object),
-    Null,
-}
-
-pub type List = ~[Json];
-pub type Object = HashMap<~str, Json>;
-
-#[deriving(Eq)]
-pub struct Error {
-    line: uint,
-    col: uint,
-    msg: @~str,
-}
-
-fn escape_str(s: &str) -> ~str {
-    let mut escaped = ~"\"";
-    for str::each_char(s) |c| {
-        match c {
-          '"' => escaped += ~"\\\"",
-          '\\' => escaped += ~"\\\\",
-          '\x08' => escaped += ~"\\b",
-          '\x0c' => escaped += ~"\\f",
-          '\n' => escaped += ~"\\n",
-          '\r' => escaped += ~"\\r",
-          '\t' => escaped += ~"\\t",
-          _ => escaped += str::from_char(c)
-        }
-    };
-
-    escaped += ~"\"";
-
-    escaped
-}
-
-fn spaces(n: uint) -> ~str {
-    let mut ss = ~"";
-    for n.times { str::push_str(&mut ss, " "); }
-    return ss;
-}
-
-pub struct Encoder {
-    priv wr: @io::Writer,
-}
-
-pub fn Encoder(wr: @io::Writer) -> Encoder {
-    Encoder {
-        wr: wr
-    }
-}
-
-impl serialize::Encoder for Encoder {
-    fn emit_nil(&mut self) { self.wr.write_str("null") }
-
-    fn emit_uint(&mut self, v: uint) { self.emit_float(v as float); }
-    fn emit_u64(&mut self, v: u64) { self.emit_float(v as float); }
-    fn emit_u32(&mut self, v: u32) { self.emit_float(v as float); }
-    fn emit_u16(&mut self, v: u16) { self.emit_float(v as float); }
-    fn emit_u8(&mut self, v: u8)   { self.emit_float(v as float); }
-
-    fn emit_int(&mut self, v: int) { self.emit_float(v as float); }
-    fn emit_i64(&mut self, v: i64) { self.emit_float(v as float); }
-    fn emit_i32(&mut self, v: i32) { self.emit_float(v as float); }
-    fn emit_i16(&mut self, v: i16) { self.emit_float(v as float); }
-    fn emit_i8(&mut self, v: i8)   { self.emit_float(v as float); }
-
-    fn emit_bool(&mut self, v: bool) {
-        if v {
-            self.wr.write_str("true");
-        } else {
-            self.wr.write_str("false");
-        }
-    }
-
-    fn emit_f64(&mut self, v: f64) { self.emit_float(v as float); }
-    fn emit_f32(&mut self, v: f32) { self.emit_float(v as float); }
-    fn emit_float(&mut self, v: float) {
-        self.wr.write_str(float::to_str_digits(v, 6u));
-    }
-
-    fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
-    fn emit_str(&mut self, v: &str) { self.wr.write_str(escape_str(v)) }
-
-    fn emit_enum(&mut self, _name: &str, f: &fn(&mut Encoder)) { f(self) }
-
-    fn emit_enum_variant(&mut self,
-                         name: &str,
-                         _id: uint,
-                         cnt: uint,
-                         f: &fn(&mut Encoder)) {
-        // enums are encoded as strings or vectors:
-        // Bunny => "Bunny"
-        // Kangaroo(34,"William") => ["Kangaroo",[34,"William"]]
-
-        if cnt == 0 {
-            self.wr.write_str(escape_str(name));
-        } else {
-            self.wr.write_char('[');
-            self.wr.write_str(escape_str(name));
-            self.wr.write_char(',');
-            f(self);
-            self.wr.write_char(']');
-        }
-    }
-
-    fn emit_enum_variant_arg(&mut self, idx: uint, f: &fn(&mut Encoder)) {
-        if idx != 0 {
-            self.wr.write_char(',');
-        }
-        f(self);
-    }
-
-    fn emit_enum_struct_variant(&mut self,
-                                name: &str,
-                                id: uint,
-                                cnt: uint,
-                                f: &fn(&mut Encoder)) {
-        self.emit_enum_variant(name, id, cnt, f)
-    }
-
-    fn emit_enum_struct_variant_field(&mut self,
-                                      _: &str,
-                                      idx: uint,
-                                      f: &fn(&mut Encoder)) {
-        self.emit_enum_variant_arg(idx, f)
-    }
-
-    fn emit_struct(&mut self, _: &str, _: uint, f: &fn(&mut Encoder)) {
-        self.wr.write_char('{');
-        f(self);
-        self.wr.write_char('}');
-    }
-
-    fn emit_struct_field(&mut self,
-                         name: &str,
-                         idx: uint,
-                         f: &fn(&mut Encoder)) {
-        if idx != 0 { self.wr.write_char(','); }
-        self.wr.write_str(escape_str(name));
-        self.wr.write_char(':');
-        f(self);
-    }
-
-    fn emit_tuple(&mut self, len: uint, f: &fn(&mut Encoder)) {
-        self.emit_seq(len, f)
-    }
-    fn emit_tuple_arg(&mut self, idx: uint, f: &fn(&mut Encoder)) {
-        self.emit_seq_elt(idx, f)
-    }
-
-    fn emit_tuple_struct(&mut self,
-                         _name: &str,
-                         len: uint,
-                         f: &fn(&mut Encoder)) {
-        self.emit_seq(len, f)
-    }
-    fn emit_tuple_struct_arg(&mut self, idx: uint, f: &fn(&mut Encoder)) {
-        self.emit_seq_elt(idx, f)
-    }
-
-    fn emit_option(&mut self, f: &fn(&mut Encoder)) { f(self); }
-    fn emit_option_none(&mut self) { self.emit_nil(); }
-    fn emit_option_some(&mut self, f: &fn(&mut Encoder)) { f(self); }
-
-    fn emit_seq(&mut self, _len: uint, f: &fn(&mut Encoder)) {
-        self.wr.write_char('[');
-        f(self);
-        self.wr.write_char(']');
-    }
-
-    fn emit_seq_elt(&mut self, idx: uint, f: &fn(&mut Encoder)) {
-        if idx != 0 {
-            self.wr.write_char(',');
-        }
-        f(self)
-    }
-
-    fn emit_map(&mut self, _len: uint, f: &fn(&mut Encoder)) {
-        self.wr.write_char('{');
-        f(self);
-        self.wr.write_char('}');
-    }
-
-    fn emit_map_elt_key(&mut self, idx: uint, f: &fn(&mut Encoder)) {
-        if idx != 0 { self.wr.write_char(','); }
-        f(self)
-    }
-
-    fn emit_map_elt_val(&mut self, _idx: uint, f: &fn(&mut Encoder)) {
-        self.wr.write_char(':');
-        f(self)
-    }
-}
-
-pub struct PrettyEncoder {
-    priv wr: @io::Writer,
-    priv indent: uint,
-}
-
-pub fn PrettyEncoder(wr: @io::Writer) -> PrettyEncoder {
-    PrettyEncoder {
-        wr: wr,
-        indent: 0,
-    }
-}
-
-impl serialize::Encoder for PrettyEncoder {
-    fn emit_nil(&mut self) { self.wr.write_str("null") }
-
-    fn emit_uint(&mut self, v: uint) { self.emit_float(v as float); }
-    fn emit_u64(&mut self, v: u64) { self.emit_float(v as float); }
-    fn emit_u32(&mut self, v: u32) { self.emit_float(v as float); }
-    fn emit_u16(&mut self, v: u16) { self.emit_float(v as float); }
-    fn emit_u8(&mut self, v: u8)   { self.emit_float(v as float); }
-
-    fn emit_int(&mut self, v: int) { self.emit_float(v as float); }
-    fn emit_i64(&mut self, v: i64) { self.emit_float(v as float); }
-    fn emit_i32(&mut self, v: i32) { self.emit_float(v as float); }
-    fn emit_i16(&mut self, v: i16) { self.emit_float(v as float); }
-    fn emit_i8(&mut self, v: i8)   { self.emit_float(v as float); }
-
-    fn emit_bool(&mut self, v: bool) {
-        if v {
-            self.wr.write_str("true");
-        } else {
-            self.wr.write_str("false");
-        }
-    }
-
-    fn emit_f64(&mut self, v: f64) { self.emit_float(v as float); }
-    fn emit_f32(&mut self, v: f32) { self.emit_float(v as float); }
-    fn emit_float(&mut self, v: float) {
-        self.wr.write_str(float::to_str_digits(v, 6u));
-    }
-
-    fn emit_char(&mut self, v: char) { self.emit_str(str::from_char(v)) }
-    fn emit_str(&mut self, v: &str) { self.wr.write_str(escape_str(v)); }
-
-    fn emit_enum(&mut self, _name: &str, f: &fn(&mut PrettyEncoder)) {
-        f(self)
-    }
-
-    fn emit_enum_variant(&mut self,
-                         name: &str,
-                         _: uint,
-                         cnt: uint,
-                         f: &fn(&mut PrettyEncoder)) {
-        if cnt == 0 {
-            self.wr.write_str(escape_str(name));
-        } else {
-            self.wr.write_char('[');
-            self.indent += 2;
-            self.wr.write_char('\n');
-            self.wr.write_str(spaces(self.indent));
-            self.wr.write_str(escape_str(name));
-            self.wr.write_str(",\n");
-            f(self);
-            self.wr.write_char('\n');
-            self.indent -= 2;
-            self.wr.write_str(spaces(self.indent));
-            self.wr.write_char(']');
-        }
-    }
-
-    fn emit_enum_variant_arg(&mut self,
-                             idx: uint,
-                             f: &fn(&mut PrettyEncoder)) {
-        if idx != 0 {
-            self.wr.write_str(",\n");
-        }
-        self.wr.write_str(spaces(self.indent));
-        f(self)
-    }
-
-    fn emit_enum_struct_variant(&mut self,
-                                name: &str,
-                                id: uint,
-                                cnt: uint,
-                                f: &fn(&mut PrettyEncoder)) {
-        self.emit_enum_variant(name, id, cnt, f)
-    }
-
-    fn emit_enum_struct_variant_field(&mut self,
-                                      _: &str,
-                                      idx: uint,
-                                      f: &fn(&mut PrettyEncoder)) {
-        self.emit_enum_variant_arg(idx, f)
-    }
-
-
-    fn emit_struct(&mut self,
-                   _: &str,
-                   len: uint,
-                   f: &fn(&mut PrettyEncoder)) {
-        if len == 0 {
-            self.wr.write_str("{}");
-        } else {
-            self.wr.write_char('{');
-            self.indent += 2;
-            f(self);
-            self.wr.write_char('\n');
-            self.indent -= 2;
-            self.wr.write_str(spaces(self.indent));
-            self.wr.write_char('}');
-        }
-    }
-
-    fn emit_struct_field(&mut self,
-                         name: &str,
-                         idx: uint,
-                         f: &fn(&mut PrettyEncoder)) {
-        if idx == 0 {
-            self.wr.write_char('\n');
-        } else {
-            self.wr.write_str(",\n");
-        }
-        self.wr.write_str(spaces(self.indent));
-        self.wr.write_str(escape_str(name));
-        self.wr.write_str(": ");
-        f(self);
-    }
-
-    fn emit_tuple(&mut self, len: uint, f: &fn(&mut PrettyEncoder)) {
-        self.emit_seq(len, f)
-    }
-    fn emit_tuple_arg(&mut self, idx: uint, f: &fn(&mut PrettyEncoder)) {
-        self.emit_seq_elt(idx, f)
-    }
-
-    fn emit_tuple_struct(&mut self,
-                         _: &str,
-                         len: uint,
-                         f: &fn(&mut PrettyEncoder)) {
-        self.emit_seq(len, f)
-    }
-    fn emit_tuple_struct_arg(&mut self,
-                             idx: uint,
-                             f: &fn(&mut PrettyEncoder)) {
-        self.emit_seq_elt(idx, f)
-    }
-
-    fn emit_option(&mut self, f: &fn(&mut PrettyEncoder)) { f(self); }
-    fn emit_option_none(&mut self) { self.emit_nil(); }
-    fn emit_option_some(&mut self, f: &fn(&mut PrettyEncoder)) { f(self); }
-
-    fn emit_seq(&mut self, len: uint, f: &fn(&mut PrettyEncoder)) {
-        if len == 0 {
-            self.wr.write_str("[]");
-        } else {
-            self.wr.write_char('[');
-            self.indent += 2;
-            f(self);
-            self.wr.write_char('\n');
-            self.indent -= 2;
-            self.wr.write_str(spaces(self.indent));
-            self.wr.write_char(']');
-        }
-    }
-
-    fn emit_seq_elt(&mut self, idx: uint, f: &fn(&mut PrettyEncoder)) {
-        if idx == 0 {
-            self.wr.write_char('\n');
-        } else {
-            self.wr.write_str(",\n");
-        }
-        self.wr.write_str(spaces(self.indent));
-        f(self)
-    }
-
-    fn emit_map(&mut self, len: uint, f: &fn(&mut PrettyEncoder)) {
-        if len == 0 {
-            self.wr.write_str("{}");
-        } else {
-            self.wr.write_char('{');
-            self.indent += 2;
-            f(self);
-            self.wr.write_char('\n');
-            self.indent -= 2;
-            self.wr.write_str(spaces(self.indent));
-            self.wr.write_char('}');
-        }
-    }
-
-    fn emit_map_elt_key(&mut self, idx: uint, f: &fn(&mut PrettyEncoder)) {
-        if idx == 0 {
-            self.wr.write_char('\n');
-        } else {
-            self.wr.write_str(",\n");
-        }
-        self.wr.write_str(spaces(self.indent));
-        f(self);
-    }
-
-    fn emit_map_elt_val(&mut self, _idx: uint, f: &fn(&mut PrettyEncoder)) {
-        self.wr.write_str(": ");
-        f(self);
-    }
-}
-
-impl<E: serialize::Encoder> serialize::Encodable<E> for Json {
-    fn encode(&self, e: &mut E) {
-        match *self {
-            Number(v) => v.encode(e),
-            String(ref v) => v.encode(e),
-            Boolean(v) => v.encode(e),
-            List(ref v) => v.encode(e),
-            Object(ref v) => v.encode(e),
-            Null => e.emit_nil(),
-        }
-    }
-}
-
-/// Encodes a json value into a io::writer
-pub fn to_writer(wr: @io::Writer, json: &Json) {
-    let mut encoder = Encoder(wr);
-    json.encode(&mut encoder)
-}
-
-/// Encodes a json value into a string
-pub fn to_str(json: &Json) -> ~str {
-    io::with_str_writer(|wr| to_writer(wr, json))
-}
-
-/// Encodes a json value into a io::writer
-pub fn to_pretty_writer(wr: @io::Writer, json: &Json) {
-    let mut encoder = PrettyEncoder(wr);
-    json.encode(&mut encoder)
-}
-
-/// Encodes a json value into a string
-pub fn to_pretty_str(json: &Json) -> ~str {
-    io::with_str_writer(|wr| to_pretty_writer(wr, json))
-}
-
-pub struct Parser {
-    priv rdr: @io::Reader,
-    priv ch: char,
-    priv line: uint,
-    priv col: uint,
-}
-
-/// Decode a json value from an io::reader
-pub fn Parser(rdr: @io::Reader) -> Parser {
-    Parser {
-        rdr: rdr,
-        ch: rdr.read_char(),
-        line: 1,
-        col: 1,
-    }
-}
-
-pub impl Parser {
-    fn parse(&mut self) -> Result<Json, Error> {
-        match self.parse_value() {
-          Ok(value) => {
-            // Skip trailing whitespaces.
-            self.parse_whitespace();
-            // Make sure there is no trailing characters.
-            if self.eof() {
-                Ok(value)
-            } else {
-                self.error(~"trailing characters")
-            }
-          }
-          Err(e) => Err(e)
-        }
-    }
-}
-
-priv impl Parser {
-    fn eof(&self) -> bool { self.ch == -1 as char }
-
-    fn bump(&mut self) {
-        self.ch = self.rdr.read_char();
-
-        if self.ch == '\n' {
-            self.line += 1u;
-            self.col = 1u;
-        } else {
-            self.col += 1u;
-        }
-    }
-
-    fn next_char(&mut self) -> char {
-        self.bump();
-        self.ch
-    }
-
-    fn error<T>(&self, msg: ~str) -> Result<T, Error> {
-        Err(Error { line: self.line, col: self.col, msg: @msg })
-    }
-
-    fn parse_value(&mut self) -> Result<Json, Error> {
-        self.parse_whitespace();
-
-        if self.eof() { return self.error(~"EOF while parsing value"); }
-
-        match self.ch {
-          'n' => self.parse_ident("ull", Null),
-          't' => self.parse_ident("rue", Boolean(true)),
-          'f' => self.parse_ident("alse", Boolean(false)),
-          '0' .. '9' | '-' => self.parse_number(),
-          '"' =>
-            match self.parse_str() {
-              Ok(s) => Ok(String(s)),
-              Err(e) => Err(e),
-            },
-          '[' => self.parse_list(),
-          '{' => self.parse_object(),
-          _ => self.error(~"invalid syntax")
-        }
-    }
-
-    fn parse_whitespace(&mut self) {
-        while char::is_whitespace(self.ch) { self.bump(); }
-    }
-
-    fn parse_ident(&mut self, ident: &str, value: Json) -> Result<Json, Error> {
-        if str::all(ident, |c| c == self.next_char()) {
-            self.bump();
-            Ok(value)
-        } else {
-            self.error(~"invalid syntax")
-        }
-    }
-
-    fn parse_number(&mut self) -> Result<Json, Error> {
-        let mut neg = 1f;
-
-        if self.ch == '-' {
-            self.bump();
-            neg = -1f;
-        }
-
-        let mut res = match self.parse_integer() {
-          Ok(res) => res,
-          Err(e) => return Err(e)
-        };
-
-        if self.ch == '.' {
-            match self.parse_decimal(res) {
-              Ok(r) => res = r,
-              Err(e) => return Err(e)
-            }
-        }
-
-        if self.ch == 'e' || self.ch == 'E' {
-            match self.parse_exponent(res) {
-              Ok(r) => res = r,
-              Err(e) => return Err(e)
-            }
-        }
-
-        Ok(Number(neg * res))
-    }
-
-    fn parse_integer(&mut self) -> Result<float, Error> {
-        let mut res = 0f;
-
-        match self.ch {
-          '0' => {
-            self.bump();
-
-            // There can be only one leading '0'.
-            match self.ch {
-              '0' .. '9' => return self.error(~"invalid number"),
-              _ => ()
-            }
-          }
-          '1' .. '9' => {
-            while !self.eof() {
-                match self.ch {
-                  '0' .. '9' => {
-                    res *= 10f;
-                    res += ((self.ch as int) - ('0' as int)) as float;
-
-                    self.bump();
-                  }
-                  _ => break
-                }
-            }
-          }
-          _ => return self.error(~"invalid number")
-        }
-
-        Ok(res)
-    }
-
-    fn parse_decimal(&mut self, res: float) -> Result<float, Error> {
-        self.bump();
-
-        // Make sure a digit follows the decimal place.
-        match self.ch {
-          '0' .. '9' => (),
-          _ => return self.error(~"invalid number")
-        }
-
-        let mut res = res;
-        let mut dec = 1f;
-        while !self.eof() {
-            match self.ch {
-              '0' .. '9' => {
-                dec /= 10f;
-                res += (((self.ch as int) - ('0' as int)) as float) * dec;
-
-                self.bump();
-              }
-              _ => break
-            }
-        }
-
-        Ok(res)
-    }
-
-    fn parse_exponent(&mut self, mut res: float) -> Result<float, Error> {
-        self.bump();
-
-        let mut exp = 0u;
-        let mut neg_exp = false;
-
-        match self.ch {
-          '+' => self.bump(),
-          '-' => { self.bump(); neg_exp = true; }
-          _ => ()
-        }
-
-        // Make sure a digit follows the exponent place.
-        match self.ch {
-          '0' .. '9' => (),
-          _ => return self.error(~"invalid number")
-        }
-
-        while !self.eof() {
-            match self.ch {
-              '0' .. '9' => {
-                exp *= 10u;
-                exp += (self.ch as uint) - ('0' as uint);
-
-                self.bump();
-              }
-              _ => break
-            }
-        }
-
-        let exp = float::pow_with_uint(10u, exp);
-        if neg_exp {
-            res /= exp;
-        } else {
-            res *= exp;
-        }
-
-        Ok(res)
-    }
-
-    fn parse_str(&mut self) -> Result<~str, Error> {
-        let mut escape = false;
-        let mut res = ~"";
-
-        while !self.eof() {
-            self.bump();
-
-            if (escape) {
-                match self.ch {
-                  '"' => str::push_char(&mut res, '"'),
-                  '\\' => str::push_char(&mut res, '\\'),
-                  '/' => str::push_char(&mut res, '/'),
-                  'b' => str::push_char(&mut res, '\x08'),
-                  'f' => str::push_char(&mut res, '\x0c'),
-                  'n' => str::push_char(&mut res, '\n'),
-                  'r' => str::push_char(&mut res, '\r'),
-                  't' => str::push_char(&mut res, '\t'),
-                  'u' => {
-                      // Parse \u1234.
-                      let mut i = 0u;
-                      let mut n = 0u;
-                      while i < 4u {
-                          match self.next_char() {
-                            '0' .. '9' => {
-                              n = n * 16u + (self.ch as uint)
-                                          - ('0'     as uint);
-                            },
-                            'a' | 'A' => n = n * 16u + 10u,
-                            'b' | 'B' => n = n * 16u + 11u,
-                            'c' | 'C' => n = n * 16u + 12u,
-                            'd' | 'D' => n = n * 16u + 13u,
-                            'e' | 'E' => n = n * 16u + 14u,
-                            'f' | 'F' => n = n * 16u + 15u,
-                            _ => return self.error(
-                                   ~"invalid \\u escape (unrecognized hex)")
-                          }
-                          i += 1u;
-                      }
-
-                      // Error out if we didn't parse 4 digits.
-                      if i != 4u {
-                          return self.error(
-                            ~"invalid \\u escape (not four digits)");
-                      }
-
-                      str::push_char(&mut res, n as char);
-                  }
-                  _ => return self.error(~"invalid escape")
-                }
-                escape = false;
-            } else if self.ch == '\\' {
-                escape = true;
-            } else {
-                if self.ch == '"' {
-                    self.bump();
-                    return Ok(res);
-                }
-                str::push_char(&mut res, self.ch);
-            }
-        }
-
-        self.error(~"EOF while parsing string")
-    }
-
-    fn parse_list(&mut self) -> Result<Json, Error> {
-        self.bump();
-        self.parse_whitespace();
-
-        let mut values = ~[];
-
-        if self.ch == ']' {
-            self.bump();
-            return Ok(List(values));
-        }
-
-        loop {
-            match self.parse_value() {
-              Ok(v) => values.push(v),
-              Err(e) => return Err(e)
-            }
-
-            self.parse_whitespace();
-            if self.eof() {
-                return self.error(~"EOF while parsing list");
-            }
-
-            match self.ch {
-              ',' => self.bump(),
-              ']' => { self.bump(); return Ok(List(values)); }
-              _ => return self.error(~"expected `,` or `]`")
-            }
-        };
-    }
-
-    fn parse_object(&mut self) -> Result<Json, Error> {
-        self.bump();
-        self.parse_whitespace();
-
-        let mut values = ~HashMap::new();
-
-        if self.ch == '}' {
-          self.bump();
-          return Ok(Object(values));
-        }
-
-        while !self.eof() {
-            self.parse_whitespace();
-
-            if self.ch != '"' {
-                return self.error(~"key must be a string");
-            }
-
-            let key = match self.parse_str() {
-              Ok(key) => key,
-              Err(e) => return Err(e)
-            };
-
-            self.parse_whitespace();
-
-            if self.ch != ':' {
-                if self.eof() { break; }
-                return self.error(~"expected `:`");
-            }
-            self.bump();
-
-            match self.parse_value() {
-              Ok(value) => { values.insert(key, value); }
-              Err(e) => return Err(e)
-            }
-            self.parse_whitespace();
-
-            match self.ch {
-              ',' => self.bump(),
-              '}' => { self.bump(); return Ok(Object(values)); }
-              _ => {
-                  if self.eof() { break; }
-                  return self.error(~"expected `,` or `}`");
-              }
-            }
-        }
-
-        return self.error(~"EOF while parsing object");
-    }
-}
-
-/// Decodes a json value from an @io::Reader
-pub fn from_reader(rdr: @io::Reader) -> Result<Json, Error> {
-    let mut parser = Parser(rdr);
-    parser.parse()
-}
-
-/// Decodes a json value from a string
-pub fn from_str(s: &str) -> Result<Json, Error> {
-    do io::with_str_reader(s) |rdr| {
-        from_reader(rdr)
-    }
-}
-
-pub struct Decoder {
-    priv stack: ~[Json],
-}
-
-pub fn Decoder(json: Json) -> Decoder {
-    Decoder {
-        stack: ~[json]
-    }
-}
-
-impl serialize::Decoder for Decoder {
-    fn read_nil(&mut self) -> () {
-        debug!("read_nil");
-        match self.stack.pop() {
-            Null => (),
-            value => fail!("not a null: %?", value)
-        }
-    }
-
-    fn read_u64(&mut self)  -> u64  { self.read_float() as u64 }
-    fn read_u32(&mut self)  -> u32  { self.read_float() as u32 }
-    fn read_u16(&mut self)  -> u16  { self.read_float() as u16 }
-    fn read_u8 (&mut self)  -> u8   { self.read_float() as u8 }
-    fn read_uint(&mut self) -> uint { self.read_float() as uint }
-
-    fn read_i64(&mut self) -> i64 { self.read_float() as i64 }
-    fn read_i32(&mut self) -> i32 { self.read_float() as i32 }
-    fn read_i16(&mut self) -> i16 { self.read_float() as i16 }
-    fn read_i8 (&mut self) -> i8  { self.read_float() as i8 }
-    fn read_int(&mut self) -> int { self.read_float() as int }
-
-    fn read_bool(&mut self) -> bool {
-        debug!("read_bool");
-        match self.stack.pop() {
-            Boolean(b) => b,
-            value => fail!("not a boolean: %?", value)
-        }
-    }
-
-    fn read_f64(&mut self) -> f64 { self.read_float() as f64 }
-    fn read_f32(&mut self) -> f32 { self.read_float() as f32 }
-    fn read_float(&mut self) -> float {
-        debug!("read_float");
-        match self.stack.pop() {
-            Number(f) => f,
-            value => fail!("not a number: %?", value)
-        }
-    }
-
-    fn read_char(&mut self) -> char {
-        let mut v = ~[];
-        for str::each_char(self.read_str()) |c| { v.push(c) }
-        if v.len() != 1 { fail!("string must have one character") }
-        v[0]
-    }
-
-    fn read_str(&mut self) -> ~str {
-        debug!("read_str");
-        match self.stack.pop() {
-            String(s) => s,
-            json => fail!("not a string: %?", json)
-        }
-    }
-
-    fn read_enum<T>(&mut self, name: &str, f: &fn(&mut Decoder) -> T) -> T {
-        debug!("read_enum(%s)", name);
-        f(self)
-    }
-
-    fn read_enum_variant<T>(&mut self,
-                            names: &[&str],
-                            f: &fn(&mut Decoder, uint) -> T)
-                            -> T {
-        debug!("read_enum_variant(names=%?)", names);
-        let name = match self.stack.pop() {
-            String(s) => s,
-            List(list) => {
-                do vec::consume_reverse(list) |_i, v| {
-                    self.stack.push(v);
-                }
-                match self.stack.pop() {
-                    String(s) => s,
-                    value => fail!("invalid variant name: %?", value),
-                }
-            }
-            ref json => fail!("invalid variant: %?", *json),
-        };
-        let idx = match vec::position(names, |n| str::eq_slice(*n, name)) {
-            Some(idx) => idx,
-            None => fail!("Unknown variant name: %?", name),
-        };
-        f(self, idx)
-    }
-
-    fn read_enum_variant_arg<T>(&mut self,
-                                idx: uint,
-                                f: &fn(&mut Decoder) -> T)
-                                -> T {
-        debug!("read_enum_variant_arg(idx=%u)", idx);
-        f(self)
-    }
-
-    fn read_enum_struct_variant<T>(&mut self,
-                                   names: &[&str],
-                                   f: &fn(&mut Decoder, uint) -> T)
-                                   -> T {
-        debug!("read_enum_struct_variant(names=%?)", names);
-        self.read_enum_variant(names, f)
-    }
-
-
-    fn read_enum_struct_variant_field<T>(&mut self,
-                                         name: &str,
-                                         idx: uint,
-                                         f: &fn(&mut Decoder) -> T)
-                                         -> T {
-        debug!("read_enum_struct_variant_field(name=%?, idx=%u)", name, idx);
-        self.read_enum_variant_arg(idx, f)
-    }
-
-    fn read_struct<T>(&mut self,
-                      name: &str,
-                      len: uint,
-                      f: &fn(&mut Decoder) -> T)
-                      -> T {
-        debug!("read_struct(name=%s, len=%u)", name, len);
-        let value = f(self);
-        self.stack.pop();
-        value
-    }
-
-    fn read_struct_field<T>(&mut self,
-                            name: &str,
-                            idx: uint,
-                            f: &fn(&mut Decoder) -> T)
-                            -> T {
-        debug!("read_struct_field(name=%?, idx=%u)", name, idx);
-        match self.stack.pop() {
-            Object(obj) => {
-                let mut obj = obj;
-                let value = match obj.pop(&name.to_owned()) {
-                    None => fail!("no such field: %s", name),
-                    Some(json) => {
-                        self.stack.push(json);
-                        f(self)
-                    }
-                };
-                self.stack.push(Object(obj));
-                value
-            }
-            value => fail!("not an object: %?", value)
-        }
-    }
-
-    fn read_tuple<T>(&mut self, f: &fn(&mut Decoder, uint) -> T) -> T {
-        debug!("read_tuple()");
-        self.read_seq(f)
-    }
-
-    fn read_tuple_arg<T>(&mut self,
-                         idx: uint,
-                         f: &fn(&mut Decoder) -> T)
-                         -> T {
-        debug!("read_tuple_arg(idx=%u)", idx);
-        self.read_seq_elt(idx, f)
-    }
-
-    fn read_tuple_struct<T>(&mut self,
-                            name: &str,
-                            f: &fn(&mut Decoder, uint) -> T)
-                            -> T {
-        debug!("read_tuple_struct(name=%?)", name);
-        self.read_tuple(f)
-    }
-
-    fn read_tuple_struct_arg<T>(&mut self,
-                                idx: uint,
-                                f: &fn(&mut Decoder) -> T)
-                                -> T {
-        debug!("read_tuple_struct_arg(idx=%u)", idx);
-        self.read_tuple_arg(idx, f)
-    }
-
-    fn read_option<T>(&mut self, f: &fn(&mut Decoder, bool) -> T) -> T {
-        match self.stack.pop() {
-            Null => f(self, false),
-            value => { self.stack.push(value); f(self, true) }
-        }
-    }
-
-    fn read_seq<T>(&mut self, f: &fn(&mut Decoder, uint) -> T) -> T {
-        debug!("read_seq()");
-        let len = match self.stack.pop() {
-            List(list) => {
-                let len = list.len();
-                do vec::consume_reverse(list) |_i, v| {
-                    self.stack.push(v);
-                }
-                len
-            }
-            _ => fail!("not a list"),
-        };
-        f(self, len)
-    }
-
-    fn read_seq_elt<T>(&mut self, idx: uint, f: &fn(&mut Decoder) -> T) -> T {
-        debug!("read_seq_elt(idx=%u)", idx);
-        f(self)
-    }
-
-    fn read_map<T>(&mut self, f: &fn(&mut Decoder, uint) -> T) -> T {
-        debug!("read_map()");
-        let len = match self.stack.pop() {
-            Object(obj) => {
-                let mut obj = obj;
-                let len = obj.len();
-                do obj.consume |key, value| {
-                    self.stack.push(value);
-                    self.stack.push(String(key));
-                }
-                len
-            }
-            json => fail!("not an object: %?", json),
-        };
-        f(self, len)
-    }
-
-    fn read_map_elt_key<T>(&mut self,
-                           idx: uint,
-                           f: &fn(&mut Decoder) -> T)
-                           -> T {
-        debug!("read_map_elt_key(idx=%u)", idx);
-        f(self)
-    }
-
-    fn read_map_elt_val<T>(&mut self, idx: uint, f: &fn(&mut Decoder) -> T)
-                           -> T {
-        debug!("read_map_elt_val(idx=%u)", idx);
-        f(self)
-    }
-}
-
-impl Eq for Json {
-    fn eq(&self, other: &Json) -> bool {
-        match (self) {
-            &Number(f0) =>
-                match other { &Number(f1) => f0 == f1, _ => false },
-            &String(ref s0) =>
-                match other { &String(ref s1) => s0 == s1, _ => false },
-            &Boolean(b0) =>
-                match other { &Boolean(b1) => b0 == b1, _ => false },
-            &Null =>
-                match other { &Null => true, _ => false },
-            &List(ref v0) =>
-                match other { &List(ref v1) => v0 == v1, _ => false },
-            &Object(ref d0) => {
-                match other {
-                    &Object(ref d1) => {
-                        if d0.len() == d1.len() {
-                            let mut equal = true;
-                            for d0.each |k, v0| {
-                                match d1.find(k) {
-                                    Some(v1) if v0 == v1 => { },
-                                    _ => { equal = false; break }
-                                }
-                            };
-                            equal
-                        } else {
-                            false
-                        }
-                    }
-                    _ => false
-                }
-            }
-        }
-    }
-    fn ne(&self, other: &Json) -> bool { !self.eq(other) }
-}
-
-/// Test if two json values are less than one another
-impl Ord for Json {
-    fn lt(&self, other: &Json) -> bool {
-        match (*self) {
-            Number(f0) => {
-                match *other {
-                    Number(f1) => f0 < f1,
-                    String(_) | Boolean(_) | List(_) | Object(_) |
-                    Null => true
-                }
-            }
-
-            String(ref s0) => {
-                match *other {
-                    Number(_) => false,
-                    String(ref s1) => s0 < s1,
-                    Boolean(_) | List(_) | Object(_) | Null => true
-                }
-            }
-
-            Boolean(b0) => {
-                match *other {
-                    Number(_) | String(_) => false,
-                    Boolean(b1) => b0 < b1,
-                    List(_) | Object(_) | Null => true
-                }
-            }
-
-            List(ref l0) => {
-                match *other {
-                    Number(_) | String(_) | Boolean(_) => false,
-                    List(ref l1) => (*l0) < (*l1),
-                    Object(_) | Null => true
-                }
-            }
-
-            Object(ref d0) => {
-                match *other {
-                    Number(_) | String(_) | Boolean(_) | List(_) => false,
-                    Object(ref d1) => {
-                        let mut d0_flat = ~[];
-                        let mut d1_flat = ~[];
-
-                        // FIXME #4430: this is horribly inefficient...
-                        for d0.each |k, v| {
-                             d0_flat.push((@copy *k, @copy *v));
-                        }
-                        d0_flat.qsort();
-
-                        for d1.each |k, v| {
-                            d1_flat.push((@copy *k, @copy *v));
-                        }
-                        d1_flat.qsort();
-
-                        d0_flat < d1_flat
-                    }
-                    Null => true
-                }
-            }
-
-            Null => {
-                match *other {
-                    Number(_) | String(_) | Boolean(_) | List(_) |
-                    Object(_) =>
-                        false,
-                    Null => true
-                }
-            }
-        }
-    }
-    fn le(&self, other: &Json) -> bool { !(*other).lt(&(*self)) }
-    fn ge(&self, other: &Json) -> bool { !(*self).lt(other) }
-    fn gt(&self, other: &Json) -> bool { (*other).lt(&(*self))  }
-}
-
-trait ToJson { fn to_json(&self) -> Json; }
-
-impl ToJson for Json {
-    fn to_json(&self) -> Json { copy *self }
-}
-
-impl ToJson for @Json {
-    fn to_json(&self) -> Json { (**self).to_json() }
-}
-
-impl ToJson for int {
-    fn to_json(&self) -> Json { Number(*self as float) }
-}
-
-impl ToJson for i8 {
-    fn to_json(&self) -> Json { Number(*self as float) }
-}
-
-impl ToJson for i16 {
-    fn to_json(&self) -> Json { Number(*self as float) }
-}
-
-impl ToJson for i32 {
-    fn to_json(&self) -> Json { Number(*self as float) }
-}
-
-impl ToJson for i64 {
-    fn to_json(&self) -> Json { Number(*self as float) }
-}
-
-impl ToJson for uint {
-    fn to_json(&self) -> Json { Number(*self as float) }
-}
-
-impl ToJson for u8 {
-    fn to_json(&self) -> Json { Number(*self as float) }
-}
-
-impl ToJson for u16 {
-    fn to_json(&self) -> Json { Number(*self as float) }
-}
-
-impl ToJson for u32 {
-    fn to_json(&self) -> Json { Number(*self as float) }
-}
-
-impl ToJson for u64 {
-    fn to_json(&self) -> Json { Number(*self as float) }
-}
-
-impl ToJson for float {
-    fn to_json(&self) -> Json { Number(*self) }
-}
-
-impl ToJson for f32 {
-    fn to_json(&self) -> Json { Number(*self as float) }
-}
-
-impl ToJson for f64 {
-    fn to_json(&self) -> Json { Number(*self as float) }
-}
-
-impl ToJson for () {
-    fn to_json(&self) -> Json { Null }
-}
-
-impl ToJson for bool {
-    fn to_json(&self) -> Json { Boolean(*self) }
-}
-
-impl ToJson for ~str {
-    fn to_json(&self) -> Json { String(copy *self) }
-}
-
-impl ToJson for @~str {
-    fn to_json(&self) -> Json { String(copy **self) }
-}
-
-impl<A:ToJson,B:ToJson> ToJson for (A, B) {
-    fn to_json(&self) -> Json {
-        match *self {
-          (ref a, ref b) => {
-            List(~[a.to_json(), b.to_json()])
-          }
-        }
-    }
-}
-
-impl<A:ToJson,B:ToJson,C:ToJson> ToJson for (A, B, C) {
-    fn to_json(&self) -> Json {
-        match *self {
-          (ref a, ref b, ref c) => {
-            List(~[a.to_json(), b.to_json(), c.to_json()])
-          }
-        }
-    }
-}
-
-impl<A:ToJson> ToJson for ~[A] {
-    fn to_json(&self) -> Json { List(self.map(|elt| elt.to_json())) }
-}
-
-impl<A:ToJson + Copy> ToJson for HashMap<~str, A> {
-    fn to_json(&self) -> Json {
-        let mut d = HashMap::new();
-        for self.each |key, value| {
-            d.insert(copy *key, value.to_json());
-        }
-        Object(~d)
-    }
-}
-
-impl<A:ToJson> ToJson for Option<A> {
-    fn to_json(&self) -> Json {
-        match *self {
-          None => Null,
-          Some(ref value) => value.to_json()
-        }
-    }
-}
-
-impl to_str::ToStr for Json {
-    fn to_str(&self) -> ~str { to_str(self) }
-}
-
-impl to_str::ToStr for Error {
-    fn to_str(&self) -> ~str {
-        fmt!("%u:%u: %s", self.line, self.col, *self.msg)
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    use core::hashmap::HashMap;
-
-    use std::serialize::Decodable;
-
-    #[deriving(Eq, Encodable, Decodable)]
-    enum Animal {
-        Dog,
-        Frog(~str, int)
-    }
-
-    #[deriving(Eq, Encodable, Decodable)]
-    struct Inner {
-        a: (),
-        b: uint,
-        c: ~[~str],
-    }
-
-    #[deriving(Eq, Encodable, Decodable)]
-    struct Outer {
-        inner: ~[Inner],
-    }
-
-    fn mk_object(items: &[(~str, Json)]) -> Json {
-        let mut d = ~HashMap::new();
-
-        for items.each |item| {
-            match *item {
-                (copy key, copy value) => { d.insert(key, value); },
-            }
-        };
-
-        Object(d)
-    }
-
-    #[test]
-    fn test_write_null() {
-        assert_eq!(to_str(&Null), ~"null");
-        assert_eq!(to_pretty_str(&Null), ~"null");
-    }
-
-
-    #[test]
-    fn test_write_number() {
-        assert_eq!(to_str(&Number(3f)), ~"3");
-        assert_eq!(to_pretty_str(&Number(3f)), ~"3");
-
-        assert_eq!(to_str(&Number(3.1f)), ~"3.1");
-        assert_eq!(to_pretty_str(&Number(3.1f)), ~"3.1");
-
-        assert_eq!(to_str(&Number(-1.5f)), ~"-1.5");
-        assert_eq!(to_pretty_str(&Number(-1.5f)), ~"-1.5");
-
-        assert_eq!(to_str(&Number(0.5f)), ~"0.5");
-        assert_eq!(to_pretty_str(&Number(0.5f)), ~"0.5");
-    }
-
-    #[test]
-    fn test_write_str() {
-        assert_eq!(to_str(&String(~"")), ~"\"\"");
-        assert_eq!(to_pretty_str(&String(~"")), ~"\"\"");
-
-        assert_eq!(to_str(&String(~"foo")), ~"\"foo\"");
-        assert_eq!(to_pretty_str(&String(~"foo")), ~"\"foo\"");
-    }
-
-    #[test]
-    fn test_write_bool() {
-        assert_eq!(to_str(&Boolean(true)), ~"true");
-        assert_eq!(to_pretty_str(&Boolean(true)), ~"true");
-
-        assert_eq!(to_str(&Boolean(false)), ~"false");
-        assert_eq!(to_pretty_str(&Boolean(false)), ~"false");
-    }
-
-    #[test]
-    fn test_write_list() {
-        assert_eq!(to_str(&List(~[])), ~"[]");
-        assert_eq!(to_pretty_str(&List(~[])), ~"[]");
-
-        assert_eq!(to_str(&List(~[Boolean(true)])), ~"[true]");
-        assert_eq!(
-            to_pretty_str(&List(~[Boolean(true)])),
-            ~"\
-            [\n  \
-                true\n\
-            ]"
-        );
-
-        assert_eq!(to_str(&List(~[
-            Boolean(false),
-            Null,
-            List(~[String(~"foo\nbar"), Number(3.5f)])
-        ])), ~"[false,null,[\"foo\\nbar\",3.5]]");
-        assert_eq!(
-            to_pretty_str(&List(~[
-                Boolean(false),
-                Null,
-                List(~[String(~"foo\nbar"), Number(3.5f)])
-            ])),
-            ~"\
-            [\n  \
-                false,\n  \
-                null,\n  \
-                [\n    \
-                    \"foo\\nbar\",\n    \
-                    3.5\n  \
-                ]\n\
-            ]"
-        );
-    }
-
-    #[test]
-    fn test_write_object() {
-        assert_eq!(to_str(&mk_object(~[])), ~"{}");
-        assert_eq!(to_pretty_str(&mk_object(~[])), ~"{}");
-
-        assert_eq!(
-            to_str(&mk_object(~[(~"a", Boolean(true))])),
-            ~"{\"a\":true}"
-        );
-        assert_eq!(
-            to_pretty_str(&mk_object(~[(~"a", Boolean(true))])),
-            ~"\
-            {\n  \
-                \"a\": true\n\
-            }"
-        );
-
-        assert_eq!(
-            to_str(&mk_object(~[
-                (~"b", List(~[
-                    mk_object(~[(~"c", String(~"\x0c\r"))]),
-                    mk_object(~[(~"d", String(~""))])
-                ]))
-            ])),
-            ~"{\
-                \"b\":[\
-                    {\"c\":\"\\f\\r\"},\
-                    {\"d\":\"\"}\
-                ]\
-            }"
-        );
-        assert_eq!(
-            to_pretty_str(&mk_object(~[
-                (~"b", List(~[
-                    mk_object(~[(~"c", String(~"\x0c\r"))]),
-                    mk_object(~[(~"d", String(~""))])
-                ]))
-            ])),
-            ~"\
-            {\n  \
-                \"b\": [\n    \
-                    {\n      \
-                        \"c\": \"\\f\\r\"\n    \
-                    },\n    \
-                    {\n      \
-                        \"d\": \"\"\n    \
-                    }\n  \
-                ]\n\
-            }"
-        );
-
-        let a = mk_object(~[
-            (~"a", Boolean(true)),
-            (~"b", List(~[
-                mk_object(~[(~"c", String(~"\x0c\r"))]),
-                mk_object(~[(~"d", String(~""))])
-            ]))
-        ]);
-
-        // We can't compare the strings directly because the object fields be
-        // printed in a different order.
-        assert_eq!(copy a, from_str(to_str(&a)).unwrap());
-        assert_eq!(copy a, from_str(to_pretty_str(&a)).unwrap());
-    }
-
-    #[test]
-    fn test_write_enum() {
-        let animal = Dog;
-        assert_eq!(
-            do io::with_str_writer |wr| {
-                let mut encoder = Encoder(wr);
-                animal.encode(&mut encoder);
-            },
-            ~"\"Dog\""
-        );
-        assert_eq!(
-            do io::with_str_writer |wr| {
-                let mut encoder = PrettyEncoder(wr);
-                animal.encode(&mut encoder);
-            },
-            ~"\"Dog\""
-        );
-
-        let animal = Frog(~"Henry", 349);
-        assert_eq!(
-            do io::with_str_writer |wr| {
-                let mut encoder = Encoder(wr);
-                animal.encode(&mut encoder);
-            },
-            ~"[\"Frog\",\"Henry\",349]"
-        );
-        assert_eq!(
-            do io::with_str_writer |wr| {
-                let mut encoder = PrettyEncoder(wr);
-                animal.encode(&mut encoder);
-            },
-            ~"\
-            [\n  \
-                \"Frog\",\n  \
-                \"Henry\",\n  \
-                349\n\
-            ]"
-        );
-    }
-
-    #[test]
-    fn test_write_some() {
-        let value = Some(~"jodhpurs");
-        let s = do io::with_str_writer |wr| {
-            let mut encoder = Encoder(wr);
-            value.encode(&mut encoder);
-        };
-        assert_eq!(s, ~"\"jodhpurs\"");
-
-        let value = Some(~"jodhpurs");
-        let s = do io::with_str_writer |wr| {
-            let mut encoder = PrettyEncoder(wr);
-            value.encode(&mut encoder);
-        };
-        assert_eq!(s, ~"\"jodhpurs\"");
-    }
-
-    #[test]
-    fn test_write_none() {
-        let value: Option<~str> = None;
-        let s = do io::with_str_writer |wr| {
-            let mut encoder = Encoder(wr);
-            value.encode(&mut encoder);
-        };
-        assert_eq!(s, ~"null");
-
-        let s = do io::with_str_writer |wr| {
-            let mut encoder = Encoder(wr);
-            value.encode(&mut encoder);
-        };
-        assert_eq!(s, ~"null");
-    }
-
-    #[test]
-    fn test_trailing_characters() {
-        assert_eq!(from_str(~"nulla"),
-            Err(Error {line: 1u, col: 5u, msg: @~"trailing characters"}));
-        assert_eq!(from_str(~"truea"),
-            Err(Error {line: 1u, col: 5u, msg: @~"trailing characters"}));
-        assert_eq!(from_str(~"falsea"),
-            Err(Error {line: 1u, col: 6u, msg: @~"trailing characters"}));
-        assert_eq!(from_str(~"1a"),
-            Err(Error {line: 1u, col: 2u, msg: @~"trailing characters"}));
-        assert_eq!(from_str(~"[]a"),
-            Err(Error {line: 1u, col: 3u, msg: @~"trailing characters"}));
-        assert_eq!(from_str(~"{}a"),
-            Err(Error {line: 1u, col: 3u, msg: @~"trailing characters"}));
-    }
-
-    #[test]
-    fn test_read_identifiers() {
-        assert_eq!(from_str(~"n"),
-            Err(Error {line: 1u, col: 2u, msg: @~"invalid syntax"}));
-        assert_eq!(from_str(~"nul"),
-            Err(Error {line: 1u, col: 4u, msg: @~"invalid syntax"}));
-
-        assert_eq!(from_str(~"t"),
-            Err(Error {line: 1u, col: 2u, msg: @~"invalid syntax"}));
-        assert_eq!(from_str(~"truz"),
-            Err(Error {line: 1u, col: 4u, msg: @~"invalid syntax"}));
-
-        assert_eq!(from_str(~"f"),
-            Err(Error {line: 1u, col: 2u, msg: @~"invalid syntax"}));
-        assert_eq!(from_str(~"faz"),
-            Err(Error {line: 1u, col: 3u, msg: @~"invalid syntax"}));
-
-        assert_eq!(from_str(~"null"), Ok(Null));
-        assert_eq!(from_str(~"true"), Ok(Boolean(true)));
-        assert_eq!(from_str(~"false"), Ok(Boolean(false)));
-        assert_eq!(from_str(~" null "), Ok(Null));
-        assert_eq!(from_str(~" true "), Ok(Boolean(true)));
-        assert_eq!(from_str(~" false "), Ok(Boolean(false)));
-    }
-
-    #[test]
-    fn test_decode_identifiers() {
-        let mut decoder = Decoder(from_str(~"null").unwrap());
-        let v: () = Decodable::decode(&mut decoder);
-        assert_eq!(v, ());
-
-        let mut decoder = Decoder(from_str(~"true").unwrap());
-        let v: bool = Decodable::decode(&mut decoder);
-        assert_eq!(v, true);
-
-        let mut decoder = Decoder(from_str(~"false").unwrap());
-        let v: bool = Decodable::decode(&mut decoder);
-        assert_eq!(v, false);
-    }
-
-    #[test]
-    fn test_read_number() {
-        assert_eq!(from_str(~"+"),
-            Err(Error {line: 1u, col: 1u, msg: @~"invalid syntax"}));
-        assert_eq!(from_str(~"."),
-            Err(Error {line: 1u, col: 1u, msg: @~"invalid syntax"}));
-
-        assert_eq!(from_str(~"-"),
-            Err(Error {line: 1u, col: 2u, msg: @~"invalid number"}));
-        assert_eq!(from_str(~"00"),
-            Err(Error {line: 1u, col: 2u, msg: @~"invalid number"}));
-        assert_eq!(from_str(~"1."),
-            Err(Error {line: 1u, col: 3u, msg: @~"invalid number"}));
-        assert_eq!(from_str(~"1e"),
-            Err(Error {line: 1u, col: 3u, msg: @~"invalid number"}));
-        assert_eq!(from_str(~"1e+"),
-            Err(Error {line: 1u, col: 4u, msg: @~"invalid number"}));
-
-        assert_eq!(from_str(~"3"), Ok(Number(3f)));
-        assert_eq!(from_str(~"3.1"), Ok(Number(3.1f)));
-        assert_eq!(from_str(~"-1.2"), Ok(Number(-1.2f)));
-        assert_eq!(from_str(~"0.4"), Ok(Number(0.4f)));
-        assert_eq!(from_str(~"0.4e5"), Ok(Number(0.4e5f)));
-        assert_eq!(from_str(~"0.4e+15"), Ok(Number(0.4e15f)));
-        assert_eq!(from_str(~"0.4e-01"), Ok(Number(0.4e-01f)));
-        assert_eq!(from_str(~" 3 "), Ok(Number(3f)));
-    }
-
-    #[test]
-    fn test_decode_numbers() {
-        let mut decoder = Decoder(from_str(~"3").unwrap());
-        let v: float = Decodable::decode(&mut decoder);
-        assert_eq!(v, 3f);
-
-        let mut decoder = Decoder(from_str(~"3.1").unwrap());
-        let v: float = Decodable::decode(&mut decoder);
-        assert_eq!(v, 3.1f);
-
-        let mut decoder = Decoder(from_str(~"-1.2").unwrap());
-        let v: float = Decodable::decode(&mut decoder);
-        assert_eq!(v, -1.2f);
-
-        let mut decoder = Decoder(from_str(~"0.4").unwrap());
-        let v: float = Decodable::decode(&mut decoder);
-        assert_eq!(v, 0.4f);
-
-        let mut decoder = Decoder(from_str(~"0.4e5").unwrap());
-        let v: float = Decodable::decode(&mut decoder);
-        assert_eq!(v, 0.4e5f);
-
-        let mut decoder = Decoder(from_str(~"0.4e15").unwrap());
-        let v: float = Decodable::decode(&mut decoder);
-        assert_eq!(v, 0.4e15f);
-
-        let mut decoder = Decoder(from_str(~"0.4e-01").unwrap());
-        let v: float = Decodable::decode(&mut decoder);
-        assert_eq!(v, 0.4e-01f);
-    }
-
-    #[test]
-    fn test_read_str() {
-        assert_eq!(from_str(~"\""),
-            Err(Error {line: 1u, col: 2u, msg: @~"EOF while parsing string"
-        }));
-        assert_eq!(from_str(~"\"lol"),
-            Err(Error {line: 1u, col: 5u, msg: @~"EOF while parsing string"
-        }));
-
-        assert_eq!(from_str(~"\"\""), Ok(String(~"")));
-        assert_eq!(from_str(~"\"foo\""), Ok(String(~"foo")));
-        assert_eq!(from_str(~"\"\\\"\""), Ok(String(~"\"")));
-        assert_eq!(from_str(~"\"\\b\""), Ok(String(~"\x08")));
-        assert_eq!(from_str(~"\"\\n\""), Ok(String(~"\n")));
-        assert_eq!(from_str(~"\"\\r\""), Ok(String(~"\r")));
-        assert_eq!(from_str(~"\"\\t\""), Ok(String(~"\t")));
-        assert_eq!(from_str(~" \"foo\" "), Ok(String(~"foo")));
-        assert_eq!(from_str(~"\"\\u12ab\""), Ok(String(~"\u12ab")));
-        assert_eq!(from_str(~"\"\\uAB12\""), Ok(String(~"\uAB12")));
-    }
-
-    #[test]
-    fn test_decode_str() {
-        let mut decoder = Decoder(from_str(~"\"\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~"");
-
-        let mut decoder = Decoder(from_str(~"\"foo\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~"foo");
-
-        let mut decoder = Decoder(from_str(~"\"\\\"\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~"\"");
-
-        let mut decoder = Decoder(from_str(~"\"\\b\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~"\x08");
-
-        let mut decoder = Decoder(from_str(~"\"\\n\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~"\n");
-
-        let mut decoder = Decoder(from_str(~"\"\\r\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~"\r");
-
-        let mut decoder = Decoder(from_str(~"\"\\t\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~"\t");
-
-        let mut decoder = Decoder(from_str(~"\"\\u12ab\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~"\u12ab");
-
-        let mut decoder = Decoder(from_str(~"\"\\uAB12\"").unwrap());
-        let v: ~str = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~"\uAB12");
-    }
-
-    #[test]
-    fn test_read_list() {
-        assert_eq!(from_str(~"["),
-            Err(Error {line: 1u, col: 2u, msg: @~"EOF while parsing value"}));
-        assert_eq!(from_str(~"[1"),
-            Err(Error {line: 1u, col: 3u, msg: @~"EOF while parsing list"}));
-        assert_eq!(from_str(~"[1,"),
-            Err(Error {line: 1u, col: 4u, msg: @~"EOF while parsing value"}));
-        assert_eq!(from_str(~"[1,]"),
-            Err(Error {line: 1u, col: 4u, msg: @~"invalid syntax"}));
-        assert_eq!(from_str(~"[6 7]"),
-            Err(Error {line: 1u, col: 4u, msg: @~"expected `,` or `]`"}));
-
-        assert_eq!(from_str(~"[]"), Ok(List(~[])));
-        assert_eq!(from_str(~"[ ]"), Ok(List(~[])));
-        assert_eq!(from_str(~"[true]"), Ok(List(~[Boolean(true)])));
-        assert_eq!(from_str(~"[ false ]"), Ok(List(~[Boolean(false)])));
-        assert_eq!(from_str(~"[null]"), Ok(List(~[Null])));
-        assert_eq!(from_str(~"[3, 1]"),
-                     Ok(List(~[Number(3f), Number(1f)])));
-        assert_eq!(from_str(~"\n[3, 2]\n"),
-                     Ok(List(~[Number(3f), Number(2f)])));
-        assert_eq!(from_str(~"[2, [4, 1]]"),
-               Ok(List(~[Number(2f), List(~[Number(4f), Number(1f)])])));
-    }
-
-    #[test]
-    fn test_decode_list() {
-        let mut decoder = Decoder(from_str(~"[]").unwrap());
-        let v: ~[()] = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~[]);
-
-        let mut decoder = Decoder(from_str(~"[null]").unwrap());
-        let v: ~[()] = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~[()]);
-
-        let mut decoder = Decoder(from_str(~"[true]").unwrap());
-        let v: ~[bool] = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~[true]);
-
-        let mut decoder = Decoder(from_str(~"[true]").unwrap());
-        let v: ~[bool] = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~[true]);
-
-        let mut decoder = Decoder(from_str(~"[3, 1]").unwrap());
-        let v: ~[int] = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~[3, 1]);
-
-        let mut decoder = Decoder(from_str(~"[[3], [1, 2]]").unwrap());
-        let v: ~[~[uint]] = Decodable::decode(&mut decoder);
-        assert_eq!(v, ~[~[3], ~[1, 2]]);
-    }
-
-    #[test]
-    fn test_read_object() {
-        assert_eq!(from_str(~"{"),
-            Err(Error {
-                line: 1u,
-                col: 2u,
-                msg: @~"EOF while parsing object"}));
-        assert_eq!(from_str(~"{ "),
-            Err(Error {
-                line: 1u,
-                col: 3u,
-                msg: @~"EOF while parsing object"}));
-        assert_eq!(from_str(~"{1"),
-            Err(Error {
-                line: 1u,
-                col: 2u,
-                msg: @~"key must be a string"}));
-        assert_eq!(from_str(~"{ \"a\""),
-            Err(Error {
-                line: 1u,
-                col: 6u,
-                msg: @~"EOF while parsing object"}));
-        assert_eq!(from_str(~"{\"a\""),
-            Err(Error {
-                line: 1u,
-                col: 5u,
-                msg: @~"EOF while parsing object"}));
-        assert_eq!(from_str(~"{\"a\" "),
-            Err(Error {
-                line: 1u,
-                col: 6u,
-                msg: @~"EOF while parsing object"}));
-
-        assert_eq!(from_str(~"{\"a\" 1"),
-            Err(Error {line: 1u, col: 6u, msg: @~"expected `:`"}));
-        assert_eq!(from_str(~"{\"a\":"),
-            Err(Error {line: 1u, col: 6u, msg: @~"EOF while parsing value"}));
-        assert_eq!(from_str(~"{\"a\":1"),
-            Err(Error {
-                line: 1u,
-                col: 7u,
-                msg: @~"EOF while parsing object"}));
-        assert_eq!(from_str(~"{\"a\":1 1"),
-            Err(Error {line: 1u, col: 8u, msg: @~"expected `,` or `}`"}));
-        assert_eq!(from_str(~"{\"a\":1,"),
-            Err(Error {
-                line: 1u,
-                col: 8u,
-                msg: @~"EOF while parsing object"}));
-
-        assert_eq!(result::unwrap(from_str(~"{}")), mk_object(~[]));
-        assert_eq!(result::unwrap(from_str(~"{\"a\": 3}")),
-                  mk_object(~[(~"a", Number(3.0f))]));
-
-        assert_eq!(result::unwrap(from_str(
-                ~"{ \"a\": null, \"b\" : true }")),
-                  mk_object(~[
-                      (~"a", Null),
-                      (~"b", Boolean(true))]));
-        assert_eq!(result::unwrap(
-                      from_str(~"\n{ \"a\": null, \"b\" : true }\n")),
-                  mk_object(~[
-                      (~"a", Null),
-                      (~"b", Boolean(true))]));
-        assert_eq!(result::unwrap(from_str(
-                ~"{\"a\" : 1.0 ,\"b\": [ true ]}")),
-                  mk_object(~[
-                      (~"a", Number(1.0)),
-                      (~"b", List(~[Boolean(true)]))
-                  ]));
-        assert_eq!(result::unwrap(from_str(
-                      ~"{" +
-                          ~"\"a\": 1.0, " +
-                          ~"\"b\": [" +
-                              ~"true," +
-                              ~"\"foo\\nbar\", " +
-                              ~"{ \"c\": {\"d\": null} } " +
-                          ~"]" +
-                      ~"}")),
-                  mk_object(~[
-                      (~"a", Number(1.0f)),
-                      (~"b", List(~[
-                          Boolean(true),
-                          String(~"foo\nbar"),
-                          mk_object(~[
-                              (~"c", mk_object(~[(~"d", Null)]))
-                          ])
-                      ]))
-                  ]));
-    }
-
-    #[test]
-    fn test_decode_struct() {
-        let s = ~"{
-            \"inner\": [
-                { \"a\": null, \"b\": 2, \"c\": [\"abc\", \"xyz\"] }
-            ]
-        }";
-        let mut decoder = Decoder(from_str(s).unwrap());
-        let v: Outer = Decodable::decode(&mut decoder);
-        assert_eq!(
-            v,
-            Outer {
-                inner: ~[
-                    Inner { a: (), b: 2, c: ~[~"abc", ~"xyz"] }
-                ]
-            }
-        );
-    }
-
-    #[test]
-    fn test_decode_option() {
-        let mut decoder = Decoder(from_str(~"null").unwrap());
-        let value: Option<~str> = Decodable::decode(&mut decoder);
-        assert_eq!(value, None);
-
-        let mut decoder = Decoder(from_str(~"\"jodhpurs\"").unwrap());
-        let value: Option<~str> = Decodable::decode(&mut decoder);
-        assert_eq!(value, Some(~"jodhpurs"));
-    }
-
-    #[test]
-    fn test_decode_enum() {
-        let mut decoder = Decoder(from_str(~"\"Dog\"").unwrap());
-        let value: Animal = Decodable::decode(&mut decoder);
-        assert_eq!(value, Dog);
-
-        let mut decoder =
-            Decoder(from_str(~"[\"Frog\",\"Henry\",349]").unwrap());
-        let value: Animal = Decodable::decode(&mut decoder);
-        assert_eq!(value, Frog(~"Henry", 349));
-    }
-
-    #[test]
-    fn test_decode_map() {
-        let s = ~"{\"a\": \"Dog\", \"b\": [\"Frog\", \"Henry\", 349]}";
-        let mut decoder = Decoder(from_str(s).unwrap());
-        let mut map: HashMap<~str, Animal> = Decodable::decode(&mut decoder);
-
-        assert_eq!(map.pop(&~"a"), Some(Dog));
-        assert_eq!(map.pop(&~"b"), Some(Frog(~"Henry", 349)));
-    }
-
-    #[test]
-    fn test_multiline_errors() {
-        assert_eq!(from_str(~"{\n  \"foo\":\n \"bar\""),
-            Err(Error {
-                line: 3u,
-                col: 8u,
-                msg: @~"EOF while parsing object"}));
-    }
-}
diff --git a/src/libstd/kinds.rs b/src/libstd/kinds.rs
new file mode 100644
index 00000000000..d9b3e35b6b9
--- /dev/null
+++ b/src/libstd/kinds.rs
@@ -0,0 +1,53 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+The kind traits
+
+Rust types can be classified in various useful ways according to
+intrinsic properties of the type. These classifications, often called
+'kinds', are represented as traits.
+
+They cannot be implemented by user code, but are instead implemented
+by the compiler automatically for the types to which they apply.
+
+The 4 kinds are
+
+* Copy - types that may be copied without allocation. This includes
+  scalar types and managed pointers, and exludes owned pointers. It
+  also excludes types that implement `Drop`.
+
+* Owned - owned types and types containing owned types.  These types
+  may be transferred across task boundaries.
+
+* Const - types that are deeply immutable. Const types are used for
+  freezable data structures.
+
+`Copy` types include both implicitly copyable types that the compiler
+will copy automatically and non-implicitly copyable types that require
+the `copy` keyword to copy. Types that do not implement `Copy` may
+instead implement `Clone`.
+
+*/
+
+#[lang="copy"]
+pub trait Copy {
+    // Empty.
+}
+
+#[lang="owned"]
+pub trait Owned {
+    // Empty.
+}
+
+#[lang="const"]
+pub trait Const {
+    // Empty.
+}
diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs
new file mode 100644
index 00000000000..7ae3f0fd2d4
--- /dev/null
+++ b/src/libstd/libc.rs
@@ -0,0 +1,2054 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+* Bindings for the C standard library and other platform libraries
+*
+* This module contains bindings to the C standard library,
+* organized into modules by their defining standard.
+* Additionally, it contains some assorted platform-specific definitions.
+* For convenience, most functions and types are reexported from `core::libc`,
+* so `pub use core::libc::*` will import the available
+* C bindings as appropriate for the target platform. The exact
+* set of functions available are platform specific.
+*
+* *Note* Rustdoc does not indicate reexports currently. Also, because these
+* definitions are platform-specific, some may not
+* appear in the generated documentation.
+*
+* We consider the following specs reasonably normative with respect
+* to interoperating with the C standard library (libc/msvcrt):
+*
+* * ISO 9899:1990 ('C95', 'ANSI C', 'Standard C'), NA1, 1995.
+* * ISO 9899:1999 ('C99' or 'C9x').
+* * ISO 9945:1988 / IEEE 1003.1-1988 ('POSIX.1').
+* * ISO 9945:2001 / IEEE 1003.1-2001 ('POSIX:2001', 'SUSv3').
+* * ISO 9945:2008 / IEEE 1003.1-2008 ('POSIX:2008', 'SUSv4').
+*
+* Note that any reference to the 1996 revision of POSIX, or any revs
+* between 1990 (when '88 was approved at ISO) and 2001 (when the next
+* actual revision-revision happened), are merely additions of other
+* chapters (1b and 1c) outside the core interfaces.
+*
+* Despite having several names each, these are *reasonably* coherent
+* point-in-time, list-of-definition sorts of specs. You can get each under a
+* variety of names but will wind up with the same definition in each case.
+*
+* See standards(7) in linux-manpages for more details.
+*
+* Our interface to these libraries is complicated by the non-universality of
+* conformance to any of them. About the only thing universally supported is
+* the first (C95), beyond that definitions quickly become absent on various
+* platforms.
+*
+* We therefore wind up dividing our module-space up (mostly for the sake of
+* sanity while editing, filling-in-details and eliminating duplication) into
+* definitions common-to-all (held in modules named c95, c99, posix88, posix01
+* and posix08) and definitions that appear only on *some* platforms (named
+* 'extra'). This would be things like significant OSX foundation kit, or
+* win32 library kernel32.dll, or various fancy glibc, linux or BSD
+* extensions.
+*
+* In addition to the per-platform 'extra' modules, we define a module of
+* 'common BSD' libc routines that never quite made it into POSIX but show up
+* in multiple derived systems. This is the 4.4BSD r2 / 1995 release, the
+* final one from Berkeley after the lawsuits died down and the CSRG
+* dissolved.
+*/
+
+#[allow(non_camel_case_types)];
+
+// Initial glob-exports mean that all the contents of all the modules
+// wind up exported, if you're interested in writing platform-specific code.
+
+pub use libc::types::common::c95::*;
+pub use libc::types::common::c99::*;
+pub use libc::types::common::posix88::*;
+pub use libc::types::common::posix01::*;
+pub use libc::types::common::posix08::*;
+pub use libc::types::common::bsd44::*;
+pub use libc::types::os::common::posix01::*;
+pub use libc::types::os::arch::c95::*;
+pub use libc::types::os::arch::c99::*;
+pub use libc::types::os::arch::posix88::*;
+pub use libc::types::os::arch::posix01::*;
+pub use libc::types::os::arch::posix08::*;
+pub use libc::types::os::arch::bsd44::*;
+pub use libc::types::os::arch::extra::*;
+
+pub use libc::consts::os::c95::*;
+pub use libc::consts::os::c99::*;
+pub use libc::consts::os::posix88::*;
+pub use libc::consts::os::posix01::*;
+pub use libc::consts::os::posix08::*;
+pub use libc::consts::os::bsd44::*;
+pub use libc::consts::os::extra::*;
+
+pub use libc::funcs::c95::ctype::*;
+pub use libc::funcs::c95::stdio::*;
+pub use libc::funcs::c95::stdlib::*;
+pub use libc::funcs::c95::string::*;
+
+pub use libc::funcs::posix88::stat_::*;
+pub use libc::funcs::posix88::stdio::*;
+pub use libc::funcs::posix88::fcntl::*;
+pub use libc::funcs::posix88::dirent::*;
+pub use libc::funcs::posix88::unistd::*;
+
+pub use libc::funcs::posix01::stat_::*;
+pub use libc::funcs::posix01::unistd::*;
+pub use libc::funcs::posix01::glob::*;
+pub use libc::funcs::posix08::unistd::*;
+
+pub use libc::funcs::bsd44::*;
+pub use libc::funcs::extra::*;
+
+#[cfg(target_os = "win32")]
+pub use libc::funcs::extra::kernel32::*;
+#[cfg(target_os = "win32")]
+pub use libc::funcs::extra::msvcrt::*;
+
+// Explicit export lists for the intersection (provided here) mean that
+// you can write more-platform-agnostic code if you stick to just these
+// symbols.
+
+pub use libc::types::common::c95::{FILE, c_void, fpos_t};
+pub use libc::types::common::posix88::{DIR, dirent_t};
+pub use libc::types::os::arch::c95::{c_char, c_double, c_float, c_int};
+pub use libc::types::os::arch::c95::{c_long, c_short, c_uchar, c_ulong};
+pub use libc::types::os::arch::c95::{c_ushort, clock_t, ptrdiff_t};
+pub use libc::types::os::arch::c95::{size_t, time_t};
+pub use libc::types::os::arch::c99::{c_longlong, c_ulonglong, intptr_t};
+pub use libc::types::os::arch::c99::{uintptr_t};
+pub use libc::types::os::arch::posix88::{dev_t, dirent_t, ino_t, mode_t};
+pub use libc::types::os::arch::posix88::{off_t, pid_t, ssize_t};
+
+pub use libc::consts::os::c95::{_IOFBF, _IOLBF, _IONBF, BUFSIZ, EOF};
+pub use libc::consts::os::c95::{EXIT_FAILURE, EXIT_SUCCESS};
+pub use libc::consts::os::c95::{FILENAME_MAX, FOPEN_MAX, L_tmpnam};
+pub use libc::consts::os::c95::{RAND_MAX, SEEK_CUR, SEEK_END};
+pub use libc::consts::os::c95::{SEEK_SET, TMP_MAX};
+pub use libc::consts::os::posix88::{F_OK, O_APPEND, O_CREAT, O_EXCL};
+pub use libc::consts::os::posix88::{O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY};
+pub use libc::consts::os::posix88::{R_OK, S_IEXEC, S_IFBLK, S_IFCHR};
+pub use libc::consts::os::posix88::{S_IFDIR, S_IFIFO, S_IFMT, S_IFREG};
+pub use libc::consts::os::posix88::{S_IREAD, S_IRUSR, S_IRWXU, S_IWUSR};
+pub use libc::consts::os::posix88::{STDERR_FILENO, STDIN_FILENO};
+pub use libc::consts::os::posix88::{STDOUT_FILENO, W_OK, X_OK};
+
+pub use libc::funcs::c95::ctype::{isalnum, isalpha, iscntrl, isdigit};
+pub use libc::funcs::c95::ctype::{islower, isprint, ispunct, isspace};
+pub use libc::funcs::c95::ctype::{isupper, isxdigit, tolower, toupper};
+
+pub use libc::funcs::c95::stdio::{fclose, feof, ferror, fflush, fgetc};
+pub use libc::funcs::c95::stdio::{fgetpos, fgets, fopen, fputc, fputs};
+pub use libc::funcs::c95::stdio::{fread, freopen, fseek, fsetpos, ftell};
+pub use libc::funcs::c95::stdio::{fwrite, perror, puts, remove, rewind};
+pub use libc::funcs::c95::stdio::{setbuf, setvbuf, tmpfile, ungetc};
+
+pub use libc::funcs::c95::stdlib::{abort, abs, atof, atoi, calloc, exit};
+pub use libc::funcs::c95::stdlib::{free, getenv, labs, malloc, rand};
+pub use libc::funcs::c95::stdlib::{realloc, srand, strtod, strtol};
+pub use libc::funcs::c95::stdlib::{strtoul, system};
+
+pub use libc::funcs::c95::string::{memchr, memcmp, memcpy, memmove};
+pub use libc::funcs::c95::string::{memset, strcat, strchr, strcmp};
+pub use libc::funcs::c95::string::{strcoll, strcpy, strcspn, strerror};
+pub use libc::funcs::c95::string::{strlen, strncat, strncmp, strncpy};
+pub use libc::funcs::c95::string::{strpbrk, strrchr, strspn, strstr};
+pub use libc::funcs::c95::string::{strtok, strxfrm};
+
+pub use libc::funcs::posix88::fcntl::{open, creat};
+pub use libc::funcs::posix88::stat_::{chmod, fstat, mkdir, stat};
+pub use libc::funcs::posix88::stdio::{fdopen, fileno, pclose, popen};
+pub use libc::funcs::posix88::unistd::{access, chdir, close, dup, dup2};
+pub use libc::funcs::posix88::unistd::{execv, execve, execvp, getcwd};
+pub use libc::funcs::posix88::unistd::{getpid, isatty, lseek, pipe, read};
+pub use libc::funcs::posix88::unistd::{rmdir, unlink, write};
+
+
+pub mod types {
+
+    // Types tend to vary *per architecture* so we pull their definitions out
+    // into this module.
+
+    // Standard types that are opaque or common, so are not per-target.
+    pub mod common {
+        pub mod c95 {
+            pub enum c_void {}
+            pub enum FILE {}
+            pub enum fpos_t {}
+        }
+        pub mod c99 {
+            pub type int8_t = i8;
+            pub type int16_t = i16;
+            pub type int32_t = i32;
+            pub type int64_t = i64;
+            pub type uint8_t = u8;
+            pub type uint16_t = u16;
+            pub type uint32_t = u32;
+            pub type uint64_t = u64;
+        }
+        pub mod posix88 {
+            pub enum DIR {}
+            pub enum dirent_t {}
+        }
+        pub mod posix01 {}
+        pub mod posix08 {}
+        pub mod bsd44 {}
+    }
+
+    // Standard types that are scalar but vary by OS and arch.
+
+    #[cfg(target_os = "linux")]
+    #[cfg(target_os = "android")]
+    pub mod os {
+        pub mod common {
+            pub mod posix01 {
+                use libc::types::common::c95::{c_void};
+                use libc::types::os::arch::c95::{c_char, size_t};
+                pub struct glob_t {
+                    gl_pathc: size_t,
+                    gl_pathv: **c_char,
+                    gl_offs:  size_t,
+
+                    __unused1: *c_void,
+                    __unused2: *c_void,
+                    __unused3: *c_void,
+                    __unused4: *c_void,
+                    __unused5: *c_void,
+                }
+            }
+        }
+
+        #[cfg(target_arch = "x86")]
+        #[cfg(target_arch = "arm")]
+        #[cfg(target_arch = "mips")]
+        pub mod arch {
+            pub mod c95 {
+                pub type c_char = i8;
+                pub type c_schar = i8;
+                pub type c_uchar = u8;
+                pub type c_short = i16;
+                pub type c_ushort = u16;
+                pub type c_int = i32;
+                pub type c_uint = u32;
+                pub type c_long = i32;
+                pub type c_ulong = u32;
+                pub type c_float = f32;
+                pub type c_double = f64;
+                pub type size_t = u32;
+                pub type ptrdiff_t = i32;
+                pub type clock_t = i32;
+                pub type time_t = i32;
+                pub type wchar_t = i32;
+            }
+            pub mod c99 {
+                pub type c_longlong = i64;
+                pub type c_ulonglong = u64;
+                pub type intptr_t = int;
+                pub type uintptr_t = uint;
+            }
+            pub mod posix88 {
+                pub type off_t = i32;
+                pub type dev_t = u64;
+                pub type ino_t = u32;
+                pub type pid_t = i32;
+                pub type uid_t = u32;
+                pub type gid_t = u32;
+                pub type useconds_t = u32;
+                pub type mode_t = u32;
+                pub type ssize_t = i32;
+            }
+            pub mod posix01 {
+                use libc::types::os::arch::c95::{c_short, c_long, c_ulong, time_t};
+                use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
+                use libc::types::os::arch::posix88::{mode_t, off_t};
+                use libc::types::os::arch::posix88::{uid_t};
+
+                pub type nlink_t = u32;
+                pub type blksize_t = i32;
+                pub type blkcnt_t = i32;
+
+                #[cfg(target_arch = "x86")]
+                #[cfg(target_arch = "arm")]
+                pub struct stat {
+                    st_dev: dev_t,
+                    __pad1: c_short,
+                    st_ino: ino_t,
+                    st_mode: mode_t,
+                    st_nlink: nlink_t,
+                    st_uid: uid_t,
+                    st_gid: gid_t,
+                    st_rdev: dev_t,
+                    __pad2: c_short,
+                    st_size: off_t,
+                    st_blksize: blksize_t,
+                    st_blocks: blkcnt_t,
+                    st_atime: time_t,
+                    st_atime_nsec: c_long,
+                    st_mtime: time_t,
+                    st_mtime_nsec: c_long,
+                    st_ctime: time_t,
+                    st_ctime_nsec: c_long,
+                    __unused4: c_long,
+                    __unused5: c_long,
+                }
+
+                #[cfg(target_arch = "mips")]
+                pub struct stat {
+                    st_dev: c_ulong,
+                    st_pad1: [c_long, ..3],
+                    st_ino: ino_t,
+                    st_mode: mode_t,
+                    st_nlink: nlink_t,
+                    st_uid: uid_t,
+                    st_gid: gid_t,
+                    st_rdev: c_ulong,
+                    st_pad2: [c_long, ..2],
+                    st_size: off_t,
+                    st_pad3: c_long,
+                    st_atime: time_t,
+                    st_atime_nsec: c_long,
+                    st_mtime: time_t,
+                    st_mtime_nsec: c_long,
+                    st_ctime: time_t,
+                    st_ctime_nsec: c_long,
+                    st_blksize: blksize_t,
+                    st_blocks: blkcnt_t,
+                    st_pad5: [c_long, ..14],
+                }
+            }
+            pub mod posix08 {}
+            pub mod bsd44 {}
+            pub mod extra {}
+        }
+
+        #[cfg(target_arch = "x86_64")]
+        pub mod arch {
+            pub mod c95 {
+                pub type c_char = i8;
+                pub type c_schar = i8;
+                pub type c_uchar = u8;
+                pub type c_short = i16;
+                pub type c_ushort = u16;
+                pub type c_int = i32;
+                pub type c_uint = u32;
+                pub type c_long = i64;
+                pub type c_ulong = u64;
+                pub type c_float = f32;
+                pub type c_double = f64;
+                pub type size_t = u64;
+                pub type ptrdiff_t = i64;
+                pub type clock_t = i64;
+                pub type time_t = i64;
+                pub type wchar_t = i32;
+            }
+            pub mod c99 {
+                pub type c_longlong = i64;
+                pub type c_ulonglong = u64;
+                pub type intptr_t = int;
+                pub type uintptr_t = uint;
+            }
+            pub mod posix88 {
+                pub type off_t = i64;
+                pub type dev_t = u64;
+                pub type ino_t = u64;
+                pub type pid_t = i32;
+                pub type uid_t = u32;
+                pub type gid_t = u32;
+                pub type useconds_t = u32;
+                pub type mode_t = u32;
+                pub type ssize_t = i64;
+            }
+            pub mod posix01 {
+                use libc::types::os::arch::c95::{c_int, c_long, time_t};
+                use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
+                use libc::types::os::arch::posix88::{mode_t, off_t};
+                use libc::types::os::arch::posix88::{uid_t};
+
+                pub type nlink_t = u64;
+                pub type blksize_t = i64;
+                pub type blkcnt_t = i64;
+                pub struct stat {
+                    st_dev: dev_t,
+                    st_ino: ino_t,
+                    st_nlink: nlink_t,
+                    st_mode: mode_t,
+                    st_uid: uid_t,
+                    st_gid: gid_t,
+                    __pad0: c_int,
+                    st_rdev: dev_t,
+                    st_size: off_t,
+                    st_blksize: blksize_t,
+                    st_blocks: blkcnt_t,
+                    st_atime: time_t,
+                    st_atime_nsec: c_long,
+                    st_mtime: time_t,
+                    st_mtime_nsec: c_long,
+                    st_ctime: time_t,
+                    st_ctime_nsec: c_long,
+                    __unused: [c_long, ..3],
+                }
+            }
+            pub mod posix08 {
+            }
+            pub mod bsd44 {
+            }
+            pub mod extra {
+            }
+        }
+    }
+
+    #[cfg(target_os = "freebsd")]
+    pub mod os {
+        pub mod common {
+            pub mod posix01 {
+                use libc::types::common::c95::{c_void};
+                use libc::types::os::arch::c95::{c_char, c_int, size_t};
+                pub struct glob_t {
+                    gl_pathc:  size_t,
+                    __unused1: size_t,
+                    gl_offs:   size_t,
+                    __unused2: c_int,
+                    gl_pathv:  **c_char,
+
+                    __unused3: *c_void,
+
+                    __unused4: *c_void,
+                    __unused5: *c_void,
+                    __unused6: *c_void,
+                    __unused7: *c_void,
+                    __unused8: *c_void,
+                }
+            }
+        }
+
+        #[cfg(target_arch = "x86_64")]
+        pub mod arch {
+            pub mod c95 {
+                pub type c_char = i8;
+                pub type c_schar = i8;
+                pub type c_uchar = u8;
+                pub type c_short = i16;
+                pub type c_ushort = u16;
+                pub type c_int = i32;
+                pub type c_uint = u32;
+                pub type c_long = i64;
+                pub type c_ulong = u64;
+                pub type c_float = f32;
+                pub type c_double = f64;
+                pub type size_t = u64;
+                pub type ptrdiff_t = i64;
+                pub type clock_t = i32;
+                pub type time_t = i64;
+                pub type wchar_t = i32;
+            }
+            pub mod c99 {
+                pub type c_longlong = i64;
+                pub type c_ulonglong = u64;
+                pub type intptr_t = int;
+                pub type uintptr_t = uint;
+            }
+            pub mod posix88 {
+                pub type off_t = i64;
+                pub type dev_t = u32;
+                pub type ino_t = u32;
+                pub type pid_t = i32;
+                pub type uid_t = u32;
+                pub type gid_t = u32;
+                pub type useconds_t = u32;
+                pub type mode_t = u16;
+                pub type ssize_t = i64;
+            }
+            pub mod posix01 {
+                use libc::types::common::c99::{uint8_t, uint32_t, int32_t};
+                use libc::types::os::arch::c95::{c_long, time_t};
+                use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
+                use libc::types::os::arch::posix88::{mode_t, off_t};
+                use libc::types::os::arch::posix88::{uid_t};
+
+                pub type nlink_t = u16;
+                pub type blksize_t = i64;
+                pub type blkcnt_t = i64;
+                pub type fflags_t = u32;
+                pub struct stat {
+                    st_dev: dev_t,
+                    st_ino: ino_t,
+                    st_mode: mode_t,
+                    st_nlink: nlink_t,
+                    st_uid: uid_t,
+                    st_gid: gid_t,
+                    st_rdev: dev_t,
+                    st_atime: time_t,
+                    st_atime_nsec: c_long,
+                    st_mtime: time_t,
+                    st_mtime_nsec: c_long,
+                    st_ctime: time_t,
+                    st_ctime_nsec: c_long,
+                    st_size: off_t,
+                    st_blocks: blkcnt_t,
+                    st_blksize: blksize_t,
+                    st_flags: fflags_t,
+                    st_gen: uint32_t,
+                    st_lspare: int32_t,
+                    st_birthtime: time_t,
+                    st_birthtime_nsec: c_long,
+                    __unused: [uint8_t, ..2],
+                }
+            }
+            pub mod posix08 {
+            }
+            pub mod bsd44 {
+            }
+            pub mod extra {
+            }
+        }
+    }
+
+    #[cfg(target_os = "win32")]
+    pub mod os {
+        pub mod common {
+            pub mod posix01 {
+                use libc::types::os::arch::c95::{c_int, c_short};
+                use libc::types::os::arch::extra::{int64, time64_t};
+                use libc::types::os::arch::posix88::{dev_t, ino_t};
+                use libc::types::os::arch::posix88::mode_t;
+
+                // Note: this is the struct called stat64 in win32. Not stat,
+                // nor stati64.
+                pub struct stat {
+                    st_dev: dev_t,
+                    st_ino: ino_t,
+                    st_mode: mode_t,
+                    st_nlink: c_short,
+                    st_uid: c_short,
+                    st_gid: c_short,
+                    st_rdev: dev_t,
+                    st_size: int64,
+                    st_atime: time64_t,
+                    st_mtime: time64_t,
+                    st_ctime: time64_t,
+                }
+            }
+        }
+
+        #[cfg(target_arch = "x86")]
+        pub mod arch {
+            pub mod c95 {
+                pub type c_char = i8;
+                pub type c_schar = i8;
+                pub type c_uchar = u8;
+                pub type c_short = i16;
+                pub type c_ushort = u16;
+                pub type c_int = i32;
+                pub type c_uint = u32;
+                pub type c_long = i32;
+                pub type c_ulong = u32;
+                pub type c_float = f32;
+                pub type c_double = f64;
+                pub type size_t = u32;
+                pub type ptrdiff_t = i32;
+                pub type clock_t = i32;
+                pub type time_t = i32;
+                pub type wchar_t = u16;
+            }
+            pub mod c99 {
+                pub type c_longlong = i64;
+                pub type c_ulonglong = u64;
+                pub type intptr_t = int;
+                pub type uintptr_t = uint;
+            }
+            pub mod posix88 {
+                pub type off_t = i32;
+                pub type dev_t = u32;
+                pub type ino_t = i16;
+                pub type pid_t = i32;
+                pub type useconds_t = u32;
+                pub type mode_t = u16;
+                pub type ssize_t = i32;
+            }
+            pub mod posix01 {
+            }
+            pub mod posix08 {
+            }
+            pub mod bsd44 {
+            }
+            pub mod extra {
+                use libc::types::common::c95::c_void;
+                use libc::types::os::arch::c95::{c_char, c_int, c_uint};
+                use libc::types::os::arch::c95::{c_long, c_ulong};
+                use libc::types::os::arch::c95::{wchar_t};
+                use libc::types::os::arch::c99::{c_ulonglong};
+
+                pub type BOOL = c_int;
+                pub type BYTE = u8;
+                pub type CCHAR = c_char;
+                pub type CHAR = c_char;
+
+                pub type DWORD = c_ulong;
+                pub type DWORDLONG = c_ulonglong;
+
+                pub type HANDLE = LPVOID;
+                pub type HMODULE = c_uint;
+
+                pub type LONG_PTR = c_long;
+
+                pub type LPCWSTR = *WCHAR;
+                pub type LPCSTR = *CHAR;
+                pub type LPCTSTR = *CHAR;
+                pub type LPTCH = *CHAR;
+
+                pub type LPWSTR = *mut WCHAR;
+                pub type LPSTR = *mut CHAR;
+                pub type LPTSTR = *mut CHAR;
+
+                // Not really, but opaque to us.
+                pub type LPSECURITY_ATTRIBUTES = LPVOID;
+
+                pub type LPVOID = *mut c_void;
+                pub type LPBYTE = *mut BYTE;
+                pub type LPWORD = *mut WORD;
+                pub type LPDWORD = *mut DWORD;
+                pub type LPHANDLE = *mut HANDLE;
+
+                pub type LRESULT = LONG_PTR;
+                pub type PBOOL = *mut BOOL;
+                pub type WCHAR = wchar_t;
+                pub type WORD = u16;
+
+                pub type time64_t = i64;
+                pub type int64 = i64;
+
+                pub struct STARTUPINFO {
+                    cb: DWORD,
+                    lpReserved: LPTSTR,
+                    lpDesktop: LPTSTR,
+                    lpTitle: LPTSTR,
+                    dwX: DWORD,
+                    dwY: DWORD,
+                    dwXSize: DWORD,
+                    dwYSize: DWORD,
+                    dwXCountChars: DWORD,
+                    dwYCountCharts: DWORD,
+                    dwFillAttribute: DWORD,
+                    dwFlags: DWORD,
+                    wShowWindow: WORD,
+                    cbReserved2: WORD,
+                    lpReserved2: LPBYTE,
+                    hStdInput: HANDLE,
+                    hStdOutput: HANDLE,
+                    hStdError: HANDLE
+                }
+                pub type LPSTARTUPINFO = *mut STARTUPINFO;
+
+                pub struct PROCESS_INFORMATION {
+                    hProcess: HANDLE,
+                    hThread: HANDLE,
+                    dwProcessId: DWORD,
+                    dwThreadId: DWORD
+                }
+                pub type LPPROCESS_INFORMATION = *mut PROCESS_INFORMATION;
+            }
+        }
+    }
+
+    #[cfg(target_os = "macos")]
+    pub mod os {
+        pub mod common {
+            pub mod posix01 {
+                use libc::types::common::c95::{c_void};
+                use libc::types::os::arch::c95::{c_char, c_int, size_t};
+                pub struct glob_t {
+                    gl_pathc:  size_t,
+                    __unused1: c_int,
+                    gl_offs:   size_t,
+                    __unused2: c_int,
+                    gl_pathv:  **c_char,
+
+                    __unused3: *c_void,
+
+                    __unused4: *c_void,
+                    __unused5: *c_void,
+                    __unused6: *c_void,
+                    __unused7: *c_void,
+                    __unused8: *c_void,
+                }
+            }
+        }
+
+        #[cfg(target_arch = "x86")]
+        pub mod arch {
+            pub mod c95 {
+                pub type c_char = i8;
+                pub type c_schar = i8;
+                pub type c_uchar = u8;
+                pub type c_short = i16;
+                pub type c_ushort = u16;
+                pub type c_int = i32;
+                pub type c_uint = u32;
+                pub type c_long = i32;
+                pub type c_ulong = u32;
+                pub type c_float = f32;
+                pub type c_double = f64;
+                pub type size_t = u32;
+                pub type ptrdiff_t = i32;
+                pub type clock_t = u32;
+                pub type time_t = i32;
+                pub type wchar_t = i32;
+            }
+            pub mod c99 {
+                pub type c_longlong = i64;
+                pub type c_ulonglong = u64;
+                pub type intptr_t = int;
+                pub type uintptr_t = uint;
+            }
+            pub mod posix88 {
+                pub type off_t = i64;
+                pub type dev_t = i32;
+                pub type ino_t = u64;
+                pub type pid_t = i32;
+                pub type uid_t = u32;
+                pub type gid_t = u32;
+                pub type useconds_t = u32;
+                pub type mode_t = u16;
+                pub type ssize_t = i32;
+            }
+            pub mod posix01 {
+                use libc::types::common::c99::{int32_t, int64_t, uint32_t};
+                use libc::types::os::arch::c95::{c_long, time_t};
+                use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t,
+                                                     mode_t, off_t, uid_t};
+
+                pub type nlink_t = u16;
+                pub type blksize_t = i64;
+                pub type blkcnt_t = i32;
+
+                pub struct stat {
+                    st_dev: dev_t,
+                    st_mode: mode_t,
+                    st_nlink: nlink_t,
+                    st_ino: ino_t,
+                    st_uid: uid_t,
+                    st_gid: gid_t,
+                    st_rdev: dev_t,
+                    st_atime: time_t,
+                    st_atime_nsec: c_long,
+                    st_mtime: time_t,
+                    st_mtime_nsec: c_long,
+                    st_ctime: time_t,
+                    st_ctime_nsec: c_long,
+                    st_birthtime: time_t,
+                    st_birthtime_nsec: c_long,
+                    st_size: off_t,
+                    st_blocks: blkcnt_t,
+                    st_blksize: blksize_t,
+                    st_flags: uint32_t,
+                    st_gen: uint32_t,
+                    st_lspare: int32_t,
+                    st_qspare: [int64_t, ..2],
+                }
+            }
+            pub mod posix08 {
+            }
+            pub mod bsd44 {
+            }
+            pub mod extra {
+            }
+        }
+
+        #[cfg(target_arch = "x86_64")]
+        pub mod arch {
+            pub mod c95 {
+                pub type c_char = i8;
+                pub type c_schar = i8;
+                pub type c_uchar = u8;
+                pub type c_short = i16;
+                pub type c_ushort = u16;
+                pub type c_int = i32;
+                pub type c_uint = u32;
+                pub type c_long = i64;
+                pub type c_ulong = u64;
+                pub type c_float = f32;
+                pub type c_double = f64;
+                pub type size_t = u64;
+                pub type ptrdiff_t = i64;
+                pub type clock_t = u64;
+                pub type time_t = i64;
+                pub type wchar_t = i32;
+            }
+            pub mod c99 {
+                pub type c_longlong = i64;
+                pub type c_ulonglong = u64;
+                pub type intptr_t = int;
+                pub type uintptr_t = uint;
+            }
+            pub mod posix88 {
+                pub type off_t = i64;
+                pub type dev_t = i32;
+                pub type ino_t = u64;
+                pub type pid_t = i32;
+                pub type uid_t = u32;
+                pub type gid_t = u32;
+                pub type useconds_t = u32;
+                pub type mode_t = u16;
+                pub type ssize_t = i64;
+            }
+            pub mod posix01 {
+                use libc::types::common::c99::{int32_t, int64_t};
+                use libc::types::common::c99::{uint32_t};
+                use libc::types::os::arch::c95::{c_long, time_t};
+                use libc::types::os::arch::posix88::{dev_t, gid_t, ino_t};
+                use libc::types::os::arch::posix88::{mode_t, off_t, uid_t};
+
+                pub type nlink_t = u16;
+                pub type blksize_t = i64;
+                pub type blkcnt_t = i32;
+
+                pub struct stat {
+                    st_dev: dev_t,
+                    st_mode: mode_t,
+                    st_nlink: nlink_t,
+                    st_ino: ino_t,
+                    st_uid: uid_t,
+                    st_gid: gid_t,
+                    st_rdev: dev_t,
+                    st_atime: time_t,
+                    st_atime_nsec: c_long,
+                    st_mtime: time_t,
+                    st_mtime_nsec: c_long,
+                    st_ctime: time_t,
+                    st_ctime_nsec: c_long,
+                    st_birthtime: time_t,
+                    st_birthtime_nsec: c_long,
+                    st_size: off_t,
+                    st_blocks: blkcnt_t,
+                    st_blksize: blksize_t,
+                    st_flags: uint32_t,
+                    st_gen: uint32_t,
+                    st_lspare: int32_t,
+                    st_qspare: [int64_t, ..2],
+                }
+            }
+            pub mod posix08 {
+            }
+            pub mod bsd44 {
+            }
+            pub mod extra {
+            }
+        }
+    }
+}
+
+pub mod consts {
+    // Consts tend to vary per OS so we pull their definitions out
+    // into this module.
+
+    #[cfg(target_os = "win32")]
+    pub mod os {
+        pub mod c95 {
+            pub static EXIT_FAILURE : int = 1;
+            pub static EXIT_SUCCESS : int = 0;
+            pub static RAND_MAX : int = 32767;
+            pub static EOF : int = -1;
+            pub static SEEK_SET : int = 0;
+            pub static SEEK_CUR : int = 1;
+            pub static SEEK_END : int = 2;
+            pub static _IOFBF : int = 0;
+            pub static _IONBF : int = 4;
+            pub static _IOLBF : int = 64;
+            pub static BUFSIZ : uint = 512_u;
+            pub static FOPEN_MAX : uint = 20_u;
+            pub static FILENAME_MAX : uint = 260_u;
+            pub static L_tmpnam : uint = 16_u;
+            pub static TMP_MAX : uint = 32767_u;
+        }
+        pub mod c99 {
+        }
+        pub mod posix88 {
+            pub static O_RDONLY : int = 0;
+            pub static O_WRONLY : int = 1;
+            pub static O_RDWR : int = 2;
+            pub static O_APPEND : int = 8;
+            pub static O_CREAT : int = 256;
+            pub static O_EXCL : int = 1024;
+            pub static O_TRUNC : int = 512;
+            pub static S_IFIFO : int = 4096;
+            pub static S_IFCHR : int = 8192;
+            pub static S_IFBLK : int = 12288;
+            pub static S_IFDIR : int = 16384;
+            pub static S_IFREG : int = 32768;
+            pub static S_IFMT : int = 61440;
+            pub static S_IEXEC : int = 64;
+            pub static S_IWRITE : int = 128;
+            pub static S_IREAD : int = 256;
+            pub static S_IRWXU : int = 448;
+            pub static S_IXUSR : int = 64;
+            pub static S_IWUSR : int = 128;
+            pub static S_IRUSR : int = 256;
+            pub static F_OK : int = 0;
+            pub static R_OK : int = 4;
+            pub static W_OK : int = 2;
+            pub static X_OK : int = 1;
+            pub static STDIN_FILENO : int = 0;
+            pub static STDOUT_FILENO : int = 1;
+            pub static STDERR_FILENO : int = 2;
+        }
+        pub mod posix01 {
+        }
+        pub mod posix08 {
+        }
+        pub mod bsd44 {
+        }
+        pub mod extra {
+            use libc::types::os::arch::extra::{DWORD, BOOL};
+
+            pub static TRUE : BOOL = 1;
+            pub static FALSE : BOOL = 0;
+
+            pub static O_TEXT : int = 16384;
+            pub static O_BINARY : int = 32768;
+            pub static O_NOINHERIT: int = 128;
+
+            pub static ERROR_SUCCESS : int = 0;
+            pub static ERROR_INSUFFICIENT_BUFFER : int = 122;
+            pub static INVALID_HANDLE_VALUE: int = -1;
+
+            pub static DELETE : DWORD = 0x00010000;
+            pub static READ_CONTROL : DWORD = 0x00020000;
+            pub static SYNCHRONIZE : DWORD = 0x00100000;
+            pub static WRITE_DAC : DWORD = 0x00040000;
+            pub static WRITE_OWNER : DWORD = 0x00080000;
+
+            pub static PROCESS_CREATE_PROCESS : DWORD = 0x0080;
+            pub static PROCESS_CREATE_THREAD : DWORD = 0x0002;
+            pub static PROCESS_DUP_HANDLE : DWORD = 0x0040;
+            pub static PROCESS_QUERY_INFORMATION : DWORD = 0x0400;
+            pub static PROCESS_QUERY_LIMITED_INFORMATION : DWORD = 0x1000;
+            pub static PROCESS_SET_INFORMATION : DWORD = 0x0200;
+            pub static PROCESS_SET_QUOTA : DWORD = 0x0100;
+            pub static PROCESS_SUSPEND_RESUME : DWORD = 0x0800;
+            pub static PROCESS_TERMINATE : DWORD = 0x0001;
+            pub static PROCESS_VM_OPERATION : DWORD = 0x0008;
+            pub static PROCESS_VM_READ : DWORD = 0x0010;
+            pub static PROCESS_VM_WRITE : DWORD = 0x0020;
+
+            pub static STARTF_FORCEONFEEDBACK : DWORD = 0x00000040;
+            pub static STARTF_FORCEOFFFEEDBACK : DWORD = 0x00000080;
+            pub static STARTF_PREVENTPINNING : DWORD = 0x00002000;
+            pub static STARTF_RUNFULLSCREEN : DWORD = 0x00000020;
+            pub static STARTF_TITLEISAPPID : DWORD = 0x00001000;
+            pub static STARTF_TITLEISLINKNAME : DWORD = 0x00000800;
+            pub static STARTF_USECOUNTCHARS : DWORD = 0x00000008;
+            pub static STARTF_USEFILLATTRIBUTE : DWORD = 0x00000010;
+            pub static STARTF_USEHOTKEY : DWORD = 0x00000200;
+            pub static STARTF_USEPOSITION : DWORD = 0x00000004;
+            pub static STARTF_USESHOWWINDOW : DWORD = 0x00000001;
+            pub static STARTF_USESIZE : DWORD = 0x00000002;
+            pub static STARTF_USESTDHANDLES : DWORD = 0x00000100;
+
+            pub static WAIT_ABANDONED : DWORD = 0x00000080;
+            pub static WAIT_OBJECT_0 : DWORD = 0x00000000;
+            pub static WAIT_TIMEOUT : DWORD = 0x00000102;
+            pub static WAIT_FAILED : DWORD = -1;
+
+            pub static DUPLICATE_CLOSE_SOURCE : DWORD = 0x00000001;
+            pub static DUPLICATE_SAME_ACCESS : DWORD = 0x00000002;
+
+            pub static INFINITE : DWORD = -1;
+            pub static STILL_ACTIVE : DWORD = 259;
+        }
+    }
+
+
+    #[cfg(target_os = "linux")]
+    #[cfg(target_os = "android")]
+    pub mod os {
+        pub mod c95 {
+            pub static EXIT_FAILURE : int = 1;
+            pub static EXIT_SUCCESS : int = 0;
+            pub static RAND_MAX : int = 2147483647;
+            pub static EOF : int = -1;
+            pub static SEEK_SET : int = 0;
+            pub static SEEK_CUR : int = 1;
+            pub static SEEK_END : int = 2;
+            pub static _IOFBF : int = 0;
+            pub static _IONBF : int = 2;
+            pub static _IOLBF : int = 1;
+            pub static BUFSIZ : uint = 8192_u;
+            pub static FOPEN_MAX : uint = 16_u;
+            pub static FILENAME_MAX : uint = 4096_u;
+            pub static L_tmpnam : uint = 20_u;
+            pub static TMP_MAX : uint = 238328_u;
+        }
+        pub mod c99 {
+        }
+        #[cfg(target_arch = "x86")]
+        #[cfg(target_arch = "x86_64")]
+        #[cfg(target_arch = "arm")]
+        pub mod posix88 {
+            pub static O_RDONLY : int = 0;
+            pub static O_WRONLY : int = 1;
+            pub static O_RDWR : int = 2;
+            pub static O_APPEND : int = 1024;
+            pub static O_CREAT : int = 64;
+            pub static O_EXCL : int = 128;
+            pub static O_TRUNC : int = 512;
+            pub static S_IFIFO : int = 4096;
+            pub static S_IFCHR : int = 8192;
+            pub static S_IFBLK : int = 24576;
+            pub static S_IFDIR : int = 16384;
+            pub static S_IFREG : int = 32768;
+            pub static S_IFMT : int = 61440;
+            pub static S_IEXEC : int = 64;
+            pub static S_IWRITE : int = 128;
+            pub static S_IREAD : int = 256;
+            pub static S_IRWXU : int = 448;
+            pub static S_IXUSR : int = 64;
+            pub static S_IWUSR : int = 128;
+            pub static S_IRUSR : int = 256;
+            pub static F_OK : int = 0;
+            pub static R_OK : int = 4;
+            pub static W_OK : int = 2;
+            pub static X_OK : int = 1;
+            pub static STDIN_FILENO : int = 0;
+            pub static STDOUT_FILENO : int = 1;
+            pub static STDERR_FILENO : int = 2;
+            pub static F_LOCK : int = 1;
+            pub static F_TEST : int = 3;
+            pub static F_TLOCK : int = 2;
+            pub static F_ULOCK : int = 0;
+            pub static SIGHUP : int = 1;
+            pub static SIGINT : int = 2;
+            pub static SIGQUIT : int = 3;
+            pub static SIGILL : int = 4;
+            pub static SIGABRT : int = 6;
+            pub static SIGFPE : int = 8;
+            pub static SIGKILL : int = 9;
+            pub static SIGSEGV : int = 11;
+            pub static SIGPIPE : int = 13;
+            pub static SIGALRM : int = 14;
+            pub static SIGTERM : int = 15;
+        }
+        #[cfg(target_arch = "mips")]
+        pub mod posix88 {
+            pub static O_RDONLY : int = 0;
+            pub static O_WRONLY : int = 1;
+            pub static O_RDWR : int = 2;
+            pub static O_APPEND : int = 8;
+            pub static O_CREAT : int = 256;
+            pub static O_EXCL : int = 1024;
+            pub static O_TRUNC : int = 512;
+            pub static S_IFIFO : int = 4096;
+            pub static S_IFCHR : int = 8192;
+            pub static S_IFBLK : int = 24576;
+            pub static S_IFDIR : int = 16384;
+            pub static S_IFREG : int = 32768;
+            pub static S_IFMT : int = 61440;
+            pub static S_IEXEC : int = 64;
+            pub static S_IWRITE : int = 128;
+            pub static S_IREAD : int = 256;
+            pub static S_IRWXU : int = 448;
+            pub static S_IXUSR : int = 64;
+            pub static S_IWUSR : int = 128;
+            pub static S_IRUSR : int = 256;
+            pub static F_OK : int = 0;
+            pub static R_OK : int = 4;
+            pub static W_OK : int = 2;
+            pub static X_OK : int = 1;
+            pub static STDIN_FILENO : int = 0;
+            pub static STDOUT_FILENO : int = 1;
+            pub static STDERR_FILENO : int = 2;
+            pub static F_LOCK : int = 1;
+            pub static F_TEST : int = 3;
+            pub static F_TLOCK : int = 2;
+            pub static F_ULOCK : int = 0;
+            pub static SIGHUP : int = 1;
+            pub static SIGINT : int = 2;
+            pub static SIGQUIT : int = 3;
+            pub static SIGILL : int = 4;
+            pub static SIGABRT : int = 6;
+            pub static SIGFPE : int = 8;
+            pub static SIGKILL : int = 9;
+            pub static SIGSEGV : int = 11;
+            pub static SIGPIPE : int = 13;
+            pub static SIGALRM : int = 14;
+            pub static SIGTERM : int = 15;
+        }
+        pub mod posix01 {
+            pub static SIGTRAP : int = 5;
+
+            pub static GLOB_ERR      : int = 1 << 0;
+            pub static GLOB_MARK     : int = 1 << 1;
+            pub static GLOB_NOSORT   : int = 1 << 2;
+            pub static GLOB_DOOFFS   : int = 1 << 3;
+            pub static GLOB_NOCHECK  : int = 1 << 4;
+            pub static GLOB_APPEND   : int = 1 << 5;
+            pub static GLOB_NOESCAPE : int = 1 << 6;
+
+            pub static GLOB_NOSPACE  : int = 1;
+            pub static GLOB_ABORTED  : int = 2;
+            pub static GLOB_NOMATCH  : int = 3;
+        }
+        pub mod posix08 {
+        }
+        pub mod bsd44 {
+        }
+        #[cfg(target_arch = "x86")]
+        #[cfg(target_arch = "x86_64")]
+        #[cfg(target_arch = "arm")]
+        pub mod extra {
+            pub static O_RSYNC : int = 1052672;
+            pub static O_DSYNC : int = 4096;
+            pub static O_SYNC : int = 1052672;
+        }
+        #[cfg(target_arch = "mips")]
+        pub mod extra {
+            pub static O_RSYNC : int = 16400;
+            pub static O_DSYNC : int = 16;
+            pub static O_SYNC : int = 16400;
+        }
+    }
+
+    #[cfg(target_os = "freebsd")]
+    pub mod os {
+        pub mod c95 {
+            pub static EXIT_FAILURE : int = 1;
+            pub static EXIT_SUCCESS : int = 0;
+            pub static RAND_MAX : int = 2147483647;
+            pub static EOF : int = -1;
+            pub static SEEK_SET : int = 0;
+            pub static SEEK_CUR : int = 1;
+            pub static SEEK_END : int = 2;
+            pub static _IOFBF : int = 0;
+            pub static _IONBF : int = 2;
+            pub static _IOLBF : int = 1;
+            pub static BUFSIZ : uint = 1024_u;
+            pub static FOPEN_MAX : uint = 20_u;
+            pub static FILENAME_MAX : uint = 1024_u;
+            pub static L_tmpnam : uint = 1024_u;
+            pub static TMP_MAX : uint = 308915776_u;
+        }
+        pub mod c99 {
+        }
+        pub mod posix88 {
+            pub static O_RDONLY : int = 0;
+            pub static O_WRONLY : int = 1;
+            pub static O_RDWR : int = 2;
+            pub static O_APPEND : int = 8;
+            pub static O_CREAT : int = 512;
+            pub static O_EXCL : int = 2048;
+            pub static O_TRUNC : int = 1024;
+            pub static S_IFIFO : int = 4096;
+            pub static S_IFCHR : int = 8192;
+            pub static S_IFBLK : int = 24576;
+            pub static S_IFDIR : int = 16384;
+            pub static S_IFREG : int = 32768;
+            pub static S_IFMT : int = 61440;
+            pub static S_IEXEC : int = 64;
+            pub static S_IWRITE : int = 128;
+            pub static S_IREAD : int = 256;
+            pub static S_IRWXU : int = 448;
+            pub static S_IXUSR : int = 64;
+            pub static S_IWUSR : int = 128;
+            pub static S_IRUSR : int = 256;
+            pub static F_OK : int = 0;
+            pub static R_OK : int = 4;
+            pub static W_OK : int = 2;
+            pub static X_OK : int = 1;
+            pub static STDIN_FILENO : int = 0;
+            pub static STDOUT_FILENO : int = 1;
+            pub static STDERR_FILENO : int = 2;
+            pub static F_LOCK : int = 1;
+            pub static F_TEST : int = 3;
+            pub static F_TLOCK : int = 2;
+            pub static F_ULOCK : int = 0;
+            pub static SIGHUP : int = 1;
+            pub static SIGINT : int = 2;
+            pub static SIGQUIT : int = 3;
+            pub static SIGILL : int = 4;
+            pub static SIGABRT : int = 6;
+            pub static SIGFPE : int = 8;
+            pub static SIGKILL : int = 9;
+            pub static SIGSEGV : int = 11;
+            pub static SIGPIPE : int = 13;
+            pub static SIGALRM : int = 14;
+            pub static SIGTERM : int = 15;
+        }
+        pub mod posix01 {
+            pub static SIGTRAP : int = 5;
+
+            pub static GLOB_APPEND   : int = 0x0001;
+            pub static GLOB_DOOFFS   : int = 0x0002;
+            pub static GLOB_ERR      : int = 0x0004;
+            pub static GLOB_MARK     : int = 0x0008;
+            pub static GLOB_NOCHECK  : int = 0x0010;
+            pub static GLOB_NOSORT   : int = 0x0020;
+            pub static GLOB_NOESCAPE : int = 0x2000;
+
+            pub static GLOB_NOSPACE  : int = -1;
+            pub static GLOB_ABORTED  : int = -2;
+            pub static GLOB_NOMATCH  : int = -3;
+        }
+        pub mod posix08 {
+        }
+        pub mod bsd44 {
+        }
+        pub mod extra {
+            pub static O_SYNC : int = 128;
+            pub static CTL_KERN: int = 1;
+            pub static KERN_PROC: int = 14;
+            pub static KERN_PROC_PATHNAME: int = 12;
+        }
+    }
+
+    #[cfg(target_os = "macos")]
+    pub mod os {
+        pub mod c95 {
+            pub static EXIT_FAILURE : int = 1;
+            pub static EXIT_SUCCESS : int = 0;
+            pub static RAND_MAX : int = 2147483647;
+            pub static EOF : int = -1;
+            pub static SEEK_SET : int = 0;
+            pub static SEEK_CUR : int = 1;
+            pub static SEEK_END : int = 2;
+            pub static _IOFBF : int = 0;
+            pub static _IONBF : int = 2;
+            pub static _IOLBF : int = 1;
+            pub static BUFSIZ : uint = 1024_u;
+            pub static FOPEN_MAX : uint = 20_u;
+            pub static FILENAME_MAX : uint = 1024_u;
+            pub static L_tmpnam : uint = 1024_u;
+            pub static TMP_MAX : uint = 308915776_u;
+        }
+        pub mod c99 {
+        }
+        pub mod posix88 {
+            pub static O_RDONLY : int = 0;
+            pub static O_WRONLY : int = 1;
+            pub static O_RDWR : int = 2;
+            pub static O_APPEND : int = 8;
+            pub static O_CREAT : int = 512;
+            pub static O_EXCL : int = 2048;
+            pub static O_TRUNC : int = 1024;
+            pub static S_IFIFO : int = 4096;
+            pub static S_IFCHR : int = 8192;
+            pub static S_IFBLK : int = 24576;
+            pub static S_IFDIR : int = 16384;
+            pub static S_IFREG : int = 32768;
+            pub static S_IFMT : int = 61440;
+            pub static S_IEXEC : int = 64;
+            pub static S_IWRITE : int = 128;
+            pub static S_IREAD : int = 256;
+            pub static S_IRWXU : int = 448;
+            pub static S_IXUSR : int = 64;
+            pub static S_IWUSR : int = 128;
+            pub static S_IRUSR : int = 256;
+            pub static F_OK : int = 0;
+            pub static R_OK : int = 4;
+            pub static W_OK : int = 2;
+            pub static X_OK : int = 1;
+            pub static STDIN_FILENO : int = 0;
+            pub static STDOUT_FILENO : int = 1;
+            pub static STDERR_FILENO : int = 2;
+            pub static F_LOCK : int = 1;
+            pub static F_TEST : int = 3;
+            pub static F_TLOCK : int = 2;
+            pub static F_ULOCK : int = 0;
+            pub static SIGHUP : int = 1;
+            pub static SIGINT : int = 2;
+            pub static SIGQUIT : int = 3;
+            pub static SIGILL : int = 4;
+            pub static SIGABRT : int = 6;
+            pub static SIGFPE : int = 8;
+            pub static SIGKILL : int = 9;
+            pub static SIGSEGV : int = 11;
+            pub static SIGPIPE : int = 13;
+            pub static SIGALRM : int = 14;
+            pub static SIGTERM : int = 15;
+        }
+        pub mod posix01 {
+            pub static SIGTRAP : int = 5;
+
+            pub static GLOB_APPEND   : int = 0x0001;
+            pub static GLOB_DOOFFS   : int = 0x0002;
+            pub static GLOB_ERR      : int = 0x0004;
+            pub static GLOB_MARK     : int = 0x0008;
+            pub static GLOB_NOCHECK  : int = 0x0010;
+            pub static GLOB_NOSORT   : int = 0x0020;
+            pub static GLOB_NOESCAPE : int = 0x2000;
+
+            pub static GLOB_NOSPACE  : int = -1;
+            pub static GLOB_ABORTED  : int = -2;
+            pub static GLOB_NOMATCH  : int = -3;
+        }
+        pub mod posix08 {
+        }
+        pub mod bsd44 {
+        }
+        pub mod extra {
+            pub static O_DSYNC : int = 4194304;
+            pub static O_SYNC : int = 128;
+            pub static F_FULLFSYNC : int = 51;
+        }
+    }
+}
+
+
+pub mod funcs {
+    // Thankfull most of c95 is universally available and does not vary by OS
+    // or anything. The same is not true of POSIX.
+
+    pub mod c95 {
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod ctype {
+            use libc::types::os::arch::c95::{c_char, c_int};
+
+            pub extern {
+                unsafe fn isalnum(c: c_int) -> c_int;
+                unsafe fn isalpha(c: c_int) -> c_int;
+                unsafe fn iscntrl(c: c_int) -> c_int;
+                unsafe fn isdigit(c: c_int) -> c_int;
+                unsafe fn isgraph(c: c_int) -> c_int;
+                unsafe fn islower(c: c_int) -> c_int;
+                unsafe fn isprint(c: c_int) -> c_int;
+                unsafe fn ispunct(c: c_int) -> c_int;
+                unsafe fn isspace(c: c_int) -> c_int;
+                unsafe fn isupper(c: c_int) -> c_int;
+                unsafe fn isxdigit(c: c_int) -> c_int;
+                unsafe fn tolower(c: c_char) -> c_char;
+                unsafe fn toupper(c: c_char) -> c_char;
+            }
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod stdio {
+            use libc::types::common::c95::{FILE, c_void, fpos_t};
+            use libc::types::os::arch::c95::{c_char, c_int, c_long, size_t};
+
+            pub extern {
+                unsafe fn fopen(filename: *c_char, mode: *c_char) -> *FILE;
+                unsafe fn freopen(filename: *c_char, mode: *c_char,
+                           file: *FILE) -> *FILE;
+                unsafe fn fflush(file: *FILE) -> c_int;
+                unsafe fn fclose(file: *FILE) -> c_int;
+                unsafe fn remove(filename: *c_char) -> c_int;
+                unsafe fn rename(oldname: *c_char, newname: *c_char) -> c_int;
+                unsafe fn tmpfile() -> *FILE;
+                unsafe fn setvbuf(stream: *FILE, buffer: *c_char,
+                           mode: c_int, size: size_t) -> c_int;
+                unsafe fn setbuf(stream: *FILE, buf: *c_char);
+                // Omitted: printf and scanf variants.
+                unsafe fn fgetc(stream: *FILE) -> c_int;
+                #[fast_ffi]
+                unsafe fn fgets(buf: *mut c_char, n: c_int,
+                         stream: *FILE) -> *c_char;
+                #[fast_ffi]
+                unsafe fn fputc(c: c_int, stream: *FILE) -> c_int;
+                #[fast_ffi]
+                unsafe fn fputs(s: *c_char, stream: *FILE) -> *c_char;
+                // Omitted: getc, getchar (might be macros).
+
+                // Omitted: gets, so ridiculously unsafe that it should not
+                // survive.
+
+                // Omitted: putc, putchar (might be macros).
+                unsafe fn puts(s: *c_char) -> c_int;
+                unsafe fn ungetc(c: c_int, stream: *FILE) -> c_int;
+                #[fast_ffi]
+                unsafe fn fread(ptr: *mut c_void, size: size_t,
+                         nobj: size_t, stream: *FILE) -> size_t;
+                #[fast_ffi]
+                unsafe fn fwrite(ptr: *c_void, size: size_t,
+                          nobj: size_t, stream: *FILE) -> size_t;
+                unsafe fn fseek(stream: *FILE, offset: c_long,
+                         whence: c_int) -> c_int;
+                unsafe fn ftell(stream: *FILE) -> c_long;
+                unsafe fn rewind(stream: *FILE);
+                unsafe fn fgetpos(stream: *FILE, ptr: *fpos_t) -> c_int;
+                unsafe fn fsetpos(stream: *FILE, ptr: *fpos_t) -> c_int;
+                unsafe fn feof(stream: *FILE) -> c_int;
+                unsafe fn ferror(stream: *FILE) -> c_int;
+                unsafe fn perror(s: *c_char);
+            }
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod stdlib {
+            use libc::types::common::c95::c_void;
+            use libc::types::os::arch::c95::{c_char, c_double, c_int};
+            use libc::types::os::arch::c95::{c_long, c_uint, c_ulong};
+            use libc::types::os::arch::c95::{size_t};
+
+            pub extern {
+                unsafe fn abs(i: c_int) -> c_int;
+                unsafe fn labs(i: c_long) -> c_long;
+                // Omitted: div, ldiv (return pub type incomplete).
+                unsafe fn atof(s: *c_char) -> c_double;
+                unsafe fn atoi(s: *c_char) -> c_int;
+                unsafe fn strtod(s: *c_char, endp: **c_char) -> c_double;
+                unsafe fn strtol(s: *c_char, endp: **c_char, base: c_int)
+                              -> c_long;
+                unsafe fn strtoul(s: *c_char, endp: **c_char, base: c_int)
+                               -> c_ulong;
+                #[fast_ffi]
+                unsafe fn calloc(nobj: size_t, size: size_t) -> *c_void;
+                #[fast_ffi]
+                unsafe fn malloc(size: size_t) -> *c_void;
+                #[fast_ffi]
+                unsafe fn realloc(p: *c_void, size: size_t) -> *c_void;
+                #[fast_ffi]
+                unsafe fn free(p: *c_void);
+                unsafe fn abort() -> !;
+                unsafe fn exit(status: c_int) -> !;
+                // Omitted: atexit.
+                unsafe fn system(s: *c_char) -> c_int;
+                unsafe fn getenv(s: *c_char) -> *c_char;
+                // Omitted: bsearch, qsort
+                unsafe fn rand() -> c_int;
+                unsafe fn srand(seed: c_uint);
+            }
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod string {
+            use libc::types::common::c95::c_void;
+            use libc::types::os::arch::c95::{c_char, c_int, size_t};
+            use libc::types::os::arch::c95::{wchar_t};
+
+            pub extern {
+                unsafe fn strcpy(dst: *c_char, src: *c_char) -> *c_char;
+                unsafe fn strncpy(dst: *c_char, src: *c_char, n: size_t)
+                               -> *c_char;
+                unsafe fn strcat(s: *c_char, ct: *c_char) -> *c_char;
+                unsafe fn strncat(s: *c_char, ct: *c_char, n: size_t)
+                               -> *c_char;
+                unsafe fn strcmp(cs: *c_char, ct: *c_char) -> c_int;
+                unsafe fn strncmp(cs: *c_char, ct: *c_char, n: size_t)
+                               -> c_int;
+                unsafe fn strcoll(cs: *c_char, ct: *c_char) -> c_int;
+                unsafe fn strchr(cs: *c_char, c: c_int) -> *c_char;
+                unsafe fn strrchr(cs: *c_char, c: c_int) -> *c_char;
+                unsafe fn strspn(cs: *c_char, ct: *c_char) -> size_t;
+                unsafe fn strcspn(cs: *c_char, ct: *c_char) -> size_t;
+                unsafe fn strpbrk(cs: *c_char, ct: *c_char) -> *c_char;
+                unsafe fn strstr(cs: *c_char, ct: *c_char) -> *c_char;
+                unsafe fn strlen(cs: *c_char) -> size_t;
+                unsafe fn strerror(n: c_int) -> *c_char;
+                unsafe fn strtok(s: *c_char, t: *c_char) -> *c_char;
+                unsafe fn strxfrm(s: *c_char, ct: *c_char, n: size_t)
+                               -> size_t;
+                unsafe fn wcslen(buf: *wchar_t) -> size_t;
+
+                // These are fine to execute on the Rust stack. They must be,
+                // in fact, because LLVM generates calls to them!
+                #[rust_stack]
+                #[inline(always)]
+                unsafe fn memcpy(s: *c_void, ct: *c_void, n: size_t)
+                              -> *c_void;
+                #[rust_stack]
+                #[inline(always)]
+                unsafe fn memmove(s: *c_void, ct: *c_void, n: size_t)
+                               -> *c_void;
+                #[rust_stack]
+                #[inline(always)]
+                unsafe fn memcmp(cx: *c_void, ct: *c_void, n: size_t)
+                              -> c_int;
+                #[rust_stack]
+                #[inline(always)]
+                unsafe fn memchr(cx: *c_void, c: c_int, n: size_t) -> *c_void;
+                #[rust_stack]
+                #[inline(always)]
+                unsafe fn memset(s: *c_void, c: c_int, n: size_t) -> *c_void;
+            }
+        }
+    }
+
+    // Microsoft helpfully underscore-qualifies all of its POSIX-like symbols
+    // to make sure you don't use them accidentally. It also randomly deviates
+    // from the exact signatures you might otherwise expect, and omits much,
+    // so be careful when trying to write portable code; it won't always work
+    // with the same POSIX functions and types as other platforms.
+
+    #[cfg(target_os = "win32")]
+    pub mod posix88 {
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod stat_ {
+            use libc::types::os::common::posix01::stat;
+            use libc::types::os::arch::c95::{c_int, c_char};
+
+            pub extern {
+                #[link_name = "_chmod"]
+                unsafe fn chmod(path: *c_char, mode: c_int) -> c_int;
+
+                #[link_name = "_mkdir"]
+                unsafe fn mkdir(path: *c_char) -> c_int;
+
+                #[link_name = "_fstat64"]
+                unsafe fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
+
+                #[link_name = "_stat64"]
+                unsafe fn stat(path: *c_char, buf: *mut stat) -> c_int;
+            }
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod stdio {
+            use libc::types::common::c95::FILE;
+            use libc::types::os::arch::c95::{c_int, c_char};
+
+            pub extern {
+                #[link_name = "_popen"]
+                unsafe fn popen(command: *c_char, mode: *c_char) -> *FILE;
+
+                #[link_name = "_pclose"]
+                unsafe fn pclose(stream: *FILE) -> c_int;
+
+                #[link_name = "_fdopen"]
+                #[fast_ffi]
+                unsafe fn fdopen(fd: c_int, mode: *c_char) -> *FILE;
+
+                #[link_name = "_fileno"]
+                unsafe fn fileno(stream: *FILE) -> c_int;
+            }
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod fcntl {
+            use libc::types::os::arch::c95::{c_int, c_char};
+            pub extern {
+                #[link_name = "_open"]
+                unsafe fn open(path: *c_char, oflag: c_int, mode: c_int)
+                            -> c_int;
+
+                #[link_name = "_creat"]
+                unsafe fn creat(path: *c_char, mode: c_int) -> c_int;
+            }
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod dirent {
+            // Not supplied at all.
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod unistd {
+            use libc::types::common::c95::c_void;
+            use libc::types::os::arch::c95::{c_int, c_uint, c_char,
+                                             c_long, size_t};
+            use libc::types::os::arch::c99::intptr_t;
+
+            pub extern {
+                #[link_name = "_access"]
+                unsafe fn access(path: *c_char, amode: c_int) -> c_int;
+
+                #[link_name = "_chdir"]
+                unsafe fn chdir(dir: *c_char) -> c_int;
+
+                #[link_name = "_close"]
+                unsafe fn close(fd: c_int) -> c_int;
+
+                #[link_name = "_dup"]
+                unsafe fn dup(fd: c_int) -> c_int;
+
+                #[link_name = "_dup2"]
+                unsafe fn dup2(src: c_int, dst: c_int) -> c_int;
+
+                #[link_name = "_execv"]
+                unsafe fn execv(prog: *c_char, argv: **c_char) -> intptr_t;
+
+                #[link_name = "_execve"]
+                unsafe fn execve(prog: *c_char, argv: **c_char,
+                          envp: **c_char) -> c_int;
+
+                #[link_name = "_execvp"]
+                unsafe fn execvp(c: *c_char, argv: **c_char) -> c_int;
+
+                #[link_name = "_execvpe"]
+                unsafe fn execvpe(c: *c_char, argv: **c_char,
+                           envp: **c_char) -> c_int;
+
+                #[link_name = "_getcwd"]
+                unsafe fn getcwd(buf: *c_char, size: size_t) -> *c_char;
+
+                #[link_name = "_getpid"]
+                unsafe fn getpid() -> c_int;
+
+                #[link_name = "_isatty"]
+                unsafe fn isatty(fd: c_int) -> c_int;
+
+                #[link_name = "_lseek"]
+                unsafe fn lseek(fd: c_int, offset: c_long, origin: c_int)
+                             -> c_long;
+
+                #[link_name = "_pipe"]
+                unsafe fn pipe(fds: *mut c_int, psize: c_uint,
+                        textmode: c_int) -> c_int;
+
+                #[link_name = "_read"]
+                #[fast_ffi]
+                unsafe fn read(fd: c_int, buf: *mut c_void, count: c_uint)
+                            -> c_int;
+
+                #[link_name = "_rmdir"]
+                unsafe fn rmdir(path: *c_char) -> c_int;
+
+                #[link_name = "_unlink"]
+                unsafe fn unlink(c: *c_char) -> c_int;
+
+                #[link_name = "_write"]
+                #[fast_ffi]
+                unsafe fn write(fd: c_int, buf: *c_void, count: c_uint)
+                             -> c_int;
+            }
+        }
+    }
+
+
+    #[cfg(target_os = "linux")]
+    #[cfg(target_os = "android")]
+    #[cfg(target_os = "macos")]
+    #[cfg(target_os = "freebsd")]
+    pub mod posix88 {
+        pub mod stat_ {
+            use libc::types::os::arch::c95::{c_char, c_int};
+            use libc::types::os::arch::posix01::stat;
+            use libc::types::os::arch::posix88::mode_t;
+
+            #[nolink]
+            #[abi = "cdecl"]
+            pub extern {
+                unsafe fn chmod(path: *c_char, mode: mode_t) -> c_int;
+                unsafe fn fchmod(fd: c_int, mode: mode_t) -> c_int;
+
+                #[cfg(target_os = "linux")]
+                #[cfg(target_os = "freebsd")]
+                #[cfg(target_os = "android")]
+               unsafe fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
+
+                #[cfg(target_os = "macos")]
+                #[link_name = "fstat64"]
+                unsafe fn fstat(fildes: c_int, buf: *mut stat) -> c_int;
+
+                unsafe fn mkdir(path: *c_char, mode: mode_t) -> c_int;
+                unsafe fn mkfifo(path: *c_char, mode: mode_t) -> c_int;
+
+                #[cfg(target_os = "linux")]
+                #[cfg(target_os = "freebsd")]
+                #[cfg(target_os = "android")]
+                unsafe fn stat(path: *c_char, buf: *mut stat) -> c_int;
+
+                #[cfg(target_os = "macos")]
+                #[link_name = "stat64"]
+                unsafe fn stat(path: *c_char, buf: *mut stat) -> c_int;
+            }
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod stdio {
+            use libc::types::common::c95::FILE;
+            use libc::types::os::arch::c95::{c_char, c_int};
+
+            pub extern {
+                unsafe fn popen(command: *c_char, mode: *c_char) -> *FILE;
+                unsafe fn pclose(stream: *FILE) -> c_int;
+                unsafe fn fdopen(fd: c_int, mode: *c_char) -> *FILE;
+                unsafe fn fileno(stream: *FILE) -> c_int;
+            }
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod fcntl {
+            use libc::types::os::arch::c95::{c_char, c_int};
+            use libc::types::os::arch::posix88::mode_t;
+
+            pub extern {
+                unsafe fn open(path: *c_char, oflag: c_int, mode: c_int)
+                            -> c_int;
+                unsafe fn creat(path: *c_char, mode: mode_t) -> c_int;
+                unsafe fn fcntl(fd: c_int, cmd: c_int) -> c_int;
+            }
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod dirent {
+            use libc::types::common::posix88::{DIR, dirent_t};
+            use libc::types::os::arch::c95::{c_char, c_int, c_long};
+
+            // NB: On OS X opendir and readdir have two versions,
+            // one for 32-bit kernelspace and one for 64.
+            // We should be linking to the 64-bit ones, called
+            // opendir$INODE64, etc. but for some reason rustc
+            // doesn't link it correctly on i686, so we're going
+            // through a C function that mysteriously does work.
+            pub unsafe fn opendir(dirname: *c_char) -> *DIR {
+                rust_opendir(dirname)
+            }
+            pub unsafe fn readdir(dirp: *DIR) -> *dirent_t {
+                rust_readdir(dirp)
+            }
+
+            extern {
+                unsafe fn rust_opendir(dirname: *c_char) -> *DIR;
+                unsafe fn rust_readdir(dirp: *DIR) -> *dirent_t;
+            }
+
+            pub extern {
+                unsafe fn closedir(dirp: *DIR) -> c_int;
+                unsafe fn rewinddir(dirp: *DIR);
+                unsafe fn seekdir(dirp: *DIR, loc: c_long);
+                unsafe fn telldir(dirp: *DIR) -> c_long;
+            }
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod unistd {
+            use libc::types::common::c95::c_void;
+            use libc::types::os::arch::c95::{c_char, c_int, c_long, c_uint};
+            use libc::types::os::arch::c95::{size_t};
+            use libc::types::os::arch::posix88::{gid_t, off_t, pid_t};
+            use libc::types::os::arch::posix88::{ssize_t, uid_t};
+
+            pub extern {
+                unsafe fn access(path: *c_char, amode: c_int) -> c_int;
+                unsafe fn alarm(seconds: c_uint) -> c_uint;
+                unsafe fn chdir(dir: *c_char) -> c_int;
+                unsafe fn chown(path: *c_char, uid: uid_t, gid: gid_t)
+                             -> c_int;
+                unsafe fn close(fd: c_int) -> c_int;
+                unsafe fn dup(fd: c_int) -> c_int;
+                unsafe fn dup2(src: c_int, dst: c_int) -> c_int;
+                unsafe fn execv(prog: *c_char, argv: **c_char) -> c_int;
+                unsafe fn execve(prog: *c_char,
+                                 argv: **c_char,
+                                 envp: **c_char)
+                              -> c_int;
+                unsafe fn execvp(c: *c_char, argv: **c_char) -> c_int;
+                unsafe fn fork() -> pid_t;
+                unsafe fn fpathconf(filedes: c_int, name: c_int) -> c_long;
+                unsafe fn getcwd(buf: *c_char, size: size_t) -> *c_char;
+                unsafe fn getegid() -> gid_t;
+                unsafe fn geteuid() -> uid_t;
+                unsafe fn getgid() -> gid_t ;
+                unsafe fn getgroups(ngroups_max: c_int, groups: *mut gid_t)
+                                 -> c_int;
+                unsafe fn getlogin() -> *c_char;
+                unsafe fn getopt(argc: c_int, argv: **c_char, optstr: *c_char)
+                              -> c_int;
+                unsafe fn getpgrp() -> pid_t;
+                unsafe fn getpid() -> pid_t;
+                unsafe fn getppid() -> pid_t;
+                unsafe fn getuid() -> uid_t;
+                unsafe fn isatty(fd: c_int) -> c_int;
+                unsafe fn link(src: *c_char, dst: *c_char) -> c_int;
+                unsafe fn lseek(fd: c_int, offset: off_t, whence: c_int)
+                             -> off_t;
+                unsafe fn pathconf(path: *c_char, name: c_int) -> c_long;
+                unsafe fn pause() -> c_int;
+                unsafe fn pipe(fds: *mut c_int) -> c_int;
+                #[fast_ffi]
+                unsafe fn read(fd: c_int, buf: *mut c_void,
+                        count: size_t) -> ssize_t;
+                unsafe fn rmdir(path: *c_char) -> c_int;
+                unsafe fn setgid(gid: gid_t) -> c_int;
+                unsafe fn setpgid(pid: pid_t, pgid: pid_t) -> c_int;
+                unsafe fn setsid() -> pid_t;
+                unsafe fn setuid(uid: uid_t) -> c_int;
+                unsafe fn sleep(secs: c_uint) -> c_uint;
+                unsafe fn sysconf(name: c_int) -> c_long;
+                unsafe fn tcgetpgrp(fd: c_int) -> pid_t;
+                unsafe fn ttyname(fd: c_int) -> *c_char;
+                unsafe fn unlink(c: *c_char) -> c_int;
+                #[fast_ffi]
+                unsafe fn write(fd: c_int, buf: *c_void, count: size_t)
+                             -> ssize_t;
+            }
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod signal {
+            use libc::types::os::arch::c95::{c_int};
+            use libc::types::os::arch::posix88::{pid_t};
+
+            pub extern {
+                unsafe fn kill(pid: pid_t, sig: c_int) -> c_int;
+            }
+        }
+    }
+
+    #[cfg(target_os = "linux")]
+    #[cfg(target_os = "android")]
+    #[cfg(target_os = "macos")]
+    #[cfg(target_os = "freebsd")]
+    pub mod posix01 {
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod stat_ {
+            use libc::types::os::arch::c95::{c_char, c_int};
+            use libc::types::os::arch::posix01::stat;
+
+            pub extern {
+                #[cfg(target_os = "linux")]
+                #[cfg(target_os = "freebsd")]
+                #[cfg(target_os = "android")]
+                unsafe fn lstat(path: *c_char, buf: *mut stat) -> c_int;
+
+                #[cfg(target_os = "macos")]
+                #[link_name = "lstat64"]
+                unsafe fn lstat(path: *c_char, buf: *mut stat) -> c_int;
+            }
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod unistd {
+            use libc::types::os::arch::c95::{c_char, c_int, size_t};
+            use libc::types::os::arch::posix88::{ssize_t};
+
+            pub extern {
+                unsafe fn readlink(path: *c_char, buf: *mut c_char,
+                            bufsz: size_t) -> ssize_t;
+
+                unsafe fn fsync(fd: c_int) -> c_int;
+
+                #[cfg(target_os = "linux")]
+                #[cfg(target_os = "android")]
+                unsafe fn fdatasync(fd: c_int) -> c_int;
+
+                unsafe fn setenv(name: *c_char, val: *c_char,
+                          overwrite: c_int) -> c_int;
+                unsafe fn unsetenv(name: *c_char) -> c_int;
+                unsafe fn putenv(string: *c_char) -> c_int;
+
+                unsafe fn symlink(path1: *c_char, path2: *c_char) -> c_int;
+            }
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod wait {
+            use libc::types::os::arch::c95::{c_int};
+            use libc::types::os::arch::posix88::{pid_t};
+
+            pub extern {
+                unsafe fn waitpid(pid: pid_t,
+                                  status: *mut c_int,
+                                  options: c_int)
+                               -> pid_t;
+            }
+        }
+
+        #[nolink]
+        #[abi = "cdecl"]
+        pub mod glob {
+            use libc::types::common::c95::{c_void};
+            use libc::types::os::arch::c95::{c_char, c_int};
+            use libc::types::os::common::posix01::{glob_t};
+
+            pub extern {
+                unsafe fn glob(pattern: *c_char, flags: c_int,
+                               errfunc: *c_void, // XXX callback
+                               pglob: *mut glob_t);
+                unsafe fn globfree(pglob: *mut glob_t);
+            }
+        }
+    }
+
+    #[cfg(target_os = "win32")]
+    pub mod posix01 {
+        pub mod stat_ {
+        }
+
+        pub mod unistd {
+        }
+
+        pub mod glob {
+        }
+    }
+
+
+    #[cfg(target_os = "win32")]
+    #[cfg(target_os = "linux")]
+    #[cfg(target_os = "android")]
+    #[cfg(target_os = "macos")]
+    #[cfg(target_os = "freebsd")]
+    pub mod posix08 {
+        pub mod unistd {
+        }
+    }
+
+
+    #[cfg(target_os = "macos")]
+    #[cfg(target_os = "freebsd")]
+    pub mod bsd44 {
+        use libc::types::common::c95::{c_void};
+        use libc::types::os::arch::c95::{c_char, c_int, c_uint, size_t};
+
+        #[abi = "cdecl"]
+        pub extern {
+            unsafe fn sysctl(name: *c_int, namelen: c_uint,
+                      oldp: *mut c_void, oldlenp: *mut size_t,
+                      newp: *c_void, newlen: size_t) -> c_int;
+
+            unsafe fn sysctlbyname(name: *c_char,
+                            oldp: *mut c_void, oldlenp: *mut size_t,
+                            newp: *c_void, newlen: size_t) -> c_int;
+
+            unsafe fn sysctlnametomib(name: *c_char, mibp: *mut c_int,
+                               sizep: *mut size_t) -> c_int;
+
+            unsafe fn getdtablesize() -> c_int;
+        }
+    }
+
+
+    #[cfg(target_os = "linux")]
+    #[cfg(target_os = "android")]
+    pub mod bsd44 {
+        use libc::types::os::arch::c95::{c_int};
+
+        #[abi = "cdecl"]
+        pub extern {
+            unsafe fn getdtablesize() -> c_int;
+        }
+    }
+
+
+    #[cfg(target_os = "win32")]
+    pub mod bsd44 {
+    }
+
+    #[cfg(target_os = "macos")]
+    #[nolink]
+    pub mod extra {
+        use libc::types::os::arch::c95::{c_char, c_int};
+
+        #[abi = "cdecl"]
+        pub extern {
+            unsafe fn _NSGetExecutablePath(buf: *mut c_char,
+                                           bufsize: *mut u32)
+                                        -> c_int;
+        }
+    }
+
+    #[cfg(target_os = "freebsd")]
+    pub mod extra {
+    }
+
+    #[cfg(target_os = "linux")]
+    #[cfg(target_os = "android")]
+    pub mod extra {
+    }
+
+
+    #[cfg(target_os = "win32")]
+    pub mod extra {
+
+        pub mod kernel32 {
+            use libc::types::os::arch::c95::{c_uint};
+            use libc::types::os::arch::extra::{BOOL, DWORD, HMODULE};
+            use libc::types::os::arch::extra::{LPCWSTR, LPWSTR, LPCTSTR,
+                                               LPTSTR, LPTCH, LPDWORD, LPVOID};
+            use libc::types::os::arch::extra::{LPSECURITY_ATTRIBUTES, LPSTARTUPINFO,
+                                               LPPROCESS_INFORMATION};
+            use libc::types::os::arch::extra::{HANDLE, LPHANDLE};
+
+            #[abi = "stdcall"]
+            pub extern "stdcall" {
+                unsafe fn GetEnvironmentVariableW(n: LPCWSTR,
+                                                  v: LPWSTR,
+                                                  nsize: DWORD)
+                                               -> DWORD;
+                unsafe fn SetEnvironmentVariableW(n: LPCWSTR, v: LPCWSTR)
+                                               -> BOOL;
+                unsafe fn GetEnvironmentStringsA() -> LPTCH;
+                unsafe fn FreeEnvironmentStringsA(env_ptr: LPTCH) -> BOOL;
+
+                unsafe fn GetModuleFileNameW(hModule: HMODULE,
+                                             lpFilename: LPWSTR,
+                                             nSize: DWORD)
+                                          -> DWORD;
+                unsafe fn CreateDirectoryW(lpPathName: LPCWSTR,
+                                           lpSecurityAttributes:
+                                           LPSECURITY_ATTRIBUTES)
+                                        -> BOOL;
+                unsafe fn CopyFileW(lpExistingFileName: LPCWSTR,
+                                    lpNewFileName: LPCWSTR,
+                                    bFailIfExists: BOOL)
+                                 -> BOOL;
+                unsafe fn DeleteFileW(lpPathName: LPCWSTR) -> BOOL;
+                unsafe fn RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL;
+                unsafe fn SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL;
+
+                unsafe fn GetLastError() -> DWORD;
+                unsafe fn FindFirstFileW(fileName: *u16,
+                                        findFileData: HANDLE)
+                    -> HANDLE;
+                unsafe fn FindNextFileW(findFile: HANDLE,
+                                       findFileData: HANDLE)
+                    -> BOOL;
+                unsafe fn FindClose(findFile: HANDLE) -> BOOL;
+                unsafe fn DuplicateHandle(hSourceProcessHandle: HANDLE,
+                                          hSourceHandle: HANDLE,
+                                          hTargetProcessHandle: HANDLE,
+                                          lpTargetHandle: LPHANDLE,
+                                          dwDesiredAccess: DWORD,
+                                          bInheritHandle: BOOL,
+                                          dwOptions: DWORD) -> BOOL;
+                unsafe fn CloseHandle(hObject: HANDLE) -> BOOL;
+                unsafe fn OpenProcess(dwDesiredAccess: DWORD,
+                                      bInheritHandle: BOOL,
+                                      dwProcessId: DWORD) -> HANDLE;
+                unsafe fn GetCurrentProcess() -> HANDLE;
+                unsafe fn CreateProcessA(lpApplicationName: LPCTSTR,
+                                         lpCommandLine: LPTSTR,
+                                         lpProcessAttributes: LPSECURITY_ATTRIBUTES,
+                                         lpThreadAttributes: LPSECURITY_ATTRIBUTES,
+                                         bInheritHandles: BOOL,
+                                         dwCreationFlags: DWORD,
+                                         lpEnvironment: LPVOID,
+                                         lpCurrentDirectory: LPCTSTR,
+                                         lpStartupInfo: LPSTARTUPINFO,
+                                         lpProcessInformation: LPPROCESS_INFORMATION) -> BOOL;
+                unsafe fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD;
+                unsafe fn TerminateProcess(hProcess: HANDLE, uExitCode: c_uint) -> BOOL;
+                unsafe fn GetExitCodeProcess(hProcess: HANDLE, lpExitCode: LPDWORD) -> BOOL;
+            }
+        }
+
+        pub mod msvcrt {
+            use libc::types::os::arch::c95::{c_int, c_long};
+
+            #[abi = "cdecl"]
+            #[nolink]
+            pub extern {
+                #[link_name = "_commit"]
+                unsafe fn commit(fd: c_int) -> c_int;
+
+                #[link_name = "_get_osfhandle"]
+                unsafe fn get_osfhandle(fd: c_int) -> c_long;
+            }
+        }
+    }
+}
diff --git a/src/libstd/list.rs b/src/libstd/list.rs
deleted file mode 100644
index 3a916233db8..00000000000
--- a/src/libstd/list.rs
+++ /dev/null
@@ -1,270 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! A standard linked list
-
-#[deriving(Eq)]
-pub enum List<T> {
-    Cons(T, @List<T>),
-    Nil,
-}
-
-#[deriving(Eq)]
-pub enum MutList<T> {
-    MutCons(T, @mut MutList<T>),
-    MutNil,
-}
-
-/// Create a list from a vector
-pub fn from_vec<T:Copy>(v: &[T]) -> @List<T> {
-    vec::foldr(v, @Nil::<T>, |h, t| @Cons(*h, t))
-}
-
-/**
- * Left fold
- *
- * Applies `f` to `u` and the first element in the list, then applies `f` to
- * the result of the previous call and the second element, and so on,
- * returning the accumulated result.
- *
- * # Arguments
- *
- * * ls - The list to fold
- * * z - The initial value
- * * f - The function to apply
- */
-pub fn foldl<T:Copy,U>(z: T, ls: @List<U>, f: &fn(&T, &U) -> T) -> T {
-    let mut accum: T = z;
-    do iter(ls) |elt| { accum = f(&accum, elt);}
-    accum
-}
-
-/**
- * Search for an element that matches a given predicate
- *
- * Apply function `f` to each element of `v`, starting from the first.
- * When function `f` returns true then an option containing the element
- * is returned. If `f` matches no elements then none is returned.
- */
-pub fn find<T:Copy>(ls: @List<T>, f: &fn(&T) -> bool) -> Option<T> {
-    let mut ls = ls;
-    loop {
-        ls = match *ls {
-          Cons(ref hd, tl) => {
-            if f(hd) { return Some(*hd); }
-            tl
-          }
-          Nil => return None
-        }
-    };
-}
-
-/// Returns true if a list contains an element with the given value
-pub fn has<T:Copy + Eq>(ls: @List<T>, elt: T) -> bool {
-    for each(ls) |e| {
-        if *e == elt { return true; }
-    }
-    return false;
-}
-
-/// Returns true if the list is empty
-pub fn is_empty<T:Copy>(ls: @List<T>) -> bool {
-    match *ls {
-        Nil => true,
-        _ => false
-    }
-}
-
-/// Returns the length of a list
-pub fn len<T>(ls: @List<T>) -> uint {
-    let mut count = 0u;
-    iter(ls, |_e| count += 1u);
-    count
-}
-
-/// Returns all but the first element of a list
-pub fn tail<T:Copy>(ls: @List<T>) -> @List<T> {
-    match *ls {
-        Cons(_, tl) => return tl,
-        Nil => fail!("list empty")
-    }
-}
-
-/// Returns the first element of a list
-pub fn head<T:Copy>(ls: @List<T>) -> T {
-    match *ls {
-      Cons(copy hd, _) => hd,
-      // makes me sad
-      _ => fail!("head invoked on empty list")
-    }
-}
-
-/// Appends one list to another
-pub fn append<T:Copy>(l: @List<T>, m: @List<T>) -> @List<T> {
-    match *l {
-      Nil => return m,
-      Cons(copy x, xs) => {
-        let rest = append(xs, m);
-        return @Cons(x, rest);
-      }
-    }
-}
-
-/*
-/// Push one element into the front of a list, returning a new list
-/// THIS VERSION DOESN'T ACTUALLY WORK
-fn push<T:Copy>(ll: &mut @list<T>, vv: T) {
-    ll = &mut @cons(vv, *ll)
-}
-*/
-
-/// Iterate over a list
-pub fn iter<T>(l: @List<T>, f: &fn(&T)) {
-    let mut cur = l;
-    loop {
-        cur = match *cur {
-          Cons(ref hd, tl) => {
-            f(hd);
-            tl
-          }
-          Nil => break
-        }
-    }
-}
-
-/// Iterate over a list
-pub fn each<T>(l: @List<T>, f: &fn(&T) -> bool) -> bool {
-    let mut cur = l;
-    loop {
-        cur = match *cur {
-          Cons(ref hd, tl) => {
-            if !f(hd) { return false; }
-            tl
-          }
-          Nil => { return true; }
-        }
-    }
-}
-
-impl<T> MutList<T> {
-    /// Iterate over a mutable list
-    pub fn each(@mut self, f: &fn(&mut T) -> bool) -> bool {
-        let mut cur = self;
-        loop {
-            let borrowed = &mut *cur;
-            cur = match *borrowed {
-                MutCons(ref mut hd, tl) => {
-                    if !f(hd) {
-                        return false;
-                    }
-                    tl
-                }
-                MutNil => break
-            }
-        }
-        return true;
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use list::*;
-    use list;
-
-    use core::option;
-
-    #[test]
-    fn test_is_empty() {
-        let empty : @list::List<int> = from_vec(~[]);
-        let full1 = from_vec(~[1]);
-        let full2 = from_vec(~['r', 'u']);
-
-        assert!(is_empty(empty));
-        assert!(!is_empty(full1));
-        assert!(!is_empty(full2));
-    }
-
-    #[test]
-    fn test_from_vec() {
-        let l = from_vec(~[0, 1, 2]);
-
-        assert_eq!(head(l), 0);
-
-        let tail_l = tail(l);
-        assert_eq!(head(tail_l), 1);
-
-        let tail_tail_l = tail(tail_l);
-        assert_eq!(head(tail_tail_l), 2);
-    }
-
-    #[test]
-    fn test_from_vec_empty() {
-        let empty : @list::List<int> = from_vec(~[]);
-        assert_eq!(empty, @list::Nil::<int>);
-    }
-
-    #[test]
-    fn test_foldl() {
-        fn add(a: &uint, b: &int) -> uint { return *a + (*b as uint); }
-        let l = from_vec(~[0, 1, 2, 3, 4]);
-        let empty = @list::Nil::<int>;
-        assert_eq!(list::foldl(0u, l, add), 10u);
-        assert_eq!(list::foldl(0u, empty, add), 0u);
-    }
-
-    #[test]
-    fn test_foldl2() {
-        fn sub(a: &int, b: &int) -> int {
-            *a - *b
-        }
-        let l = from_vec(~[1, 2, 3, 4]);
-        assert_eq!(list::foldl(0, l, sub), -10);
-    }
-
-    #[test]
-    fn test_find_success() {
-        fn match_(i: &int) -> bool { return *i == 2; }
-        let l = from_vec(~[0, 1, 2]);
-        assert_eq!(list::find(l, match_), option::Some(2));
-    }
-
-    #[test]
-    fn test_find_fail() {
-        fn match_(_i: &int) -> bool { return false; }
-        let l = from_vec(~[0, 1, 2]);
-        let empty = @list::Nil::<int>;
-        assert_eq!(list::find(l, match_), option::None::<int>);
-        assert_eq!(list::find(empty, match_), option::None::<int>);
-    }
-
-    #[test]
-    fn test_has() {
-        let l = from_vec(~[5, 8, 6]);
-        let empty = @list::Nil::<int>;
-        assert!((list::has(l, 5)));
-        assert!((!list::has(l, 7)));
-        assert!((list::has(l, 8)));
-        assert!((!list::has(empty, 5)));
-    }
-
-    #[test]
-    fn test_len() {
-        let l = from_vec(~[0, 1, 2]);
-        let empty = @list::Nil::<int>;
-        assert_eq!(list::len(l), 3u);
-        assert_eq!(list::len(empty), 0u);
-    }
-
-    #[test]
-    fn test_append() {
-        assert!(from_vec(~[1,2,3,4])
-            == list::append(list::from_vec(~[1,2]), list::from_vec(~[3,4])));
-    }
-}
diff --git a/src/libstd/local_data.rs b/src/libstd/local_data.rs
new file mode 100644
index 00000000000..2cbf8b9f05e
--- /dev/null
+++ b/src/libstd/local_data.rs
@@ -0,0 +1,226 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+Task local data management
+
+Allows storing boxes with arbitrary types inside, to be accessed
+anywhere within a task, keyed by a pointer to a global finaliser
+function. Useful for dynamic variables, singletons, and interfacing
+with foreign code with bad callback interfaces.
+
+To use, declare a monomorphic global function at the type to store,
+and use it as the 'key' when accessing. See the 'tls' tests below for
+examples.
+
+Casting 'Arcane Sight' reveals an overwhelming aura of Transmutation
+magic.
+
+*/
+
+use prelude::*;
+use task::local_data_priv::{local_get, local_pop, local_modify, local_set, Handle};
+
+/**
+ * Indexes a task-local data slot. The function's code pointer is used for
+ * comparison. Recommended use is to write an empty function for each desired
+ * task-local data slot (and use class destructors, not code inside the
+ * function, if specific teardown is needed). DO NOT use multiple
+ * instantiations of a single polymorphic function to index data of different
+ * types; arbitrary type coercion is possible this way.
+ *
+ * One other exception is that this global state can be used in a destructor
+ * context to create a circular @-box reference, which will crash during task
+ * failure (see issue #3039).
+ *
+ * These two cases aside, the interface is safe.
+ */
+pub type LocalDataKey<'self,T> = &'self fn(v: @T);
+
+/**
+ * Remove a task-local data value from the table, returning the
+ * reference that was originally created to insert it.
+ */
+pub unsafe fn local_data_pop<T: 'static>(
+    key: LocalDataKey<T>) -> Option<@T> {
+
+    local_pop(Handle::new(), key)
+}
+/**
+ * Retrieve a task-local data value. It will also be kept alive in the
+ * table until explicitly removed.
+ */
+pub unsafe fn local_data_get<T: 'static>(
+    key: LocalDataKey<T>) -> Option<@T> {
+
+    local_get(Handle::new(), key)
+}
+/**
+ * Store a value in task-local data. If this key already has a value,
+ * that value is overwritten (and its destructor is run).
+ */
+pub unsafe fn local_data_set<T: 'static>(
+    key: LocalDataKey<T>, data: @T) {
+
+    local_set(Handle::new(), key, data)
+}
+/**
+ * Modify a task-local data value. If the function returns 'None', the
+ * data is removed (and its reference dropped).
+ */
+pub unsafe fn local_data_modify<T: 'static>(
+    key: LocalDataKey<T>,
+    modify_fn: &fn(Option<@T>) -> Option<@T>) {
+
+    local_modify(Handle::new(), key, modify_fn)
+}
+
+#[test]
+fn test_tls_multitask() {
+    unsafe {
+        fn my_key(_x: @~str) { }
+        local_data_set(my_key, @~"parent data");
+        do task::spawn {
+            unsafe {
+                // TLS shouldn't carry over.
+                assert!(local_data_get(my_key).is_none());
+                local_data_set(my_key, @~"child data");
+                assert!(*(local_data_get(my_key).get()) ==
+                    ~"child data");
+                // should be cleaned up for us
+            }
+        }
+        // Must work multiple times
+        assert!(*(local_data_get(my_key).get()) == ~"parent data");
+        assert!(*(local_data_get(my_key).get()) == ~"parent data");
+        assert!(*(local_data_get(my_key).get()) == ~"parent data");
+    }
+}
+
+#[test]
+fn test_tls_overwrite() {
+    unsafe {
+        fn my_key(_x: @~str) { }
+        local_data_set(my_key, @~"first data");
+        local_data_set(my_key, @~"next data"); // Shouldn't leak.
+        assert!(*(local_data_get(my_key).get()) == ~"next data");
+    }
+}
+
+#[test]
+fn test_tls_pop() {
+    unsafe {
+        fn my_key(_x: @~str) { }
+        local_data_set(my_key, @~"weasel");
+        assert!(*(local_data_pop(my_key).get()) == ~"weasel");
+        // Pop must remove the data from the map.
+        assert!(local_data_pop(my_key).is_none());
+    }
+}
+
+#[test]
+fn test_tls_modify() {
+    unsafe {
+        fn my_key(_x: @~str) { }
+        local_data_modify(my_key, |data| {
+            match data {
+                Some(@ref val) => fail!("unwelcome value: %s", *val),
+                None           => Some(@~"first data")
+            }
+        });
+        local_data_modify(my_key, |data| {
+            match data {
+                Some(@~"first data") => Some(@~"next data"),
+                Some(@ref val)       => fail!("wrong value: %s", *val),
+                None                 => fail!("missing value")
+            }
+        });
+        assert!(*(local_data_pop(my_key).get()) == ~"next data");
+    }
+}
+
+#[test]
+fn test_tls_crust_automorestack_memorial_bug() {
+    // This might result in a stack-canary clobber if the runtime fails to
+    // set sp_limit to 0 when calling the cleanup extern - it might
+    // automatically jump over to the rust stack, which causes next_c_sp
+    // to get recorded as something within a rust stack segment. Then a
+    // subsequent upcall (esp. for logging, think vsnprintf) would run on
+    // a stack smaller than 1 MB.
+    fn my_key(_x: @~str) { }
+    do task::spawn {
+        unsafe { local_data_set(my_key, @~"hax"); }
+    }
+}
+
+#[test]
+fn test_tls_multiple_types() {
+    fn str_key(_x: @~str) { }
+    fn box_key(_x: @@()) { }
+    fn int_key(_x: @int) { }
+    do task::spawn {
+        unsafe {
+            local_data_set(str_key, @~"string data");
+            local_data_set(box_key, @@());
+            local_data_set(int_key, @42);
+        }
+    }
+}
+
+#[test]
+fn test_tls_overwrite_multiple_types() {
+    fn str_key(_x: @~str) { }
+    fn box_key(_x: @@()) { }
+    fn int_key(_x: @int) { }
+    do task::spawn {
+        unsafe {
+            local_data_set(str_key, @~"string data");
+            local_data_set(int_key, @42);
+            // This could cause a segfault if overwriting-destruction is done
+            // with the crazy polymorphic transmute rather than the provided
+            // finaliser.
+            local_data_set(int_key, @31337);
+        }
+    }
+}
+
+#[test]
+#[should_fail]
+#[ignore(cfg(windows))]
+fn test_tls_cleanup_on_failure() {
+    unsafe {
+        fn str_key(_x: @~str) { }
+        fn box_key(_x: @@()) { }
+        fn int_key(_x: @int) { }
+        local_data_set(str_key, @~"parent data");
+        local_data_set(box_key, @@());
+        do task::spawn {
+            unsafe { // spawn_linked
+                local_data_set(str_key, @~"string data");
+                local_data_set(box_key, @@());
+                local_data_set(int_key, @42);
+                fail!();
+            }
+        }
+        // Not quite nondeterministic.
+        local_data_set(int_key, @31337);
+        fail!();
+    }
+}
+
+#[test]
+fn test_static_pointer() {
+    unsafe {
+        fn key(_x: @&'static int) { }
+        static VALUE: int = 0;
+        local_data_set(key, @&VALUE);
+    }
+}
diff --git a/src/libstd/logging.rs b/src/libstd/logging.rs
new file mode 100644
index 00000000000..be71714a048
--- /dev/null
+++ b/src/libstd/logging.rs
@@ -0,0 +1,97 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Logging
+
+use option::*;
+use either::*;
+use rt;
+use rt::logging::{Logger, StdErrLogger};
+use cast;
+use str;
+
+/// Turns on logging to stdout globally
+pub fn console_on() {
+    unsafe {
+        rustrt::rust_log_console_on();
+    }
+}
+
+/**
+ * Turns off logging to stdout globally
+ *
+ * Turns off the console unless the user has overridden the
+ * runtime environment's logging spec, e.g. by setting
+ * the RUST_LOG environment variable
+ */
+pub fn console_off() {
+    unsafe {
+        rustrt::rust_log_console_off();
+    }
+}
+
+#[cfg(not(test))]
+#[lang="log_type"]
+pub fn log_type<T>(level: u32, object: &T) {
+    use container::Container;
+    use io;
+    use libc;
+    use repr;
+    use vec;
+
+    let bytes = do io::with_bytes_writer |writer| {
+        repr::write_repr(writer, object);
+    };
+
+    match rt::context() {
+        rt::OldTaskContext => {
+            unsafe {
+                let len = bytes.len() as libc::size_t;
+                rustrt::rust_log_str(level, cast::transmute(vec::raw::to_ptr(bytes)), len);
+            }
+        }
+        _ => {
+            // XXX: Bad allocation
+            let msg = str::from_bytes(bytes);
+            newsched_log_str(msg);
+        }
+    }
+}
+
+fn newsched_log_str(msg: ~str) {
+    use rt::task::Task;
+    use rt::local::Local;
+
+    unsafe {
+        match Local::try_unsafe_borrow::<Task>() {
+            Some(local) => {
+                // Use the available logger
+                (*local).logger.log(Left(msg));
+            }
+            None => {
+                // There is no logger anywhere, just write to stderr
+                let mut logger = StdErrLogger;
+                logger.log(Left(msg));
+            }
+        }
+    }
+}
+
+pub mod rustrt {
+    use libc;
+
+    pub extern {
+        unsafe fn rust_log_console_on();
+        unsafe fn rust_log_console_off();
+        unsafe fn rust_log_str(level: u32,
+                               string: *libc::c_char,
+                               size: libc::size_t);
+    }
+}
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
new file mode 100644
index 00000000000..fda48b6ffb7
--- /dev/null
+++ b/src/libstd/macros.rs
@@ -0,0 +1,53 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[macro_escape];
+
+// Some basic logging
+macro_rules! rtdebug_ (
+    ($( $arg:expr),+) => ( {
+        dumb_println(fmt!( $($arg),+ ));
+
+        fn dumb_println(s: &str) {
+            use io::WriterUtil;
+            let dbg = ::libc::STDERR_FILENO as ::io::fd_t;
+            dbg.write_str(s);
+            dbg.write_str("\n");
+        }
+
+    } )
+)
+
+// An alternate version with no output, for turning off logging
+macro_rules! rtdebug (
+    ($( $arg:expr),+) => ( $(let _ = $arg)*; )
+)
+
+macro_rules! rtassert (
+    ( $arg:expr ) => ( {
+        if !$arg {
+            abort!("assertion failed: %s", stringify!($arg));
+        }
+    } )
+)
+
+macro_rules! abort(
+    ($( $msg:expr),+) => ( {
+        rtdebug!($($msg),+);
+
+        do_abort();
+
+        // NB: This is in a fn to avoid putting the `unsafe` block in a macro,
+        // which causes spurious 'unnecessary unsafe block' warnings.
+        fn do_abort() -> ! {
+            unsafe { ::libc::abort(); }
+        }
+    } )
+)
diff --git a/src/libstd/managed.rs b/src/libstd/managed.rs
new file mode 100644
index 00000000000..ecde1eb1917
--- /dev/null
+++ b/src/libstd/managed.rs
@@ -0,0 +1,100 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations on managed box types
+
+use ptr::to_unsafe_ptr;
+
+#[cfg(not(test))] use cmp::{Eq, Ord};
+
+pub mod raw {
+    use intrinsic::TyDesc;
+
+    pub static RC_EXCHANGE_UNIQUE : uint = (-1) as uint;
+    pub static RC_MANAGED_UNIQUE : uint = (-2) as uint;
+    pub static RC_IMMORTAL : uint = 0x77777777;
+
+    pub struct BoxHeaderRepr {
+        ref_count: uint,
+        type_desc: *TyDesc,
+        prev: *BoxRepr,
+        next: *BoxRepr,
+    }
+
+    pub struct BoxRepr {
+        header: BoxHeaderRepr,
+        data: u8
+    }
+
+}
+
+/// Determine if two shared boxes point to the same object
+#[inline(always)]
+pub fn ptr_eq<T>(a: @T, b: @T) -> bool {
+    let a_ptr: *T = to_unsafe_ptr(&*a), b_ptr: *T = to_unsafe_ptr(&*b);
+    a_ptr == b_ptr
+}
+
+/// Determine if two mutable shared boxes point to the same object
+#[inline(always)]
+pub fn mut_ptr_eq<T>(a: @mut T, b: @mut T) -> bool {
+    let a_ptr: *T = to_unsafe_ptr(&*a), b_ptr: *T = to_unsafe_ptr(&*b);
+    a_ptr == b_ptr
+}
+
+#[cfg(not(test))]
+impl<T:Eq> Eq for @T {
+    #[inline(always)]
+    fn eq(&self, other: &@T) -> bool { *(*self) == *(*other) }
+    #[inline(always)]
+    fn ne(&self, other: &@T) -> bool { *(*self) != *(*other) }
+}
+
+#[cfg(not(test))]
+impl<T:Eq> Eq for @mut T {
+    #[inline(always)]
+    fn eq(&self, other: &@mut T) -> bool { *(*self) == *(*other) }
+    #[inline(always)]
+    fn ne(&self, other: &@mut T) -> bool { *(*self) != *(*other) }
+}
+
+#[cfg(not(test))]
+impl<T:Ord> Ord for @T {
+    #[inline(always)]
+    fn lt(&self, other: &@T) -> bool { *(*self) < *(*other) }
+    #[inline(always)]
+    fn le(&self, other: &@T) -> bool { *(*self) <= *(*other) }
+    #[inline(always)]
+    fn ge(&self, other: &@T) -> bool { *(*self) >= *(*other) }
+    #[inline(always)]
+    fn gt(&self, other: &@T) -> bool { *(*self) > *(*other) }
+}
+
+#[cfg(not(test))]
+impl<T:Ord> Ord for @mut T {
+    #[inline(always)]
+    fn lt(&self, other: &@mut T) -> bool { *(*self) < *(*other) }
+    #[inline(always)]
+    fn le(&self, other: &@mut T) -> bool { *(*self) <= *(*other) }
+    #[inline(always)]
+    fn ge(&self, other: &@mut T) -> bool { *(*self) >= *(*other) }
+    #[inline(always)]
+    fn gt(&self, other: &@mut T) -> bool { *(*self) > *(*other) }
+}
+
+#[test]
+fn test() {
+    let x = @3;
+    let y = @3;
+    assert!((ptr_eq::<int>(x, x)));
+    assert!((ptr_eq::<int>(y, y)));
+    assert!((!ptr_eq::<int>(x, y)));
+    assert!((!ptr_eq::<int>(y, x)));
+}
diff --git a/src/libstd/md4.rs b/src/libstd/md4.rs
deleted file mode 100644
index da81f730eda..00000000000
--- a/src/libstd/md4.rs
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use core::str;
-use core::uint;
-use core::vec;
-
-struct Quad {
-    a: u32,
-    b: u32,
-    c: u32,
-    d: u32
-}
-
-pub fn md4(msg: &[u8]) -> Quad {
-    // subtle: if orig_len is merely uint, then the code below
-    // which performs shifts by 32 bits or more has undefined
-    // results.
-    let orig_len: u64 = (msg.len() * 8u) as u64;
-
-    // pad message
-    let mut msg = vec::append(vec::to_owned(msg), [0x80u8]);
-    let mut bitlen = orig_len + 8u64;
-    while (bitlen + 64u64) % 512u64 > 0u64 {
-        msg.push(0u8);
-        bitlen += 8u64;
-    }
-
-    // append length
-    let mut i = 0u64;
-    while i < 8u64 {
-        msg.push((orig_len >> (i * 8u64)) as u8);
-        i += 1u64;
-    }
-
-    let mut a = 0x67452301u32;
-    let mut b = 0xefcdab89u32;
-    let mut c = 0x98badcfeu32;
-    let mut d = 0x10325476u32;
-
-    fn rot(r: int, x: u32) -> u32 {
-        let r = r as u32;
-        (x << r) | (x >> (32u32 - r))
-    }
-
-    let mut i = 0u;
-    let e = msg.len();
-    let mut x = vec::from_elem(16u, 0u32);
-    while i < e {
-        let aa = a, bb = b, cc = c, dd = d;
-
-        let mut j = 0u, base = i;
-        while j < 16u {
-            x[j] = (msg[base] as u32) + (msg[base + 1u] as u32 << 8u32) +
-                (msg[base + 2u] as u32 << 16u32) +
-                (msg[base + 3u] as u32 << 24u32);
-            j += 1u; base += 4u;
-        }
-
-        let mut j = 0u;
-        while j < 16u {
-            a = rot(3, a + ((b & c) | (!b & d)) + x[j]);
-            j += 1u;
-            d = rot(7, d + ((a & b) | (!a & c)) + x[j]);
-            j += 1u;
-            c = rot(11, c + ((d & a) | (!d & b)) + x[j]);
-            j += 1u;
-            b = rot(19, b + ((c & d) | (!c & a)) + x[j]);
-            j += 1u;
-        }
-
-        let mut j = 0u;
-        let q = 0x5a827999u32;
-        while j < 4u {
-            a = rot(3, a + ((b & c) | ((b & d) | (c & d))) + x[j] + q);
-            d = rot(5, d + ((a & b) | ((a & c) | (b & c))) + x[j + 4u] + q);
-            c = rot(9, c + ((d & a) | ((d & b) | (a & b))) + x[j + 8u] + q);
-            b = rot(13, b + ((c & d) | ((c & a) | (d & a))) + x[j + 12u] + q);
-            j += 1u;
-        }
-
-        let mut j = 0u;
-        let q = 0x6ed9eba1u32;
-        while j < 8u {
-            let jj = if j > 2u { j - 3u } else { j };
-            a = rot(3, a + (b ^ c ^ d) + x[jj] + q);
-            d = rot(9, d + (a ^ b ^ c) + x[jj + 8u] + q);
-            c = rot(11, c + (d ^ a ^ b) + x[jj + 4u] + q);
-            b = rot(15, b + (c ^ d ^ a) + x[jj + 12u] + q);
-            j += 2u;
-        }
-
-        a += aa; b += bb; c += cc; d += dd;
-        i += 64u;
-    }
-    return Quad {a: a, b: b, c: c, d: d};
-}
-
-pub fn md4_str(msg: &[u8]) -> ~str {
-    let Quad {a, b, c, d} = md4(msg);
-    fn app(a: u32, b: u32, c: u32, d: u32, f: &fn(u32)) {
-        f(a); f(b); f(c); f(d);
-    }
-    let mut result = ~"";
-    do app(a, b, c, d) |u| {
-        let mut i = 0u32;
-        while i < 4u32 {
-            let byte = (u >> (i * 8u32)) as u8;
-            if byte <= 16u8 { result += ~"0"; }
-            result += uint::to_str_radix(byte as uint, 16u);
-            i += 1u32;
-        }
-    }
-    result
-}
-
-pub fn md4_text(msg: &str) -> ~str { md4_str(str::to_bytes(msg)) }
-
-#[test]
-fn test_md4() {
-    assert_eq!(md4_text(~""), ~"31d6cfe0d16ae931b73c59d7e0c089c0");
-    assert_eq!(md4_text(~"a"), ~"bde52cb31de33e46245e05fbdbd6fb24");
-    assert_eq!(md4_text(~"abc"), ~"a448017aaf21d8525fc10ae87aa6729d");
-    assert!(md4_text(~"message digest") ==
-        ~"d9130a8164549fe818874806e1c7014b");
-    assert!(md4_text(~"abcdefghijklmnopqrstuvwxyz") ==
-        ~"d79e1c308aa5bbcdeea8ed63df412da9");
-    assert!(md4_text(
-        ~"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\
-        0123456789") == ~"043f8582f241db351ce627e153e7f0e4");
-    assert!(md4_text(~"1234567890123456789012345678901234567890123456789\
-                     0123456789012345678901234567890") ==
-        ~"e33b4ddc9c38f2199c3e7b164fcc0536");
-}
diff --git a/src/libstd/net_ip.rs b/src/libstd/net_ip.rs
deleted file mode 100644
index 4f67f1c5f13..00000000000
--- a/src/libstd/net_ip.rs
+++ /dev/null
@@ -1,447 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Types/fns concerning Internet Protocol (IP), versions 4 & 6
-
-use core::libc;
-use core::comm::{stream, SharedChan};
-use core::ptr;
-use core::result;
-use core::str;
-
-use iotask = uv::iotask::IoTask;
-use interact = uv::iotask::interact;
-
-use sockaddr_in = super::uv_ll::sockaddr_in;
-use sockaddr_in6 = super::uv_ll::sockaddr_in6;
-use addrinfo = super::uv_ll::addrinfo;
-use uv_getaddrinfo_t = super::uv_ll::uv_getaddrinfo_t;
-use uv_ip4_name = super::uv_ll::ip4_name;
-use uv_ip4_port = super::uv_ll::ip4_port;
-use uv_ip6_name = super::uv_ll::ip6_name;
-use uv_ip6_port = super::uv_ll::ip6_port;
-use uv_getaddrinfo = super::uv_ll::getaddrinfo;
-use uv_freeaddrinfo = super::uv_ll::freeaddrinfo;
-use create_uv_getaddrinfo_t = super::uv_ll::getaddrinfo_t;
-use set_data_for_req = super::uv_ll::set_data_for_req;
-use get_data_for_req = super::uv_ll::get_data_for_req;
-use ll = super::uv_ll;
-
-/// An IP address
-pub enum IpAddr {
-    /// An IPv4 address
-    Ipv4(sockaddr_in),
-    Ipv6(sockaddr_in6)
-}
-
-/// Human-friendly feedback on why a parse_addr attempt failed
-pub struct ParseAddrErr {
-    err_msg: ~str,
-}
-
-/**
- * Convert a `IpAddr` to a str
- *
- * # Arguments
- *
- * * ip - a `std::net::ip::IpAddr`
- */
-pub fn format_addr(ip: &IpAddr) -> ~str {
-    match *ip {
-      Ipv4(ref addr) =>  unsafe {
-        let result = uv_ip4_name(addr);
-        if result == ~"" {
-            fail!("failed to convert inner sockaddr_in address to str")
-        }
-        result
-      },
-      Ipv6(ref addr) => unsafe {
-        let result = uv_ip6_name(addr);
-        if result == ~"" {
-            fail!("failed to convert inner sockaddr_in address to str")
-        }
-        result
-      }
-    }
-}
-
-/**
- * Get the associated port
- *
- * # Arguments
- * * ip - a `std::net::ip::IpAddr`
- */
-pub fn get_port(ip: &IpAddr) -> uint {
-    match *ip {
-        Ipv4(ref addr) => unsafe {
-            uv_ip4_port(addr)
-        },
-        Ipv6(ref addr) => unsafe {
-            uv_ip6_port(addr)
-        }
-    }
-}
-
-/// Represents errors returned from `net::ip::get_addr()`
-enum IpGetAddrErr {
-    GetAddrUnknownError
-}
-
-/**
- * Attempts name resolution on the provided `node` string
- *
- * # Arguments
- *
- * * `node` - a string representing some host address
- * * `iotask` - a `uv::iotask` used to interact with the underlying event loop
- *
- * # Returns
- *
- * A `result<~[ip_addr], ip_get_addr_err>` instance that will contain
- * a vector of `ip_addr` results, in the case of success, or an error
- * object in the case of failure
-*/
-pub fn get_addr(node: &str, iotask: &iotask)
-                -> result::Result<~[IpAddr], IpGetAddrErr> {
-    let (output_po, output_ch) = stream();
-    let mut output_ch = Some(SharedChan::new(output_ch));
-    do str::as_buf(node) |node_ptr, len| {
-        let output_ch = output_ch.swap_unwrap();
-        debug!("slice len %?", len);
-        let handle = create_uv_getaddrinfo_t();
-        let handle_ptr: *uv_getaddrinfo_t = &handle;
-        let handle_data = GetAddrData {
-            output_ch: output_ch.clone()
-        };
-        let handle_data_ptr: *GetAddrData = &handle_data;
-        do interact(iotask) |loop_ptr| {
-            unsafe {
-                let result = uv_getaddrinfo(
-                    loop_ptr,
-                    handle_ptr,
-                    get_addr_cb,
-                    node_ptr,
-                    ptr::null(),
-                    ptr::null());
-                match result {
-                    0i32 => {
-                        set_data_for_req(handle_ptr, handle_data_ptr);
-                    }
-                    _ => {
-                        output_ch.send(result::Err(GetAddrUnknownError));
-                    }
-                }
-            }
-        };
-        output_po.recv()
-    }
-}
-
-pub mod v4 {
-    use net::ip::{IpAddr, Ipv4, ParseAddrErr};
-    use uv::ll;
-    use uv_ip4_addr = uv::ll::ip4_addr;
-    use uv_ip4_name = uv::ll::ip4_name;
-
-    use core::cast::transmute;
-    use core::result;
-    use core::str;
-    use core::uint;
-    use core::vec;
-
-    /**
-     * Convert a str to `ip_addr`
-     *
-     * # Failure
-     *
-     * Fails if the string is not a valid IPv4 address
-     *
-     * # Arguments
-     *
-     * * ip - a string of the format `x.x.x.x`
-     *
-     * # Returns
-     *
-     * * an `ip_addr` of the `ipv4` variant
-     */
-    pub fn parse_addr(ip: &str) -> IpAddr {
-        match try_parse_addr(ip) {
-          result::Ok(addr) => addr,
-          result::Err(ref err_data) => fail!(copy err_data.err_msg)
-        }
-    }
-    // the simple, old style numberic representation of
-    // ipv4
-    pub struct Ipv4Rep { a: u8, b: u8, c: u8, d: u8 }
-
-    pub trait AsUnsafeU32 {
-        unsafe fn as_u32(&self) -> u32;
-    }
-
-    impl AsUnsafeU32 for Ipv4Rep {
-        // this is pretty dastardly, i know
-        unsafe fn as_u32(&self) -> u32 {
-            let this: &mut u32 = transmute(self);
-            *this
-        }
-    }
-    pub fn parse_to_ipv4_rep(ip: &str) -> result::Result<Ipv4Rep, ~str> {
-        let mut parts = ~[];
-        for str::each_split_char(ip, '.') |s| { parts.push(s.to_owned()) }
-        let parts = vec::map(parts, |s| {
-            match uint::from_str(*s) {
-              Some(n) if n <= 255 => n,
-              _ => 256
-            }
-        });
-        if parts.len() != 4 {
-            Err(fmt!("'%s' doesn't have 4 parts", ip))
-        } else if parts.contains(&256) {
-            Err(fmt!("invalid octal in addr '%s'", ip))
-        } else {
-            Ok(Ipv4Rep {
-                a: parts[0] as u8, b: parts[1] as u8,
-                c: parts[2] as u8, d: parts[3] as u8,
-            })
-        }
-    }
-    pub fn try_parse_addr(ip: &str) -> result::Result<IpAddr,ParseAddrErr> {
-        unsafe {
-            let INADDR_NONE = ll::get_INADDR_NONE();
-            let ip_rep_result = parse_to_ipv4_rep(ip);
-            if result::is_err(&ip_rep_result) {
-                let err_str = result::get_err(&ip_rep_result);
-                return result::Err(ParseAddrErr { err_msg: err_str })
-            }
-            // ipv4_rep.as_u32 is unsafe :/
-            let input_is_inaddr_none =
-                result::get(&ip_rep_result).as_u32() == INADDR_NONE;
-
-            let new_addr = uv_ip4_addr(str::to_owned(ip), 22);
-            let reformatted_name = uv_ip4_name(&new_addr);
-            debug!("try_parse_addr: input ip: %s reparsed ip: %s",
-                            ip, reformatted_name);
-            let ref_ip_rep_result = parse_to_ipv4_rep(reformatted_name);
-            if result::is_err(&ref_ip_rep_result) {
-                let err_str = result::get_err(&ref_ip_rep_result);
-                return Err(ParseAddrErr { err_msg: err_str })
-            }
-
-            if result::get(&ref_ip_rep_result).as_u32() == INADDR_NONE &&
-                 !input_is_inaddr_none {
-                Err(ParseAddrErr {
-                    err_msg: ~"uv_ip4_name produced invalid result.",
-                })
-            } else {
-                Ok(Ipv4(copy(new_addr)))
-            }
-        }
-    }
-}
-pub mod v6 {
-    use net::ip::{IpAddr, Ipv6, ParseAddrErr};
-    use uv_ip6_addr = uv::ll::ip6_addr;
-    use uv_ip6_name = uv::ll::ip6_name;
-
-    use core::result;
-    use core::str;
-
-    /**
-     * Convert a str to `ip_addr`
-     *
-     * # Failure
-     *
-     * Fails if the string is not a valid IPv6 address
-     *
-     * # Arguments
-     *
-     * * ip - an ipv6 string. See RFC2460 for spec.
-     *
-     * # Returns
-     *
-     * * an `ip_addr` of the `ipv6` variant
-     */
-    pub fn parse_addr(ip: &str) -> IpAddr {
-        match try_parse_addr(ip) {
-          result::Ok(addr) => addr,
-          result::Err(copy err_data) => fail!(copy err_data.err_msg)
-        }
-    }
-    pub fn try_parse_addr(ip: &str) -> result::Result<IpAddr,ParseAddrErr> {
-        unsafe {
-            // need to figure out how to establish a parse failure..
-            let new_addr = uv_ip6_addr(str::to_owned(ip), 22);
-            let reparsed_name = uv_ip6_name(&new_addr);
-            debug!("v6::try_parse_addr ip: '%s' reparsed '%s'",
-                            ip, reparsed_name);
-            // '::' appears to be uv_ip6_name() returns for bogus
-            // parses..
-            if  ip != &"::" && reparsed_name == ~"::" {
-                Err(ParseAddrErr { err_msg:fmt!("failed to parse '%s'", ip) })
-            }
-            else {
-                Ok(Ipv6(new_addr))
-            }
-        }
-    }
-}
-
-struct GetAddrData {
-    output_ch: SharedChan<result::Result<~[IpAddr],IpGetAddrErr>>
-}
-
-extern fn get_addr_cb(handle: *uv_getaddrinfo_t,
-                      status: libc::c_int,
-                      res: *addrinfo) {
-    unsafe {
-        debug!("in get_addr_cb");
-        let handle_data = get_data_for_req(handle) as
-            *GetAddrData;
-        let output_ch = (*handle_data).output_ch.clone();
-        if status == 0i32 {
-            if res != (ptr::null::<addrinfo>()) {
-                let mut out_vec = ~[];
-                debug!("initial addrinfo: %?", res);
-                let mut curr_addr = res;
-                loop {
-                    let new_ip_addr = if ll::is_ipv4_addrinfo(curr_addr) {
-                        Ipv4(copy((
-                            *ll::addrinfo_as_sockaddr_in(curr_addr))))
-                    }
-                    else if ll::is_ipv6_addrinfo(curr_addr) {
-                        Ipv6(copy((
-                            *ll::addrinfo_as_sockaddr_in6(curr_addr))))
-                    }
-                    else {
-                        debug!("curr_addr is not of family AF_INET or \
-                                AF_INET6. Error.");
-                        output_ch.send(
-                            result::Err(GetAddrUnknownError));
-                        break;
-                    };
-                    out_vec.push(new_ip_addr);
-
-                    let next_addr = ll::get_next_addrinfo(curr_addr);
-                    if next_addr == ptr::null::<addrinfo>() as *addrinfo {
-                        debug!("null next_addr encountered. no mas");
-                        break;
-                    }
-                    else {
-                        curr_addr = next_addr;
-                        debug!("next_addr addrinfo: %?", curr_addr);
-                    }
-                }
-                debug!("successful process addrinfo result, len: %?",
-                                out_vec.len());
-                output_ch.send(result::Ok(out_vec));
-            }
-            else {
-                debug!("addrinfo pointer is NULL");
-                output_ch.send(
-                    result::Err(GetAddrUnknownError));
-            }
-        }
-        else {
-            debug!("status != 0 error in get_addr_cb");
-            output_ch.send(
-                result::Err(GetAddrUnknownError));
-        }
-        if res != (ptr::null::<addrinfo>()) {
-            uv_freeaddrinfo(res);
-        }
-        debug!("leaving get_addr_cb");
-    }
-}
-
-#[cfg(test)]
-mod test {
-
-    use net_ip::*;
-    use net_ip::v4;
-    use net_ip::v6;
-    use uv;
-
-    use core::result;
-    use core::vec;
-
-    #[test]
-    fn test_ip_ipv4_parse_and_format_ip() {
-        let localhost_str = ~"127.0.0.1";
-        assert!(format_addr(&v4::parse_addr(localhost_str))
-                == localhost_str)
-    }
-    #[test]
-    fn test_ip_ipv6_parse_and_format_ip() {
-        let localhost_str = ~"::1";
-        let format_result = format_addr(&v6::parse_addr(localhost_str));
-        debug!("results: expected: '%s' actual: '%s'",
-            localhost_str, format_result);
-        assert_eq!(format_result, localhost_str);
-    }
-    #[test]
-    fn test_ip_ipv4_bad_parse() {
-        match v4::try_parse_addr(~"b4df00d") {
-          result::Err(ref err_info) => {
-            debug!("got error as expected %?", err_info);
-            assert!(true);
-          }
-          result::Ok(ref addr) => {
-            fail!("Expected failure, but got addr %?", addr);
-          }
-        }
-    }
-    #[test]
-    #[ignore(target_os="win32")]
-    fn test_ip_ipv6_bad_parse() {
-        match v6::try_parse_addr(~"::,~2234k;") {
-          result::Err(ref err_info) => {
-            debug!("got error as expected %?", err_info);
-            assert!(true);
-          }
-          result::Ok(ref addr) => {
-            fail!("Expected failure, but got addr %?", addr);
-          }
-        }
-    }
-    #[test]
-    #[ignore(reason = "valgrind says it's leaky")]
-    fn test_ip_get_addr() {
-        let localhost_name = ~"localhost";
-        let iotask = &uv::global_loop::get();
-        let ga_result = get_addr(localhost_name, iotask);
-        if result::is_err(&ga_result) {
-            fail!("got err result from net::ip::get_addr();")
-        }
-        // note really sure how to reliably test/assert
-        // this.. mostly just wanting to see it work, atm.
-        let results = result::unwrap(ga_result);
-        debug!("test_get_addr: Number of results for %s: %?",
-                        localhost_name, results.len());
-        for results.each |r| {
-            let ipv_prefix = match *r {
-              Ipv4(_) => ~"IPv4",
-              Ipv6(_) => ~"IPv6"
-            };
-            debug!("test_get_addr: result %s: '%s'",
-                            ipv_prefix, format_addr(r));
-        }
-        // at least one result.. this is going to vary from system
-        // to system, based on stuff like the contents of /etc/hosts
-        assert!(!results.is_empty());
-    }
-    #[test]
-    #[ignore(reason = "valgrind says it's leaky")]
-    fn test_ip_get_addr_bad_input() {
-        let localhost_name = ~"sjkl234m,./sdf";
-        let iotask = &uv::global_loop::get();
-        let ga_result = get_addr(localhost_name, iotask);
-        assert!(result::is_err(&ga_result));
-    }
-}
diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs
deleted file mode 100644
index db61679890b..00000000000
--- a/src/libstd/net_tcp.rs
+++ /dev/null
@@ -1,1970 +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.
-
-//! High-level interface to libuv's TCP functionality
-// FIXME #4425: Need FFI fixes
-
-use future;
-use future_spawn = future::spawn;
-use ip = net_ip;
-use uv;
-use uv::iotask;
-use uv::iotask::IoTask;
-
-use core::io;
-use core::libc::size_t;
-use core::libc;
-use core::comm::{stream, Port, SharedChan};
-use core::ptr;
-use core::result::{Result};
-use core::result;
-use core::uint;
-use core::vec;
-
-pub mod rustrt {
-    use core::libc;
-
-    #[nolink]
-    pub extern {
-        unsafe fn rust_uv_current_kernel_malloc(size: libc::c_uint)
-                                             -> *libc::c_void;
-        unsafe fn rust_uv_current_kernel_free(mem: *libc::c_void);
-        unsafe fn rust_uv_helper_uv_tcp_t_size() -> libc::c_uint;
-    }
-}
-
-/**
- * Encapsulates an open TCP/IP connection through libuv
- *
- * `TcpSocket` is non-copyable/sendable and automagically handles closing the
- * underlying libuv data structures when it goes out of scope. This is the
- * data structure that is used for read/write operations over a TCP stream.
- */
-pub struct TcpSocket {
-  socket_data: @TcpSocketData,
-}
-
-#[unsafe_destructor]
-impl Drop for TcpSocket {
-    fn finalize(&self) {
-        tear_down_socket_data(self.socket_data)
-    }
-}
-
-pub fn TcpSocket(socket_data: @TcpSocketData) -> TcpSocket {
-    TcpSocket {
-        socket_data: socket_data
-    }
-}
-
-/**
- * A buffered wrapper for `net::tcp::TcpSocket`
- *
- * It is created with a call to `net::tcp::socket_buf()` and has impls that
- * satisfy both the `io::Reader` and `io::Writer` traits.
- */
-pub struct TcpSocketBuf {
-    data: @mut TcpBufferedSocketData,
-    end_of_stream: @mut bool
-}
-
-pub fn TcpSocketBuf(data: @mut TcpBufferedSocketData) -> TcpSocketBuf {
-    TcpSocketBuf {
-        data: data,
-        end_of_stream: @mut false
-    }
-}
-
-/// Contains raw, string-based, error information returned from libuv
-pub struct TcpErrData {
-    err_name: ~str,
-    err_msg: ~str,
-}
-
-/// Details returned as part of a `Result::Err` result from `tcp::listen`
-pub enum TcpListenErrData {
-    /**
-     * Some unplanned-for error. The first and second fields correspond
-     * to libuv's `err_name` and `err_msg` fields, respectively.
-     */
-    GenericListenErr(~str, ~str),
-    /**
-     * Failed to bind to the requested IP/Port, because it is already in use.
-     *
-     * # Possible Causes
-     *
-     * * Attempting to bind to a port already bound to another listener
-     */
-    AddressInUse,
-    /**
-     * Request to bind to an IP/Port was denied by the system.
-     *
-     * # Possible Causes
-     *
-     * * Attemping to binding to an IP/Port as a non-Administrator
-     *   on Windows Vista+
-     * * Attempting to bind, as a non-priv'd
-     *   user, to 'privileged' ports (< 1024) on *nix
-     */
-    AccessDenied
-}
-/// Details returned as part of a `Result::Err` result from `tcp::connect`
-pub enum TcpConnectErrData {
-    /**
-     * Some unplanned-for error. The first and second fields correspond
-     * to libuv's `err_name` and `err_msg` fields, respectively.
-     */
-    GenericConnectErr(~str, ~str),
-    /// Invalid IP or invalid port
-    ConnectionRefused
-}
-
-/**
- * Initiate a client connection over TCP/IP
- *
- * # Arguments
- *
- * * `input_ip` - The IP address (versions 4 or 6) of the remote host
- * * `port` - the unsigned integer of the desired remote host port
- * * `iotask` - a `uv::iotask` that the tcp request will run on
- *
- * # Returns
- *
- * A `result` that, if the operation succeeds, contains a
- * `net::net::TcpSocket` that can be used to send and receive data to/from
- * the remote host. In the event of failure, a
- * `net::tcp::TcpConnectErrData` instance will be returned
- */
-pub fn connect(input_ip: ip::IpAddr, port: uint,
-               iotask: &IoTask)
-    -> result::Result<TcpSocket, TcpConnectErrData> {
-    unsafe {
-        let (result_po, result_ch) = stream::<ConnAttempt>();
-        let result_ch = SharedChan::new(result_ch);
-        let (closed_signal_po, closed_signal_ch) = stream::<()>();
-        let closed_signal_ch = SharedChan::new(closed_signal_ch);
-        let conn_data = ConnectReqData {
-            result_ch: result_ch,
-            closed_signal_ch: closed_signal_ch
-        };
-        let conn_data_ptr: *ConnectReqData = &conn_data;
-        let (reader_po, reader_ch) = stream::<Result<~[u8], TcpErrData>>();
-        let reader_ch = SharedChan::new(reader_ch);
-        let stream_handle_ptr = malloc_uv_tcp_t();
-        *(stream_handle_ptr as *mut uv::ll::uv_tcp_t) = uv::ll::tcp_t();
-        let socket_data = @TcpSocketData {
-            reader_po: @reader_po,
-            reader_ch: reader_ch,
-            stream_handle_ptr: stream_handle_ptr,
-            connect_req: uv::ll::connect_t(),
-            write_req: uv::ll::write_t(),
-            ipv6: match input_ip {
-                ip::Ipv4(_) => { false }
-                ip::Ipv6(_) => { true }
-            },
-            iotask: iotask.clone()
-        };
-        let socket_data_ptr: *TcpSocketData = &*socket_data;
-        // get an unsafe representation of our stream_handle_ptr that
-        // we can send into the interact cb to be handled in libuv..
-        debug!("stream_handle_ptr outside interact %?",
-                        stream_handle_ptr);
-        do iotask::interact(iotask) |loop_ptr| {
-            unsafe {
-                debug!("in interact cb for tcp client connect..");
-                debug!("stream_handle_ptr in interact %?",
-                                stream_handle_ptr);
-                match uv::ll::tcp_init( loop_ptr, stream_handle_ptr) {
-                    0i32 => {
-                        debug!("tcp_init successful");
-                        debug!("dealing w/ ipv4 connection..");
-                        let connect_req_ptr: *uv::ll::uv_connect_t =
-                            &(*socket_data_ptr).connect_req;
-                        let addr_str = ip::format_addr(&input_ip);
-                        let connect_result = match input_ip {
-                            ip::Ipv4(ref addr) => {
-                                // have to "recreate" the
-                                // sockaddr_in/6 since the ip_addr
-                                // discards the port info.. should
-                                // probably add an additional rust
-                                // type that actually is closer to
-                                // what the libuv API expects (ip str
-                                // + port num)
-                                debug!("addr: %?", addr);
-                                let in_addr = uv::ll::ip4_addr(addr_str,
-                                                               port as int);
-                                uv::ll::tcp_connect(
-                                    connect_req_ptr,
-                                    stream_handle_ptr,
-                                    &in_addr,
-                                    tcp_connect_on_connect_cb)
-                            }
-                            ip::Ipv6(ref addr) => {
-                                debug!("addr: %?", addr);
-                                let in_addr = uv::ll::ip6_addr(addr_str,
-                                                               port as int);
-                                uv::ll::tcp_connect6(
-                                    connect_req_ptr,
-                                    stream_handle_ptr,
-                                    &in_addr,
-                                    tcp_connect_on_connect_cb)
-                            }
-                        };
-                        match connect_result {
-                            0i32 => {
-                                debug!("tcp_connect successful: \
-                                        stream %x,
-                                        socket data %x",
-                                       stream_handle_ptr as uint,
-                                       socket_data_ptr as uint);
-                                // reusable data that we'll have for the
-                                // duration..
-                                uv::ll::set_data_for_uv_handle(
-                                    stream_handle_ptr,
-                                    socket_data_ptr as
-                                    *libc::c_void);
-                                // just so the connect_cb can send the
-                                // outcome..
-                                uv::ll::set_data_for_req(connect_req_ptr,
-                                                         conn_data_ptr);
-                                debug!("leaving tcp_connect interact cb...");
-                                // let tcp_connect_on_connect_cb send on
-                                // the result_ch, now..
-                            }
-                            _ => {
-                                // immediate connect
-                                // failure.. probably a garbage ip or
-                                // somesuch
-                                let err_data =
-                                    uv::ll::get_last_err_data(loop_ptr);
-                                let result_ch = (*conn_data_ptr)
-                                    .result_ch.clone();
-                                result_ch.send(ConnFailure(err_data));
-                                uv::ll::set_data_for_uv_handle(
-                                    stream_handle_ptr,
-                                    conn_data_ptr);
-                                uv::ll::close(stream_handle_ptr,
-                                              stream_error_close_cb);
-                            }
-                        }
-                    }
-                    _ => {
-                        // failure to create a tcp handle
-                        let err_data = uv::ll::get_last_err_data(loop_ptr);
-                        let result_ch = (*conn_data_ptr).result_ch.clone();
-                        result_ch.send(ConnFailure(err_data));
-                    }
-                }
-            }
-        }
-        match result_po.recv() {
-            ConnSuccess => {
-                debug!("tcp::connect - received success on result_po");
-                result::Ok(TcpSocket(socket_data))
-            }
-            ConnFailure(ref err_data) => {
-                closed_signal_po.recv();
-                debug!("tcp::connect - received failure on result_po");
-                // still have to free the malloc'd stream handle..
-                rustrt::rust_uv_current_kernel_free(stream_handle_ptr
-                                                    as *libc::c_void);
-                let tcp_conn_err = match err_data.err_name {
-                    ~"ECONNREFUSED" => ConnectionRefused,
-                    _ => GenericConnectErr(copy err_data.err_name,
-                                           copy err_data.err_msg)
-                };
-                result::Err(tcp_conn_err)
-            }
-        }
-    }
-}
-
-/**
- * Write binary data to a tcp stream; Blocks until operation completes
- *
- * # Arguments
- *
- * * sock - a `TcpSocket` to write to
- * * raw_write_data - a vector of `~[u8]` that will be written to the stream.
- * This value must remain valid for the duration of the `write` call
- *
- * # Returns
- *
- * A `Result` object with a `()` value as the `Ok` variant, or a
- * `TcpErrData` value as the `Err` variant
- */
-pub fn write(sock: &TcpSocket, raw_write_data: ~[u8])
-             -> result::Result<(), TcpErrData> {
-    let socket_data_ptr: *TcpSocketData = &*sock.socket_data;
-    write_common_impl(socket_data_ptr, raw_write_data)
-}
-
-/**
- * Write binary data to tcp stream; Returns a `future::Future` value
- * immediately
- *
- * # Safety
- *
- * This function can produce unsafe results if:
- *
- * 1. the call to `write_future` is made
- * 2. the `future::Future` value returned is never resolved via
- * `Future::get`
- * 3. and then the `TcpSocket` passed in to `write_future` leaves
- * scope and is destructed before the task that runs the libuv write
- * operation completes.
- *
- * As such: If using `write_future`, always be sure to resolve the returned
- * `Future` so as to ensure libuv doesn't try to access a released write
- * handle. Otherwise, use the blocking `tcp::write` function instead.
- *
- * # Arguments
- *
- * * sock - a `TcpSocket` to write to
- * * raw_write_data - a vector of `~[u8]` that will be written to the stream.
- * This value must remain valid for the duration of the `write` call
- *
- * # Returns
- *
- * A `Future` value that, once the `write` operation completes, resolves to a
- * `Result` object with a `nil` value as the `Ok` variant, or a `TcpErrData`
- * value as the `Err` variant
- */
-pub fn write_future(sock: &TcpSocket, raw_write_data: ~[u8])
-    -> future::Future<result::Result<(), TcpErrData>>
-{
-    let socket_data_ptr: *TcpSocketData = &*sock.socket_data;
-    do future_spawn {
-        let data_copy = copy(raw_write_data);
-        write_common_impl(socket_data_ptr, data_copy)
-    }
-}
-
-/**
- * Begin reading binary data from an open TCP connection; used with
- * `read_stop`
- *
- * # Arguments
- *
- * * sock -- a `net::tcp::TcpSocket` for the connection to read from
- *
- * # Returns
- *
- * * A `Result` instance that will either contain a
- * `core::comm::Port<Result<~[u8], TcpErrData>>` that the user can read
- * (and * optionally, loop on) from until `read_stop` is called, or a
- * `TcpErrData` record
- */
-pub fn read_start(sock: &TcpSocket)
-                  -> result::Result<@Port<result::Result<~[u8],
-                                                         TcpErrData>>,
-                                    TcpErrData> {
-    let socket_data: *TcpSocketData = &*sock.socket_data;
-    read_start_common_impl(socket_data)
-}
-
-/**
- * Stop reading from an open TCP connection; used with `read_start`
- *
- * # Arguments
- *
- * * `sock` - a `net::tcp::TcpSocket` that you wish to stop reading on
- */
-pub fn read_stop(sock: &TcpSocket) -> result::Result<(), TcpErrData> {
-    let socket_data: *TcpSocketData = &*sock.socket_data;
-    read_stop_common_impl(socket_data)
-}
-
-/**
- * Reads a single chunk of data from `TcpSocket`; block until data/error
- * recv'd
- *
- * Does a blocking read operation for a single chunk of data from a
- * `TcpSocket` until a data arrives or an error is received. The provided
- * `timeout_msecs` value is used to raise an error if the timeout period
- * passes without any data received.
- *
- * # Arguments
- *
- * * `sock` - a `net::tcp::TcpSocket` that you wish to read from
- * * `timeout_msecs` - a `uint` value, in msecs, to wait before dropping the
- * read attempt. Pass `0u` to wait indefinitely
- */
-pub fn read(sock: &TcpSocket, timeout_msecs: uint)
-            -> result::Result<~[u8],TcpErrData> {
-    let socket_data: *TcpSocketData = &*sock.socket_data;
-    read_common_impl(socket_data, timeout_msecs)
-}
-
-/**
- * Reads a single chunk of data; returns a `future::Future<~[u8]>`
- * immediately
- *
- * Does a non-blocking read operation for a single chunk of data from a
- * `TcpSocket` and immediately returns a `Future` value representing the
- * result. When resolving the returned `Future`, it will block until data
- * arrives or an error is received. The provided `timeout_msecs`
- * value is used to raise an error if the timeout period passes without any
- * data received.
- *
- * # Safety
- *
- * This function can produce unsafe results if the call to `read_future` is
- * made, the `future::Future` value returned is never resolved via
- * `Future::get`, and then the `TcpSocket` passed in to `read_future` leaves
- * scope and is destructed before the task that runs the libuv read
- * operation completes.
- *
- * As such: If using `read_future`, always be sure to resolve the returned
- * `Future` so as to ensure libuv doesn't try to access a released read
- * handle. Otherwise, use the blocking `tcp::read` function instead.
- *
- * # Arguments
- *
- * * `sock` - a `net::tcp::TcpSocket` that you wish to read from
- * * `timeout_msecs` - a `uint` value, in msecs, to wait before dropping the
- * read attempt. Pass `0u` to wait indefinitely
- */
-fn read_future(sock: &TcpSocket, timeout_msecs: uint)
-               -> future::Future<result::Result<~[u8],TcpErrData>> {
-    let socket_data: *TcpSocketData = &*sock.socket_data;
-    do future_spawn {
-        read_common_impl(socket_data, timeout_msecs)
-    }
-}
-
-/**
- * Bind an incoming client connection to a `net::tcp::TcpSocket`
- *
- * # Notes
- *
- * It is safe to call `net::tcp::accept` _only_ within the context of the
- * `new_connect_cb` callback provided as the final argument to the
- * `net::tcp::listen` function.
- *
- * The `new_conn` opaque value is provided _only_ as the first argument to the
- * `new_connect_cb` provided as a part of `net::tcp::listen`.
- * It can be safely sent to another task but it _must_ be
- * used (via `net::tcp::accept`) before the `new_connect_cb` call it was
- * provided to returns.
- *
- * This implies that a port/chan pair must be used to make sure that the
- * `new_connect_cb` call blocks until an attempt to create a
- * `net::tcp::TcpSocket` is completed.
- *
- * # Example
- *
- * Here, the `new_conn` is used in conjunction with `accept` from within
- * a task spawned by the `new_connect_cb` passed into `listen`
- *
- * ~~~~~~~~~~~
- * do net::tcp::listen(remote_ip, remote_port, backlog, iotask,
- *     // this callback is ran once after the connection is successfully
- *     // set up
- *     |kill_ch| {
- *       // pass the kill_ch to your main loop or wherever you want
- *       // to be able to externally kill the server from
- *     })
- *     // this callback is ran when a new connection arrives
- *     |new_conn, kill_ch| {
- *     let (cont_po, cont_ch) = comm::stream::<option::Option<TcpErrData>>();
- *     do task::spawn {
- *         let accept_result = net::tcp::accept(new_conn);
- *         match accept_result {
- *             Err(accept_error) => {
- *                 cont_ch.send(Some(accept_error));
- *                 // fail?
- *             },
- *             Ok(sock) => {
- *                 cont_ch.send(None);
- *                 // do work here
- *             }
- *         }
- *     };
- *     match cont_po.recv() {
- *       // shut down listen()
- *       Some(err_data) => kill_ch.send(Some(err_data)),
- *       // wait for next connection
- *       None => ()
- *     }
- * };
- * ~~~~~~~~~~~
- *
- * # Arguments
- *
- * * `new_conn` - an opaque value used to create a new `TcpSocket`
- *
- * # Returns
- *
- * On success, this function will return a `net::tcp::TcpSocket` as the
- * `Ok` variant of a `Result`. The `net::tcp::TcpSocket` is anchored within
- * the task that `accept` was called within for its lifetime. On failure,
- * this function will return a `net::tcp::TcpErrData` record
- * as the `Err` variant of a `Result`.
- */
-pub fn accept(new_conn: TcpNewConnection)
-    -> result::Result<TcpSocket, TcpErrData> {
-    unsafe {
-        match new_conn{
-            NewTcpConn(server_handle_ptr) => {
-                let server_data_ptr = uv::ll::get_data_for_uv_handle(
-                    server_handle_ptr) as *TcpListenFcData;
-                let (reader_po, reader_ch) = stream::<
-                    Result<~[u8], TcpErrData>>();
-                let reader_ch = SharedChan::new(reader_ch);
-                let iotask = &(*server_data_ptr).iotask;
-                let stream_handle_ptr = malloc_uv_tcp_t();
-                *(stream_handle_ptr as *mut uv::ll::uv_tcp_t) =
-                    uv::ll::tcp_t();
-                let client_socket_data: @TcpSocketData = @TcpSocketData {
-                    reader_po: @reader_po,
-                    reader_ch: reader_ch,
-                    stream_handle_ptr : stream_handle_ptr,
-                    connect_req : uv::ll::connect_t(),
-                    write_req : uv::ll::write_t(),
-                    ipv6: (*server_data_ptr).ipv6,
-                    iotask : iotask.clone()
-                };
-                let client_socket_data_ptr: *TcpSocketData =
-                    &*client_socket_data;
-                let client_stream_handle_ptr =
-                    (*client_socket_data_ptr).stream_handle_ptr;
-
-                let (result_po, result_ch) = stream::<Option<TcpErrData>>();
-                let result_ch = SharedChan::new(result_ch);
-
-                // UNSAFE LIBUV INTERACTION BEGIN
-                // .. normally this happens within the context of
-                // a call to uv::hl::interact.. but we're breaking
-                // the rules here because this always has to be
-                // called within the context of a listen() new_connect_cb
-                // callback (or it will likely fail and drown your cat)
-                debug!("in interact cb for tcp::accept");
-                let loop_ptr = uv::ll::get_loop_for_uv_handle(
-                    server_handle_ptr);
-                match uv::ll::tcp_init(loop_ptr, client_stream_handle_ptr) {
-                    0i32 => {
-                        debug!("uv_tcp_init successful for \
-                                     client stream");
-                        match uv::ll::accept(
-                            server_handle_ptr as *libc::c_void,
-                            client_stream_handle_ptr as *libc::c_void) {
-                            0i32 => {
-                                debug!("successfully accepted client \
-                                        connection: \
-                                        stream %x, \
-                                        socket data %x",
-                                       client_stream_handle_ptr as uint,
-                                       client_socket_data_ptr as uint);
-                                uv::ll::set_data_for_uv_handle(
-                                    client_stream_handle_ptr,
-                                    client_socket_data_ptr
-                                    as *libc::c_void);
-                                let ptr = uv::ll::get_data_for_uv_handle(
-                                    client_stream_handle_ptr);
-                                debug!("ptrs: %x %x",
-                                       client_socket_data_ptr as uint,
-                                       ptr as uint);
-                                result_ch.send(None);
-                            }
-                            _ => {
-                                debug!("failed to accept client conn");
-                                result_ch.send(Some(
-                                    uv::ll::get_last_err_data(
-                                        loop_ptr).to_tcp_err()));
-                            }
-                        }
-                    }
-                    _ => {
-                        debug!("failed to accept client stream");
-                        result_ch.send(Some(
-                            uv::ll::get_last_err_data(
-                                loop_ptr).to_tcp_err()));
-                    }
-                }
-                // UNSAFE LIBUV INTERACTION END
-                match result_po.recv() {
-                    Some(copy err_data) => result::Err(err_data),
-                    None => result::Ok(TcpSocket(client_socket_data))
-                }
-            }
-        }
-    }
-}
-
-/**
- * Bind to a given IP/port and listen for new connections
- *
- * # Arguments
- *
- * * `host_ip` - a `net::ip::IpAddr` representing a unique IP
- * (versions 4 or 6)
- * * `port` - a uint representing the port to listen on
- * * `backlog` - a uint representing the number of incoming connections
- * to cache in memory
- * * `hl_loop` - a `uv_iotask::IoTask` that the tcp request will run on
- * * `on_establish_cb` - a callback that is evaluated if/when the listener
- * is successfully established. it takes no parameters
- * * `new_connect_cb` - a callback to be evaluated, on the libuv thread,
- * whenever a client attempts to conect on the provided ip/port. the
- * callback's arguments are:
- *     * `new_conn` - an opaque type that can be passed to
- *     `net::tcp::accept` in order to be converted to a `TcpSocket`.
- *     * `kill_ch` - channel of type `core::comm::Chan<Option<tcp_err_data>>`.
- *     this channel can be used to send a message to cause `listen` to begin
- *     closing the underlying libuv data structures.
- *
- * # returns
- *
- * a `Result` instance containing empty data of type `()` on a
- * successful/normal shutdown, and a `TcpListenErrData` enum in the event
- * of listen exiting because of an error
- */
-pub fn listen(host_ip: ip::IpAddr, port: uint, backlog: uint,
-              iotask: &IoTask,
-              on_establish_cb: ~fn(SharedChan<Option<TcpErrData>>),
-              new_connect_cb: ~fn(TcpNewConnection,
-                                  SharedChan<Option<TcpErrData>>))
-    -> result::Result<(), TcpListenErrData> {
-    do listen_common(host_ip, port, backlog, iotask,
-                     on_establish_cb)
-        // on_connect_cb
-        |handle| {
-        unsafe {
-            let server_data_ptr = uv::ll::get_data_for_uv_handle(handle)
-                as *TcpListenFcData;
-            let new_conn = NewTcpConn(handle);
-            let kill_ch = (*server_data_ptr).kill_ch.clone();
-            new_connect_cb(new_conn, kill_ch);
-        }
-    }
-}
-
-fn listen_common(host_ip: ip::IpAddr,
-                 port: uint,
-                 backlog: uint,
-                 iotask: &IoTask,
-                 on_establish_cb: ~fn(SharedChan<Option<TcpErrData>>),
-                 on_connect_cb: ~fn(*uv::ll::uv_tcp_t))
-              -> result::Result<(), TcpListenErrData> {
-    let (stream_closed_po, stream_closed_ch) = stream::<()>();
-    let stream_closed_ch = SharedChan::new(stream_closed_ch);
-    let (kill_po, kill_ch) = stream::<Option<TcpErrData>>();
-    let kill_ch = SharedChan::new(kill_ch);
-    let server_stream = uv::ll::tcp_t();
-    let server_stream_ptr: *uv::ll::uv_tcp_t = &server_stream;
-    let server_data: TcpListenFcData = TcpListenFcData {
-        server_stream_ptr: server_stream_ptr,
-        stream_closed_ch: stream_closed_ch,
-        kill_ch: kill_ch.clone(),
-        on_connect_cb: on_connect_cb,
-        iotask: iotask.clone(),
-        ipv6: match &host_ip {
-            &ip::Ipv4(_) => { false }
-            &ip::Ipv6(_) => { true }
-        },
-        active: @mut true
-    };
-    let server_data_ptr: *TcpListenFcData = &server_data;
-
-    let (setup_po, setup_ch) = stream();
-
-    // this is to address a compiler warning about
-    // an implicit copy.. it seems that double nested
-    // will defeat a move sigil, as is done to the host_ip
-    // arg above.. this same pattern works w/o complaint in
-    // tcp::connect (because the iotask::interact cb isn't
-    // nested within a core::comm::listen block)
-    let loc_ip = copy(host_ip);
-    do iotask::interact(iotask) |loop_ptr| {
-        unsafe {
-            match uv::ll::tcp_init(loop_ptr, server_stream_ptr) {
-                0i32 => {
-                    uv::ll::set_data_for_uv_handle(
-                        server_stream_ptr,
-                        server_data_ptr);
-                    let addr_str = ip::format_addr(&loc_ip);
-                    let bind_result = match loc_ip {
-                        ip::Ipv4(ref addr) => {
-                            debug!("addr: %?", addr);
-                            let in_addr = uv::ll::ip4_addr(
-                                addr_str,
-                                port as int);
-                            uv::ll::tcp_bind(server_stream_ptr, &in_addr)
-                        }
-                        ip::Ipv6(ref addr) => {
-                            debug!("addr: %?", addr);
-                            let in_addr = uv::ll::ip6_addr(
-                                addr_str,
-                                port as int);
-                            uv::ll::tcp_bind6(server_stream_ptr, &in_addr)
-                        }
-                    };
-                    match bind_result {
-                        0i32 => {
-                            match uv::ll::listen(
-                                server_stream_ptr,
-                                backlog as libc::c_int,
-                                tcp_lfc_on_connection_cb) {
-                                0i32 => setup_ch.send(None),
-                                _ => {
-                                    debug!(
-                                        "failure to uv_tcp_init");
-                                    let err_data =
-                                        uv::ll::get_last_err_data(
-                                            loop_ptr);
-                                    setup_ch.send(Some(err_data));
-                                }
-                            }
-                        }
-                        _ => {
-                            debug!("failure to uv_tcp_bind");
-                            let err_data = uv::ll::get_last_err_data(
-                                loop_ptr);
-                            setup_ch.send(Some(err_data));
-                        }
-                    }
-                }
-                _ => {
-                    debug!("failure to uv_tcp_bind");
-                    let err_data = uv::ll::get_last_err_data(
-                        loop_ptr);
-                    setup_ch.send(Some(err_data));
-                }
-            }
-        }
-    }
-
-    let setup_result = setup_po.recv();
-
-    match setup_result {
-        Some(ref err_data) => {
-            do iotask::interact(iotask) |loop_ptr| {
-                unsafe {
-                    debug!(
-                        "tcp::listen post-kill recv hl interact %?",
-                             loop_ptr);
-                    *(*server_data_ptr).active = false;
-                    uv::ll::close(server_stream_ptr, tcp_lfc_close_cb);
-                }
-            };
-            stream_closed_po.recv();
-            match err_data.err_name {
-                ~"EACCES" => {
-                    debug!("Got EACCES error");
-                    result::Err(AccessDenied)
-                }
-                ~"EADDRINUSE" => {
-                    debug!("Got EADDRINUSE error");
-                    result::Err(AddressInUse)
-                }
-                _ => {
-                    debug!("Got '%s' '%s' libuv error",
-                                    err_data.err_name, err_data.err_msg);
-                    result::Err(
-                        GenericListenErr(copy err_data.err_name,
-                                         copy err_data.err_msg))
-                }
-            }
-        }
-        None => {
-            on_establish_cb(kill_ch.clone());
-            let kill_result = kill_po.recv();
-            do iotask::interact(iotask) |loop_ptr| {
-                unsafe {
-                    debug!(
-                        "tcp::listen post-kill recv hl interact %?",
-                             loop_ptr);
-                    *(*server_data_ptr).active = false;
-                    uv::ll::close(server_stream_ptr, tcp_lfc_close_cb);
-                }
-            };
-            stream_closed_po.recv();
-            match kill_result {
-                // some failure post bind/listen
-                Some(ref err_data) => result::Err(GenericListenErr(
-                    copy err_data.err_name,
-                    copy err_data.err_msg)),
-                // clean exit
-                None => result::Ok(())
-            }
-        }
-    }
-}
-
-
-/**
- * Convert a `net::tcp::TcpSocket` to a `net::tcp::TcpSocketBuf`.
- *
- * This function takes ownership of a `net::tcp::TcpSocket`, returning it
- * stored within a buffered wrapper, which can be converted to a `io::Reader`
- * or `io::Writer`
- *
- * # Arguments
- *
- * * `sock` -- a `net::tcp::TcpSocket` that you want to buffer
- *
- * # Returns
- *
- * A buffered wrapper that you can cast as an `io::Reader` or `io::Writer`
- */
-pub fn socket_buf(sock: TcpSocket) -> TcpSocketBuf {
-    TcpSocketBuf(@mut TcpBufferedSocketData {
-        sock: sock, buf: ~[], buf_off: 0
-    })
-}
-
-/// Convenience methods extending `net::tcp::TcpSocket`
-pub impl TcpSocket {
-    pub fn read_start(&self) -> result::Result<@Port<
-        result::Result<~[u8], TcpErrData>>, TcpErrData> {
-        read_start(self)
-    }
-    pub fn read_stop(&self) ->
-        result::Result<(), TcpErrData> {
-        read_stop(self)
-    }
-    fn read(&self, timeout_msecs: uint) ->
-        result::Result<~[u8], TcpErrData> {
-        read(self, timeout_msecs)
-    }
-    fn read_future(&self, timeout_msecs: uint) ->
-        future::Future<result::Result<~[u8], TcpErrData>> {
-        read_future(self, timeout_msecs)
-    }
-    pub fn write(&self, raw_write_data: ~[u8])
-        -> result::Result<(), TcpErrData> {
-        write(self, raw_write_data)
-    }
-    pub fn write_future(&self, raw_write_data: ~[u8])
-        -> future::Future<result::Result<(), TcpErrData>> {
-        write_future(self, raw_write_data)
-    }
-    pub fn get_peer_addr(&self) -> ip::IpAddr {
-        unsafe {
-            if self.socket_data.ipv6 {
-                let addr = uv::ll::ip6_addr("", 0);
-                uv::ll::tcp_getpeername6(self.socket_data.stream_handle_ptr,
-                                         &addr);
-                ip::Ipv6(addr)
-            } else {
-                let addr = uv::ll::ip4_addr("", 0);
-                uv::ll::tcp_getpeername(self.socket_data.stream_handle_ptr,
-                                        &addr);
-                ip::Ipv4(addr)
-            }
-        }
-    }
-}
-
-/// Implementation of `io::Reader` trait for a buffered `net::tcp::TcpSocket`
-impl io::Reader for TcpSocketBuf {
-    fn read(&self, buf: &mut [u8], len: uint) -> uint {
-        if len == 0 { return 0 }
-        let mut count: uint = 0;
-
-        loop {
-          assert!(count < len);
-
-          // If possible, copy up to `len` bytes from the internal
-          // `data.buf` into `buf`
-          let nbuffered = vec::uniq_len(&const self.data.buf) -
-                self.data.buf_off;
-          let needed = len - count;
-            if nbuffered > 0 {
-                unsafe {
-                    let ncopy = uint::min(nbuffered, needed);
-                    let dst = ptr::mut_offset(
-                        vec::raw::to_mut_ptr(buf), count);
-                    let src = ptr::offset(
-                        vec::raw::to_ptr(self.data.buf),
-                        self.data.buf_off);
-                    ptr::copy_memory(dst, src, ncopy);
-                    self.data.buf_off += ncopy;
-                    count += ncopy;
-                }
-          }
-
-          assert!(count <= len);
-          if count == len {
-              break;
-          }
-
-          // We copied all the bytes we had in the internal buffer into
-          // the result buffer, but the caller wants more bytes, so we
-          // need to read in data from the socket. Note that the internal
-          // buffer is of no use anymore as we read all bytes from it,
-          // so we can throw it away.
-          let read_result = {
-            let data = &*self.data;
-            read(&data.sock, 0)
-          };
-          if read_result.is_err() {
-              let err_data = read_result.get_err();
-
-              if err_data.err_name == ~"EOF" {
-                  *self.end_of_stream = true;
-                  break;
-              } else {
-                  debug!("ERROR sock_buf as io::reader.read err %? %?",
-                         err_data.err_name, err_data.err_msg);
-                  // As we have already copied data into result buffer,
-                  // we cannot simply return 0 here. Instead the error
-                  // should show up in a later call to read().
-                  break;
-              }
-          } else {
-              self.data.buf = result::unwrap(read_result);
-              self.data.buf_off = 0;
-          }
-        }
-
-        count
-    }
-    fn read_byte(&self) -> int {
-        loop {
-          if vec::uniq_len(&const self.data.buf) > self.data.buf_off {
-            let c = self.data.buf[self.data.buf_off];
-            self.data.buf_off += 1;
-            return c as int
-          }
-
-          let read_result = {
-            let data = &*self.data;
-            read(&data.sock, 0)
-          };
-          if read_result.is_err() {
-              let err_data = read_result.get_err();
-
-              if err_data.err_name == ~"EOF" {
-                  *self.end_of_stream = true;
-                  return -1
-              } else {
-                  debug!("ERROR sock_buf as io::reader.read err %? %?",
-                         err_data.err_name, err_data.err_msg);
-                  fail!()
-              }
-          } else {
-              self.data.buf = result::unwrap(read_result);
-              self.data.buf_off = 0;
-          }
-        }
-    }
-    fn eof(&self) -> bool {
-        *self.end_of_stream
-    }
-    fn seek(&self, dist: int, seek: io::SeekStyle) {
-        debug!("tcp_socket_buf seek stub %? %?", dist, seek);
-        // noop
-    }
-    fn tell(&self) -> uint {
-        0u // noop
-    }
-}
-
-/// Implementation of `io::Reader` trait for a buffered `net::tcp::TcpSocket`
-impl io::Writer for TcpSocketBuf {
-    pub fn write(&self, data: &[u8]) {
-        let socket_data_ptr: *TcpSocketData =
-            &(*((*(self.data)).sock).socket_data);
-        let w_result = write_common_impl(socket_data_ptr,
-                                         vec::slice(data,
-                                                    0,
-                                                    data.len()).to_vec());
-        if w_result.is_err() {
-            let err_data = w_result.get_err();
-            debug!(
-                "ERROR sock_buf as io::writer.writer err: %? %?",
-                err_data.err_name, err_data.err_msg);
-        }
-    }
-    fn seek(&self, dist: int, seek: io::SeekStyle) {
-      debug!("tcp_socket_buf seek stub %? %?", dist, seek);
-        // noop
-    }
-    fn tell(&self) -> uint {
-        0u
-    }
-    fn flush(&self) -> int {
-        0
-    }
-    fn get_type(&self) -> io::WriterType {
-        io::File
-    }
-}
-
-// INTERNAL API
-
-fn tear_down_socket_data(socket_data: @TcpSocketData) {
-    unsafe {
-        let (closed_po, closed_ch) = stream::<()>();
-        let closed_ch = SharedChan::new(closed_ch);
-        let close_data = TcpSocketCloseData {
-            closed_ch: closed_ch
-        };
-        let close_data_ptr: *TcpSocketCloseData = &close_data;
-        let stream_handle_ptr = (*socket_data).stream_handle_ptr;
-        do iotask::interact(&(*socket_data).iotask) |loop_ptr| {
-            unsafe {
-                debug!(
-                    "interact dtor for tcp_socket stream %? loop %?",
-                         stream_handle_ptr, loop_ptr);
-                uv::ll::set_data_for_uv_handle(stream_handle_ptr,
-                                               close_data_ptr);
-                uv::ll::close(stream_handle_ptr, tcp_socket_dtor_close_cb);
-            }
-        };
-        closed_po.recv();
-        //the line below will most likely crash
-        //log(debug, fmt!("about to free socket_data at %?", socket_data));
-        rustrt::rust_uv_current_kernel_free(stream_handle_ptr
-                                            as *libc::c_void);
-        debug!("exiting dtor for tcp_socket");
-    }
-}
-
-// shared implementation for tcp::read
-fn read_common_impl(socket_data: *TcpSocketData, timeout_msecs: uint)
-    -> result::Result<~[u8],TcpErrData> {
-    unsafe {
-        use timer;
-
-        debug!("starting tcp::read");
-        let iotask = &(*socket_data).iotask;
-        let rs_result = read_start_common_impl(socket_data);
-        if result::is_err(&rs_result) {
-            let err_data = result::get_err(&rs_result);
-            result::Err(err_data)
-        }
-        else {
-            debug!("tcp::read before recv_timeout");
-            let read_result = if timeout_msecs > 0u {
-                timer::recv_timeout(
-                    iotask, timeout_msecs, result::unwrap(rs_result))
-            } else {
-                Some(result::get(&rs_result).recv())
-            };
-            debug!("tcp::read after recv_timeout");
-            match read_result {
-                None => {
-                    debug!("tcp::read: timed out..");
-                    let err_data = TcpErrData {
-                        err_name: ~"TIMEOUT",
-                        err_msg: ~"req timed out"
-                    };
-                    read_stop_common_impl(socket_data);
-                    result::Err(err_data)
-                }
-                Some(data_result) => {
-                    debug!("tcp::read got data");
-                    read_stop_common_impl(socket_data);
-                    data_result
-                }
-            }
-        }
-    }
-}
-
-// shared impl for read_stop
-fn read_stop_common_impl(socket_data: *TcpSocketData) ->
-    result::Result<(), TcpErrData> {
-    unsafe {
-        let stream_handle_ptr = (*socket_data).stream_handle_ptr;
-        let (stop_po, stop_ch) = stream::<Option<TcpErrData>>();
-        do iotask::interact(&(*socket_data).iotask) |loop_ptr| {
-            unsafe {
-                debug!("in interact cb for tcp::read_stop");
-                match uv::ll::read_stop(stream_handle_ptr
-                                        as *uv::ll::uv_stream_t) {
-                    0i32 => {
-                        debug!("successfully called uv_read_stop");
-                        stop_ch.send(None);
-                    }
-                    _ => {
-                        debug!("failure in calling uv_read_stop");
-                        let err_data = uv::ll::get_last_err_data(loop_ptr);
-                        stop_ch.send(Some(err_data.to_tcp_err()));
-                    }
-                }
-            }
-        }
-        match stop_po.recv() {
-            Some(err_data) => Err(err_data),
-            None => Ok(())
-        }
-    }
-}
-
-// shared impl for read_start
-fn read_start_common_impl(socket_data: *TcpSocketData)
-    -> result::Result<@Port<
-        result::Result<~[u8], TcpErrData>>, TcpErrData> {
-    unsafe {
-        let stream_handle_ptr = (*socket_data).stream_handle_ptr;
-        let (start_po, start_ch) = stream::<Option<uv::ll::uv_err_data>>();
-        debug!("in tcp::read_start before interact loop");
-        do iotask::interact(&(*socket_data).iotask) |loop_ptr| {
-            unsafe {
-                debug!("in tcp::read_start interact cb %?",
-                                loop_ptr);
-                match uv::ll::read_start(stream_handle_ptr
-                                         as *uv::ll::uv_stream_t,
-                                         on_alloc_cb,
-                                         on_tcp_read_cb) {
-                    0i32 => {
-                        debug!("success doing uv_read_start");
-                        start_ch.send(None);
-                    }
-                    _ => {
-                        debug!("error attempting uv_read_start");
-                        let err_data = uv::ll::get_last_err_data(loop_ptr);
-                        start_ch.send(Some(err_data));
-                    }
-                }
-            }
-        }
-        match start_po.recv() {
-            Some(ref err_data) => result::Err(
-                err_data.to_tcp_err()),
-            None => {
-                result::Ok((*socket_data).reader_po)
-            }
-        }
-    }
-}
-
-// helper to convert a "class" vector of [u8] to a *[uv::ll::uv_buf_t]
-
-// shared implementation used by write and write_future
-fn write_common_impl(socket_data_ptr: *TcpSocketData,
-                     raw_write_data: ~[u8])
-    -> result::Result<(), TcpErrData> {
-    unsafe {
-        let write_req_ptr: *uv::ll::uv_write_t =
-            &(*socket_data_ptr).write_req;
-        let stream_handle_ptr =
-            (*socket_data_ptr).stream_handle_ptr;
-        let write_buf_vec = ~[
-            uv::ll::buf_init(vec::raw::to_ptr(raw_write_data),
-                             raw_write_data.len())
-        ];
-        let write_buf_vec_ptr: *~[uv::ll::uv_buf_t] = &write_buf_vec;
-        let (result_po, result_ch) = stream::<TcpWriteResult>();
-        let result_ch = SharedChan::new(result_ch);
-        let write_data = WriteReqData {
-            result_ch: result_ch
-        };
-        let write_data_ptr: *WriteReqData = &write_data;
-        do iotask::interact(&(*socket_data_ptr).iotask) |loop_ptr| {
-            unsafe {
-                debug!("in interact cb for tcp::write %?",
-                                loop_ptr);
-                match uv::ll::write(write_req_ptr,
-                                    stream_handle_ptr,
-                                    write_buf_vec_ptr,
-                                    tcp_write_complete_cb) {
-                    0i32 => {
-                        debug!("uv_write() invoked successfully");
-                        uv::ll::set_data_for_req(write_req_ptr,
-                                                 write_data_ptr);
-                    }
-                    _ => {
-                        debug!("error invoking uv_write()");
-                        let err_data = uv::ll::get_last_err_data(loop_ptr);
-                        let result_ch = (*write_data_ptr).result_ch.clone();
-                        result_ch.send(TcpWriteError(err_data.to_tcp_err()));
-                    }
-                }
-            }
-        }
-        // FIXME (#2656): Instead of passing unsafe pointers to local data,
-        // and waiting here for the write to complete, we should transfer
-        // ownership of everything to the I/O task and let it deal with the
-        // aftermath, so we don't have to sit here blocking.
-        match result_po.recv() {
-            TcpWriteSuccess => Ok(()),
-            TcpWriteError(err_data) => Err(err_data)
-        }
-    }
-}
-
-enum TcpNewConnection {
-    NewTcpConn(*uv::ll::uv_tcp_t)
-}
-
-struct TcpListenFcData {
-    server_stream_ptr: *uv::ll::uv_tcp_t,
-    stream_closed_ch: SharedChan<()>,
-    kill_ch: SharedChan<Option<TcpErrData>>,
-    on_connect_cb: ~fn(*uv::ll::uv_tcp_t),
-    iotask: IoTask,
-    ipv6: bool,
-    active: @mut bool,
-}
-
-extern fn tcp_lfc_close_cb(handle: *uv::ll::uv_tcp_t) {
-    unsafe {
-        let server_data_ptr = uv::ll::get_data_for_uv_handle(
-            handle) as *TcpListenFcData;
-        let stream_closed_ch = (*server_data_ptr).stream_closed_ch.clone();
-        stream_closed_ch.send(());
-    }
-}
-
-extern fn tcp_lfc_on_connection_cb(handle: *uv::ll::uv_tcp_t,
-                                     status: libc::c_int) {
-    unsafe {
-        let server_data_ptr = uv::ll::get_data_for_uv_handle(handle)
-            as *TcpListenFcData;
-        let kill_ch = (*server_data_ptr).kill_ch.clone();
-        if *(*server_data_ptr).active {
-            match status {
-              0i32 => ((*server_data_ptr).on_connect_cb)(handle),
-              _ => {
-                let loop_ptr = uv::ll::get_loop_for_uv_handle(handle);
-                kill_ch.send(
-                           Some(uv::ll::get_last_err_data(loop_ptr)
-                                .to_tcp_err()));
-                *(*server_data_ptr).active = false;
-              }
-            }
-        }
-    }
-}
-
-fn malloc_uv_tcp_t() -> *uv::ll::uv_tcp_t {
-    unsafe {
-        rustrt::rust_uv_current_kernel_malloc(
-            rustrt::rust_uv_helper_uv_tcp_t_size()) as *uv::ll::uv_tcp_t
-    }
-}
-
-enum TcpConnectResult {
-    TcpConnected(TcpSocket),
-    TcpConnectError(TcpErrData)
-}
-
-enum TcpWriteResult {
-    TcpWriteSuccess,
-    TcpWriteError(TcpErrData)
-}
-
-enum TcpReadStartResult {
-    TcpReadStartSuccess(Port<TcpReadResult>),
-    TcpReadStartError(TcpErrData)
-}
-
-enum TcpReadResult {
-    TcpReadData(~[u8]),
-    TcpReadDone,
-    TcpReadErr(TcpErrData)
-}
-
-trait ToTcpErr {
-    fn to_tcp_err(&self) -> TcpErrData;
-}
-
-impl ToTcpErr for uv::ll::uv_err_data {
-    fn to_tcp_err(&self) -> TcpErrData {
-        TcpErrData { err_name: copy self.err_name, err_msg: copy self.err_msg }
-    }
-}
-
-extern fn on_tcp_read_cb(stream: *uv::ll::uv_stream_t,
-                         nread: libc::ssize_t,
-                         buf: uv::ll::uv_buf_t) {
-    unsafe {
-        debug!("entering on_tcp_read_cb stream: %x nread: %?",
-                        stream as uint, nread);
-        let loop_ptr = uv::ll::get_loop_for_uv_handle(stream);
-        let socket_data_ptr = uv::ll::get_data_for_uv_handle(stream)
-            as *TcpSocketData;
-        debug!("socket data is %x", socket_data_ptr as uint);
-        match nread as int {
-          // incoming err.. probably eof
-          -1 => {
-            let err_data = uv::ll::get_last_err_data(loop_ptr).to_tcp_err();
-            debug!("on_tcp_read_cb: incoming err.. name %? msg %?",
-                            err_data.err_name, err_data.err_msg);
-            let reader_ch = &(*socket_data_ptr).reader_ch;
-            reader_ch.send(result::Err(err_data));
-          }
-          // do nothing .. unneeded buf
-          0 => (),
-          // have data
-          _ => {
-            // we have data
-            debug!("tcp on_read_cb nread: %d", nread as int);
-            let reader_ch = &(*socket_data_ptr).reader_ch;
-            let buf_base = uv::ll::get_base_from_buf(buf);
-            let new_bytes = vec::from_buf(buf_base, nread as uint);
-            reader_ch.send(result::Ok(new_bytes));
-          }
-        }
-        uv::ll::free_base_of_buf(buf);
-        debug!("exiting on_tcp_read_cb");
-    }
-}
-
-extern fn on_alloc_cb(handle: *libc::c_void,
-                      suggested_size: size_t)
-    -> uv::ll::uv_buf_t {
-    unsafe {
-        debug!("tcp read on_alloc_cb!");
-        let char_ptr = uv::ll::malloc_buf_base_of(suggested_size);
-        debug!("tcp read on_alloc_cb h: %? char_ptr: %u sugsize: %u",
-                         handle,
-                         char_ptr as uint,
-                         suggested_size as uint);
-        uv::ll::buf_init(char_ptr, suggested_size as uint)
-    }
-}
-
-struct TcpSocketCloseData {
-    closed_ch: SharedChan<()>,
-}
-
-extern fn tcp_socket_dtor_close_cb(handle: *uv::ll::uv_tcp_t) {
-    unsafe {
-        let data = uv::ll::get_data_for_uv_handle(handle)
-            as *TcpSocketCloseData;
-        let closed_ch = (*data).closed_ch.clone();
-        closed_ch.send(());
-        debug!("tcp_socket_dtor_close_cb exiting..");
-    }
-}
-
-extern fn tcp_write_complete_cb(write_req: *uv::ll::uv_write_t,
-                              status: libc::c_int) {
-    unsafe {
-        let write_data_ptr = uv::ll::get_data_for_req(write_req)
-            as *WriteReqData;
-        if status == 0i32 {
-            debug!("successful write complete");
-            let result_ch = (*write_data_ptr).result_ch.clone();
-            result_ch.send(TcpWriteSuccess);
-        } else {
-            let stream_handle_ptr = uv::ll::get_stream_handle_from_write_req(
-                write_req);
-            let loop_ptr = uv::ll::get_loop_for_uv_handle(stream_handle_ptr);
-            let err_data = uv::ll::get_last_err_data(loop_ptr);
-            debug!("failure to write");
-            let result_ch = (*write_data_ptr).result_ch.clone();
-            result_ch.send(TcpWriteError(err_data.to_tcp_err()));
-        }
-    }
-}
-
-struct WriteReqData {
-    result_ch: SharedChan<TcpWriteResult>,
-}
-
-struct ConnectReqData {
-    result_ch: SharedChan<ConnAttempt>,
-    closed_signal_ch: SharedChan<()>,
-}
-
-extern fn stream_error_close_cb(handle: *uv::ll::uv_tcp_t) {
-    unsafe {
-        let data = uv::ll::get_data_for_uv_handle(handle) as
-            *ConnectReqData;
-        let closed_signal_ch = (*data).closed_signal_ch.clone();
-        closed_signal_ch.send(());
-        debug!("exiting steam_error_close_cb for %?", handle);
-    }
-}
-
-extern fn tcp_connect_close_cb(handle: *uv::ll::uv_tcp_t) {
-    debug!("closed client tcp handle %?", handle);
-}
-
-extern fn tcp_connect_on_connect_cb(connect_req_ptr: *uv::ll::uv_connect_t,
-                                   status: libc::c_int) {
-    unsafe {
-        let conn_data_ptr = (uv::ll::get_data_for_req(connect_req_ptr)
-                          as *ConnectReqData);
-        let result_ch = (*conn_data_ptr).result_ch.clone();
-        debug!("tcp_connect result_ch %?", result_ch);
-        let tcp_stream_ptr =
-            uv::ll::get_stream_handle_from_connect_req(connect_req_ptr);
-        match status {
-          0i32 => {
-            debug!("successful tcp connection!");
-            result_ch.send(ConnSuccess);
-          }
-          _ => {
-            debug!("error in tcp_connect_on_connect_cb");
-            let loop_ptr = uv::ll::get_loop_for_uv_handle(tcp_stream_ptr);
-            let err_data = uv::ll::get_last_err_data(loop_ptr);
-            debug!("err_data %? %?", err_data.err_name,
-                            err_data.err_msg);
-            result_ch.send(ConnFailure(err_data));
-            uv::ll::set_data_for_uv_handle(tcp_stream_ptr,
-                                           conn_data_ptr);
-            uv::ll::close(tcp_stream_ptr, stream_error_close_cb);
-          }
-        }
-        debug!("leaving tcp_connect_on_connect_cb");
-    }
-}
-
-enum ConnAttempt {
-    ConnSuccess,
-    ConnFailure(uv::ll::uv_err_data)
-}
-
-struct TcpSocketData {
-    reader_po: @Port<result::Result<~[u8], TcpErrData>>,
-    reader_ch: SharedChan<result::Result<~[u8], TcpErrData>>,
-    stream_handle_ptr: *uv::ll::uv_tcp_t,
-    connect_req: uv::ll::uv_connect_t,
-    write_req: uv::ll::uv_write_t,
-    ipv6: bool,
-    iotask: IoTask,
-}
-
-struct TcpBufferedSocketData {
-    sock: TcpSocket,
-    buf: ~[u8],
-    buf_off: uint
-}
-
-#[cfg(test)]
-mod test {
-    use net::ip;
-    use net::tcp::{GenericListenErr, TcpConnectErrData, TcpListenErrData};
-    use net::tcp::{connect, accept, read, listen, TcpSocket, socket_buf};
-    use net;
-    use uv::iotask::IoTask;
-    use uv;
-
-    use core::cell::Cell;
-    use core::comm::{stream, SharedChan};
-
-    // FIXME don't run on fbsd or linux 32 bit (#2064)
-    #[cfg(target_os="win32")]
-    #[cfg(target_os="darwin")]
-    #[cfg(target_os="linux")]
-    #[cfg(target_os="android")]
-    mod tcp_ipv4_server_and_client_test {
-        #[cfg(target_arch="x86_64")]
-        mod impl64 {
-            use net::tcp::test::*;
-
-            #[test]
-            fn test_gl_tcp_server_and_client_ipv4() {
-                unsafe {
-                    impl_gl_tcp_ipv4_server_and_client();
-                }
-            }
-            #[test]
-            fn test_gl_tcp_get_peer_addr() {
-                unsafe {
-                    impl_gl_tcp_ipv4_get_peer_addr();
-                }
-            }
-            #[test]
-            fn test_gl_tcp_ipv4_client_error_connection_refused() {
-                unsafe {
-                    impl_gl_tcp_ipv4_client_error_connection_refused();
-                }
-            }
-            #[test]
-            fn test_gl_tcp_server_address_in_use() {
-                unsafe {
-                    impl_gl_tcp_ipv4_server_address_in_use();
-                }
-            }
-            #[test]
-            fn test_gl_tcp_server_access_denied() {
-                unsafe {
-                    impl_gl_tcp_ipv4_server_access_denied();
-                }
-            }
-            // Strange failure on Windows. --pcwalton
-            #[test]
-            #[ignore(cfg(target_os = "win32"))]
-            fn test_gl_tcp_ipv4_server_client_reader_writer() {
-                impl_gl_tcp_ipv4_server_client_reader_writer();
-            }
-            #[test]
-            fn test_tcp_socket_impl_reader_handles_eof() {
-                impl_tcp_socket_impl_reader_handles_eof();
-            }
-        }
-        #[cfg(target_arch="x86")]
-        #[cfg(target_arch="arm")]
-        #[cfg(target_arch="mips")]
-        mod impl32 {
-            use net::tcp::test::*;
-
-            #[test]
-            #[ignore(cfg(target_os = "linux"))]
-            fn test_gl_tcp_server_and_client_ipv4() {
-                unsafe {
-                    impl_gl_tcp_ipv4_server_and_client();
-                }
-            }
-            #[test]
-            #[ignore(cfg(target_os = "linux"))]
-            fn test_gl_tcp_get_peer_addr() {
-                unsafe {
-                    impl_gl_tcp_ipv4_get_peer_addr();
-                }
-            }
-            #[test]
-            #[ignore(cfg(target_os = "linux"))]
-            fn test_gl_tcp_ipv4_client_error_connection_refused() {
-                unsafe {
-                    impl_gl_tcp_ipv4_client_error_connection_refused();
-                }
-            }
-            #[test]
-            #[ignore(cfg(target_os = "linux"))]
-            fn test_gl_tcp_server_address_in_use() {
-                unsafe {
-                    impl_gl_tcp_ipv4_server_address_in_use();
-                }
-            }
-            #[test]
-            #[ignore(cfg(target_os = "linux"))]
-            #[ignore(cfg(windows), reason = "deadlocking bots")]
-            fn test_gl_tcp_server_access_denied() {
-                unsafe {
-                    impl_gl_tcp_ipv4_server_access_denied();
-                }
-            }
-            #[test]
-            #[ignore(cfg(target_os = "linux"))]
-            #[ignore(cfg(target_os = "win32"))]
-            fn test_gl_tcp_ipv4_server_client_reader_writer() {
-                impl_gl_tcp_ipv4_server_client_reader_writer();
-            }
-        }
-    }
-    pub fn impl_gl_tcp_ipv4_server_and_client() {
-        let hl_loop = &uv::global_loop::get();
-        let server_ip = "127.0.0.1";
-        let server_port = 8888u;
-        let expected_req = ~"ping";
-        let expected_resp = "pong";
-
-        let (server_result_po, server_result_ch) = stream::<~str>();
-
-        let (cont_po, cont_ch) = stream::<()>();
-        let cont_ch = SharedChan::new(cont_ch);
-        // server
-        let hl_loop_clone = hl_loop.clone();
-        do task::spawn_sched(task::ManualThreads(1u)) {
-            let cont_ch = cont_ch.clone();
-            let actual_req = run_tcp_test_server(
-                server_ip,
-                server_port,
-                expected_resp.to_str(),
-                cont_ch.clone(),
-                &hl_loop_clone);
-            server_result_ch.send(actual_req);
-        };
-        cont_po.recv();
-        // client
-        debug!("server started, firing up client..");
-        let actual_resp_result = run_tcp_test_client(
-            server_ip,
-            server_port,
-            expected_req,
-            hl_loop);
-        assert!(actual_resp_result.is_ok());
-        let actual_resp = actual_resp_result.get();
-        let actual_req = server_result_po.recv();
-        debug!("REQ: expected: '%s' actual: '%s'",
-                       expected_req, actual_req);
-        debug!("RESP: expected: '%s' actual: '%s'",
-                       expected_resp, actual_resp);
-        assert!(str::contains(actual_req, expected_req));
-        assert!(str::contains(actual_resp, expected_resp));
-    }
-    pub fn impl_gl_tcp_ipv4_get_peer_addr() {
-        let hl_loop = &uv::global_loop::get();
-        let server_ip = "127.0.0.1";
-        let server_port = 8887u;
-        let expected_resp = "pong";
-
-        let (cont_po, cont_ch) = stream::<()>();
-        let cont_ch = SharedChan::new(cont_ch);
-        // server
-        let hl_loop_clone = hl_loop.clone();
-        do task::spawn_sched(task::ManualThreads(1u)) {
-            let cont_ch = cont_ch.clone();
-            run_tcp_test_server(
-                server_ip,
-                server_port,
-                expected_resp.to_str(),
-                cont_ch.clone(),
-                &hl_loop_clone);
-        };
-        cont_po.recv();
-        // client
-        debug!("server started, firing up client..");
-        let server_ip_addr = ip::v4::parse_addr(server_ip);
-        let iotask = uv::global_loop::get();
-        let connect_result = connect(server_ip_addr, server_port,
-                                     &iotask);
-
-        let sock = result::unwrap(connect_result);
-
-        debug!("testing peer address");
-        // This is what we are actually testing!
-        assert!(net::ip::format_addr(&sock.get_peer_addr()) ==
-            ~"127.0.0.1");
-        assert_eq!(net::ip::get_port(&sock.get_peer_addr()), 8887);
-
-        // Fulfill the protocol the test server expects
-        let resp_bytes = str::to_bytes(~"ping");
-        tcp_write_single(&sock, resp_bytes);
-        debug!("message sent");
-        sock.read(0u);
-        debug!("result read");
-    }
-    pub fn impl_gl_tcp_ipv4_client_error_connection_refused() {
-        let hl_loop = &uv::global_loop::get();
-        let server_ip = "127.0.0.1";
-        let server_port = 8889u;
-        let expected_req = ~"ping";
-        // client
-        debug!("firing up client..");
-        let actual_resp_result = run_tcp_test_client(
-            server_ip,
-            server_port,
-            expected_req,
-            hl_loop);
-        match actual_resp_result.get_err() {
-          ConnectionRefused => (),
-          _ => fail!("unknown error.. expected connection_refused")
-        }
-    }
-    pub fn impl_gl_tcp_ipv4_server_address_in_use() {
-        let hl_loop = &uv::global_loop::get();
-        let server_ip = "127.0.0.1";
-        let server_port = 8890u;
-        let expected_req = ~"ping";
-        let expected_resp = "pong";
-
-        let (cont_po, cont_ch) = stream::<()>();
-        let cont_ch = SharedChan::new(cont_ch);
-        // server
-        let hl_loop_clone = hl_loop.clone();
-        do task::spawn_sched(task::ManualThreads(1u)) {
-            let cont_ch = cont_ch.clone();
-            run_tcp_test_server(
-                server_ip,
-                server_port,
-                expected_resp.to_str(),
-                cont_ch.clone(),
-                &hl_loop_clone);
-        }
-        cont_po.recv();
-        // this one should fail..
-        let listen_err = run_tcp_test_server_fail(
-                            server_ip,
-                            server_port,
-                            hl_loop);
-        // client.. just doing this so that the first server tears down
-        debug!("server started, firing up client..");
-        run_tcp_test_client(
-            server_ip,
-            server_port,
-            expected_req,
-            hl_loop);
-        match listen_err {
-          AddressInUse => {
-            assert!(true);
-          }
-          _ => {
-            fail!("expected address_in_use listen error, \
-                   but got a different error varient. check logs.");
-          }
-        }
-    }
-    pub fn impl_gl_tcp_ipv4_server_access_denied() {
-        let hl_loop = &uv::global_loop::get();
-        let server_ip = "127.0.0.1";
-        let server_port = 80u;
-        // this one should fail..
-        let listen_err = run_tcp_test_server_fail(
-                            server_ip,
-                            server_port,
-                            hl_loop);
-        match listen_err {
-          AccessDenied => {
-            assert!(true);
-          }
-          _ => {
-            fail!("expected address_in_use listen error, \
-                   but got a different error varient. check logs.");
-          }
-        }
-    }
-    pub fn impl_gl_tcp_ipv4_server_client_reader_writer() {
-
-        let iotask = &uv::global_loop::get();
-        let server_ip = "127.0.0.1";
-        let server_port = 8891u;
-        let expected_req = ~"ping";
-        let expected_resp = "pong";
-
-        let (server_result_po, server_result_ch) = stream::<~str>();
-
-        let (cont_po, cont_ch) = stream::<()>();
-        let cont_ch = SharedChan::new(cont_ch);
-        // server
-        let iotask_clone = iotask.clone();
-        do task::spawn_sched(task::ManualThreads(1u)) {
-            let cont_ch = cont_ch.clone();
-            let actual_req = run_tcp_test_server(
-                server_ip,
-                server_port,
-                expected_resp.to_str(),
-                cont_ch.clone(),
-                &iotask_clone);
-            server_result_ch.send(actual_req);
-        };
-        cont_po.recv();
-        // client
-        let server_addr = ip::v4::parse_addr(server_ip);
-        let conn_result = connect(server_addr, server_port, iotask);
-        if result::is_err(&conn_result) {
-            assert!(false);
-        }
-        let sock_buf = @socket_buf(result::unwrap(conn_result));
-        buf_write(sock_buf, expected_req);
-
-        // so contrived!
-        let actual_resp = do str::as_bytes(&expected_resp.to_str()) |resp_buf| {
-            buf_read(sock_buf, resp_buf.len())
-        };
-
-        let actual_req = server_result_po.recv();
-        debug!("REQ: expected: '%s' actual: '%s'",
-                       expected_req, actual_req);
-        debug!("RESP: expected: '%s' actual: '%s'",
-                       expected_resp, actual_resp);
-        assert!(str::contains(actual_req, expected_req));
-        assert!(str::contains(actual_resp, expected_resp));
-    }
-
-    pub fn impl_tcp_socket_impl_reader_handles_eof() {
-        use core::io::{Reader,ReaderUtil};
-
-        let hl_loop = &uv::global_loop::get();
-        let server_ip = "127.0.0.1";
-        let server_port = 10041u;
-        let expected_req = ~"GET /";
-        let expected_resp = "A string\nwith multiple lines\n";
-
-        let (cont_po, cont_ch) = stream::<()>();
-        let cont_ch = SharedChan::new(cont_ch);
-        // server
-        let hl_loop_clone = hl_loop.clone();
-        do task::spawn_sched(task::ManualThreads(1u)) {
-            let cont_ch = cont_ch.clone();
-            run_tcp_test_server(
-                server_ip,
-                server_port,
-                expected_resp.to_str(),
-                cont_ch.clone(),
-                &hl_loop_clone);
-        };
-        cont_po.recv();
-        // client
-        debug!("server started, firing up client..");
-        let server_addr = ip::v4::parse_addr(server_ip);
-        let conn_result = connect(server_addr, server_port, hl_loop);
-        if result::is_err(&conn_result) {
-            assert!(false);
-        }
-        let sock_buf = @socket_buf(result::unwrap(conn_result));
-        buf_write(sock_buf, expected_req);
-
-        let buf_reader = sock_buf as @Reader;
-        let actual_response = str::from_bytes(buf_reader.read_whole_stream());
-        debug!("Actual response: %s", actual_response);
-        assert!(expected_resp == actual_response);
-    }
-
-    fn buf_write<W:io::Writer>(w: &W, val: &str) {
-        debug!("BUF_WRITE: val len %?", str::len(val));
-        do str::byte_slice(val) |b_slice| {
-            debug!("BUF_WRITE: b_slice len %?",
-                            b_slice.len());
-            w.write(b_slice)
-        }
-    }
-
-    fn buf_read<R:io::Reader>(r: &R, len: uint) -> ~str {
-        let new_bytes = (*r).read_bytes(len);
-        debug!("in buf_read.. new_bytes len: %?",
-                        new_bytes.len());
-        str::from_bytes(new_bytes)
-    }
-
-    fn run_tcp_test_server(server_ip: &str, server_port: uint, resp: ~str,
-                          cont_ch: SharedChan<()>,
-                          iotask: &IoTask) -> ~str {
-        let (server_po, server_ch) = stream::<~str>();
-        let server_ch = SharedChan::new(server_ch);
-        let server_ip_addr = ip::v4::parse_addr(server_ip);
-        let resp_cell = Cell(resp);
-        let listen_result = listen(server_ip_addr, server_port, 128,
-                                   iotask,
-            // on_establish_cb -- called when listener is set up
-            |kill_ch| {
-                debug!("establish_cb %?",
-                    kill_ch);
-                cont_ch.send(());
-            },
-            // risky to run this on the loop, but some users
-            // will want the POWER
-            |new_conn, kill_ch| {
-                let resp_cell2 = Cell(resp_cell.take());
-                debug!("SERVER: new connection!");
-                let (cont_po, cont_ch) = stream();
-                let server_ch = server_ch.clone();
-                do task::spawn_sched(task::ManualThreads(1u)) {
-                    debug!("SERVER: starting worker for new req");
-
-                    let accept_result = accept(new_conn);
-                    debug!("SERVER: after accept()");
-                    if result::is_err(&accept_result) {
-                        debug!("SERVER: error accept connection");
-                        let err_data = result::get_err(&accept_result);
-                        kill_ch.send(Some(err_data));
-                        debug!(
-                            "SERVER/WORKER: send on err cont ch");
-                        cont_ch.send(());
-                    }
-                    else {
-                        debug!("SERVER/WORKER: send on cont ch");
-                        cont_ch.send(());
-                        let sock = result::unwrap(accept_result);
-                        let peer_addr = sock.get_peer_addr();
-                        debug!("SERVER: successfully accepted \
-                                connection from %s:%u",
-                                 ip::format_addr(&peer_addr),
-                                 ip::get_port(&peer_addr));
-                        let received_req_bytes = read(&sock, 0u);
-                        match received_req_bytes {
-                          result::Ok(data) => {
-                            debug!("SERVER: got REQ str::from_bytes..");
-                            debug!("SERVER: REQ data len: %?",
-                                            data.len());
-                            server_ch.send(
-                                str::from_bytes(data));
-                            debug!("SERVER: before write");
-                            tcp_write_single(&sock, str::to_bytes(resp_cell2.take()));
-                            debug!("SERVER: after write.. die");
-                            kill_ch.send(None);
-                          }
-                          result::Err(err_data) => {
-                            debug!("SERVER: error recvd: %s %s",
-                                err_data.err_name, err_data.err_msg);
-                            kill_ch.send(Some(err_data));
-                            server_ch.send(~"");
-                          }
-                        }
-                        debug!("SERVER: worker spinning down");
-                    }
-                }
-                debug!("SERVER: waiting to recv on cont_ch");
-                cont_po.recv();
-        });
-        // err check on listen_result
-        if result::is_err(&listen_result) {
-            match result::get_err(&listen_result) {
-              GenericListenErr(ref name, ref msg) => {
-                fail!("SERVER: exited abnormally name %s msg %s", *name, *msg);
-              }
-              AccessDenied => {
-                fail!("SERVER: exited abnormally, got access denied..");
-              }
-              AddressInUse => {
-                fail!("SERVER: exited abnormally, got address in use...");
-              }
-            }
-        }
-        let ret_val = server_po.recv();
-        debug!("SERVER: exited and got return val: '%s'", ret_val);
-        ret_val
-    }
-
-    fn run_tcp_test_server_fail(server_ip: &str, server_port: uint,
-                                iotask: &IoTask) -> TcpListenErrData {
-        let server_ip_addr = ip::v4::parse_addr(server_ip);
-        let listen_result = listen(server_ip_addr, server_port, 128,
-                                   iotask,
-            // on_establish_cb -- called when listener is set up
-            |kill_ch| {
-                debug!("establish_cb %?", kill_ch);
-            },
-            |new_conn, kill_ch| {
-                fail!("SERVER: shouldn't be called.. %? %?", new_conn, kill_ch);
-        });
-        // err check on listen_result
-        if result::is_err(&listen_result) {
-            result::get_err(&listen_result)
-        }
-        else {
-            fail!("SERVER: did not fail as expected")
-        }
-    }
-
-    fn run_tcp_test_client(server_ip: &str, server_port: uint, resp: &str,
-                          iotask: &IoTask) -> result::Result<~str,
-                                                    TcpConnectErrData> {
-        let server_ip_addr = ip::v4::parse_addr(server_ip);
-
-        debug!("CLIENT: starting..");
-        let connect_result = connect(server_ip_addr, server_port,
-                                     iotask);
-        if result::is_err(&connect_result) {
-            debug!("CLIENT: failed to connect");
-            let err_data = result::get_err(&connect_result);
-            Err(err_data)
-        }
-        else {
-            let sock = result::unwrap(connect_result);
-            let resp_bytes = str::to_bytes(resp);
-            tcp_write_single(&sock, resp_bytes);
-            let read_result = sock.read(0u);
-            if read_result.is_err() {
-                debug!("CLIENT: failure to read");
-                Ok(~"")
-            }
-            else {
-                let ret_val = str::from_bytes(read_result.get());
-                debug!("CLIENT: after client_ch recv ret: '%s'",
-                   ret_val);
-                Ok(ret_val)
-            }
-        }
-    }
-
-    fn tcp_write_single(sock: &TcpSocket, val: ~[u8]) {
-        let mut write_result_future = sock.write_future(val);
-        let write_result = write_result_future.get();
-        if result::is_err(&write_result) {
-            debug!("tcp_write_single: write failed!");
-            let err_data = result::get_err(&write_result);
-            debug!("tcp_write_single err name: %s msg: %s",
-                err_data.err_name, err_data.err_msg);
-            // meh. torn on what to do here.
-            fail!("tcp_write_single failed");
-        }
-    }
-}
diff --git a/src/libstd/net_url.rs b/src/libstd/net_url.rs
deleted file mode 100644
index fb57c717be9..00000000000
--- a/src/libstd/net_url.rs
+++ /dev/null
@@ -1,1068 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Types/fns concerning URLs (see RFC 3986)
-
-use core::cmp::Eq;
-use core::io::{Reader, ReaderUtil};
-use core::io;
-use core::hashmap::HashMap;
-use core::str;
-use core::to_bytes;
-use core::uint;
-
-#[deriving(Clone, Eq)]
-struct Url {
-    scheme: ~str,
-    user: Option<UserInfo>,
-    host: ~str,
-    port: Option<~str>,
-    path: ~str,
-    query: Query,
-    fragment: Option<~str>
-}
-
-#[deriving(Clone, Eq)]
-struct UserInfo {
-    user: ~str,
-    pass: Option<~str>
-}
-
-pub type Query = ~[(~str, ~str)];
-
-pub impl Url {
-    fn new(
-        scheme: ~str,
-        user: Option<UserInfo>,
-        host: ~str,
-        port: Option<~str>,
-        path: ~str,
-        query: Query,
-        fragment: Option<~str>
-    ) -> Url {
-        Url {
-            scheme: scheme,
-            user: user,
-            host: host,
-            port: port,
-            path: path,
-            query: query,
-            fragment: fragment,
-        }
-    }
-}
-
-pub impl UserInfo {
-    fn new(user: ~str, pass: Option<~str>) -> UserInfo {
-        UserInfo { user: user, pass: pass }
-    }
-}
-
-fn encode_inner(s: &str, full_url: bool) -> ~str {
-    do io::with_str_reader(s) |rdr| {
-        let mut out = ~"";
-
-        while !rdr.eof() {
-            let ch = rdr.read_byte() as char;
-            match ch {
-              // unreserved:
-              'A' .. 'Z' |
-              'a' .. 'z' |
-              '0' .. '9' |
-              '-' | '.' | '_' | '~' => {
-                str::push_char(&mut out, ch);
-              }
-              _ => {
-                  if full_url {
-                    match ch {
-                      // gen-delims:
-                      ':' | '/' | '?' | '#' | '[' | ']' | '@' |
-
-                      // sub-delims:
-                      '!' | '$' | '&' | '"' | '(' | ')' | '*' |
-                      '+' | ',' | ';' | '=' => {
-                        str::push_char(&mut out, ch);
-                      }
-
-                      _ => out += fmt!("%%%X", ch as uint)
-                    }
-                } else {
-                    out += fmt!("%%%X", ch as uint);
-                }
-              }
-            }
-        }
-
-        out
-    }
-}
-
-/**
- * Encodes a URI by replacing reserved characters with percent encoded
- * character sequences.
- *
- * This function is compliant with RFC 3986.
- */
-pub fn encode(s: &str) -> ~str {
-    encode_inner(s, true)
-}
-
-/**
- * Encodes a URI component by replacing reserved characters with percent
- * encoded character sequences.
- *
- * This function is compliant with RFC 3986.
- */
-
-pub fn encode_component(s: &str) -> ~str {
-    encode_inner(s, false)
-}
-
-fn decode_inner(s: &str, full_url: bool) -> ~str {
-    do io::with_str_reader(s) |rdr| {
-        let mut out = ~"";
-
-        while !rdr.eof() {
-            match rdr.read_char() {
-              '%' => {
-                let bytes = rdr.read_bytes(2u);
-                let ch = uint::parse_bytes(bytes, 16u).get() as char;
-
-                if full_url {
-                    // Only decode some characters:
-                    match ch {
-                      // gen-delims:
-                      ':' | '/' | '?' | '#' | '[' | ']' | '@' |
-
-                      // sub-delims:
-                      '!' | '$' | '&' | '"' | '(' | ')' | '*' |
-                      '+' | ',' | ';' | '=' => {
-                        str::push_char(&mut out, '%');
-                        str::push_char(&mut out, bytes[0u] as char);
-                        str::push_char(&mut out, bytes[1u] as char);
-                      }
-
-                      ch => str::push_char(&mut out, ch)
-                    }
-                } else {
-                      str::push_char(&mut out, ch);
-                }
-              }
-              ch => str::push_char(&mut out, ch)
-            }
-        }
-
-        out
-    }
-}
-
-/**
- * Decode a string encoded with percent encoding.
- *
- * This will only decode escape sequences generated by encode.
- */
-pub fn decode(s: &str) -> ~str {
-    decode_inner(s, true)
-}
-
-/**
- * Decode a string encoded with percent encoding.
- */
-pub fn decode_component(s: &str) -> ~str {
-    decode_inner(s, false)
-}
-
-fn encode_plus(s: &str) -> ~str {
-    do io::with_str_reader(s) |rdr| {
-        let mut out = ~"";
-
-        while !rdr.eof() {
-            let ch = rdr.read_byte() as char;
-            match ch {
-              'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '_' | '.' | '-' => {
-                str::push_char(&mut out, ch);
-              }
-              ' ' => str::push_char(&mut out, '+'),
-              _ => out += fmt!("%%%X", ch as uint)
-            }
-        }
-
-        out
-    }
-}
-
-/**
- * Encode a hashmap to the 'application/x-www-form-urlencoded' media type.
- */
-pub fn encode_form_urlencoded(m: &HashMap<~str, ~[~str]>) -> ~str {
-    let mut out = ~"";
-    let mut first = true;
-
-    for m.each |key, values| {
-        let key = encode_plus(*key);
-
-        for values.each |value| {
-            if first {
-                first = false;
-            } else {
-                str::push_char(&mut out, '&');
-                first = false;
-            }
-
-            out += fmt!("%s=%s", key, encode_plus(*value));
-        }
-    }
-
-    out
-}
-
-/**
- * Decode a string encoded with the 'application/x-www-form-urlencoded' media
- * type into a hashmap.
- */
-pub fn decode_form_urlencoded(s: &[u8]) -> HashMap<~str, ~[~str]> {
-    do io::with_bytes_reader(s) |rdr| {
-        let mut m = HashMap::new();
-        let mut key = ~"";
-        let mut value = ~"";
-        let mut parsing_key = true;
-
-        while !rdr.eof() {
-            match rdr.read_char() {
-                '&' | ';' => {
-                    if key != ~"" && value != ~"" {
-                        let mut values = match m.pop(&key) {
-                            Some(values) => values,
-                            None => ~[],
-                        };
-
-                        values.push(value);
-                        m.insert(key, values);
-                    }
-
-                    parsing_key = true;
-                    key = ~"";
-                    value = ~"";
-                }
-                '=' => parsing_key = false,
-                ch => {
-                    let ch = match ch {
-                        '%' => {
-                            let bytes = rdr.read_bytes(2u);
-                            uint::parse_bytes(bytes, 16u).get() as char
-                        }
-                        '+' => ' ',
-                        ch => ch
-                    };
-
-                    if parsing_key {
-                        str::push_char(&mut key, ch)
-                    } else {
-                        str::push_char(&mut value, ch)
-                    }
-                }
-            }
-        }
-
-        if key != ~"" && value != ~"" {
-            let mut values = match m.pop(&key) {
-                Some(values) => values,
-                None => ~[],
-            };
-
-            values.push(value);
-            m.insert(key, values);
-        }
-
-        m
-    }
-}
-
-
-fn split_char_first(s: &str, c: char) -> (~str, ~str) {
-    let len = str::len(s);
-    let mut index = len;
-    let mut mat = 0;
-    do io::with_str_reader(s) |rdr| {
-        let mut ch;
-        while !rdr.eof() {
-            ch = rdr.read_byte() as char;
-            if ch == c {
-                // found a match, adjust markers
-                index = rdr.tell()-1;
-                mat = 1;
-                break;
-            }
-        }
-    }
-    if index+mat == len {
-        return (str::slice(s, 0, index).to_owned(), ~"");
-    } else {
-        return (str::slice(s, 0, index).to_owned(),
-             str::slice(s, index + mat, str::len(s)).to_owned());
-    }
-}
-
-fn userinfo_from_str(uinfo: &str) -> UserInfo {
-    let (user, p) = split_char_first(uinfo, ':');
-    let pass = if str::len(p) == 0 {
-        None
-    } else {
-        Some(p)
-    };
-    return UserInfo::new(user, pass);
-}
-
-fn userinfo_to_str(userinfo: &UserInfo) -> ~str {
-    match userinfo.pass {
-        Some(ref pass) => fmt!("%s:%s@", userinfo.user, *pass),
-        None => fmt!("%s@", userinfo.user),
-    }
-}
-
-fn query_from_str(rawquery: &str) -> Query {
-    let mut query: Query = ~[];
-    if str::len(rawquery) != 0 {
-        for str::each_split_char(rawquery, '&') |p| {
-            let (k, v) = split_char_first(p, '=');
-            query.push((decode_component(k), decode_component(v)));
-        };
-    }
-    return query;
-}
-
-pub fn query_to_str(query: &Query) -> ~str {
-    let mut strvec = ~[];
-    for query.each |kv| {
-        match kv {
-            &(ref k, ref v) => {
-                strvec.push(fmt!("%s=%s",
-                    encode_component(*k),
-                    encode_component(*v))
-                );
-            }
-        }
-    }
-    return str::connect(strvec, "&");
-}
-
-// returns the scheme and the rest of the url, or a parsing error
-pub fn get_scheme(rawurl: &str) -> Result<(~str, ~str), ~str> {
-    for str::each_chari(rawurl) |i,c| {
-        match c {
-          'A' .. 'Z' | 'a' .. 'z' => loop,
-          '0' .. '9' | '+' | '-' | '.' => {
-            if i == 0 {
-                return Err(~"url: Scheme must begin with a letter.");
-            }
-            loop;
-          }
-          ':' => {
-            if i == 0 {
-                return Err(~"url: Scheme cannot be empty.");
-            } else {
-                return Ok((rawurl.slice(0,i).to_owned(),
-                                rawurl.slice(i+1,str::len(rawurl)).to_owned()));
-            }
-          }
-          _ => {
-            return Err(~"url: Invalid character in scheme.");
-          }
-        }
-    };
-    return Err(~"url: Scheme must be terminated with a colon.");
-}
-
-#[deriving(Clone, Eq)]
-enum Input {
-    Digit, // all digits
-    Hex, // digits and letters a-f
-    Unreserved // all other legal characters
-}
-
-// returns userinfo, host, port, and unparsed part, or an error
-fn get_authority(rawurl: &str) ->
-    Result<(Option<UserInfo>, ~str, Option<~str>, ~str), ~str> {
-    if !str::starts_with(rawurl, "//") {
-        // there is no authority.
-        return Ok((None, ~"", None, rawurl.to_str()));
-    }
-
-    enum State {
-        Start, // starting state
-        PassHostPort, // could be in user or port
-        Ip6Port, // either in ipv6 host or port
-        Ip6Host, // are in an ipv6 host
-        InHost, // are in a host - may be ipv6, but don't know yet
-        InPort // are in port
-    }
-
-    let len = rawurl.len();
-    let mut st = Start;
-    let mut in = Digit; // most restricted, start here.
-
-    let mut userinfo = None;
-    let mut host = ~"";
-    let mut port = None;
-
-    let mut colon_count = 0;
-    let mut pos = 0, begin = 2, end = len;
-
-    for str::each_chari(rawurl) |i,c| {
-        if i < 2 { loop; } // ignore the leading //
-
-        // deal with input class first
-        match c {
-          '0' .. '9' => (),
-          'A' .. 'F' | 'a' .. 'f' => {
-            if in == Digit {
-                in = Hex;
-            }
-          }
-          'G' .. 'Z' | 'g' .. 'z' | '-' | '.' | '_' | '~' | '%' |
-          '&' |'\'' | '(' | ')' | '+' | '!' | '*' | ',' | ';' | '=' => {
-            in = Unreserved;
-          }
-          ':' | '@' | '?' | '#' | '/' => {
-            // separators, don't change anything
-          }
-          _ => {
-            return Err(~"Illegal character in authority");
-          }
-        }
-
-        // now process states
-        match c {
-          ':' => {
-            colon_count += 1;
-            match st {
-              Start => {
-                pos = i;
-                st = PassHostPort;
-              }
-              PassHostPort => {
-                // multiple colons means ipv6 address.
-                if in == Unreserved {
-                    return Err(
-                        ~"Illegal characters in IPv6 address.");
-                }
-                st = Ip6Host;
-              }
-              InHost => {
-                pos = i;
-                // can't be sure whether this is an ipv6 address or a port
-                if in == Unreserved {
-                    return Err(~"Illegal characters in authority.");
-                }
-                st = Ip6Port;
-              }
-              Ip6Port => {
-                if in == Unreserved {
-                    return Err(~"Illegal characters in authority.");
-                }
-                st = Ip6Host;
-              }
-              Ip6Host => {
-                if colon_count > 7 {
-                    host = str::slice(rawurl, begin, i).to_owned();
-                    pos = i;
-                    st = InPort;
-                }
-              }
-              _ => {
-                return Err(~"Invalid ':' in authority.");
-              }
-            }
-            in = Digit; // reset input class
-          }
-
-          '@' => {
-            in = Digit; // reset input class
-            colon_count = 0; // reset count
-            match st {
-              Start => {
-                let user = str::slice(rawurl, begin, i).to_owned();
-                userinfo = Some(UserInfo::new(user, None));
-                st = InHost;
-              }
-              PassHostPort => {
-                let user = str::slice(rawurl, begin, pos).to_owned();
-                let pass = str::slice(rawurl, pos+1, i).to_owned();
-                userinfo = Some(UserInfo::new(user, Some(pass)));
-                st = InHost;
-              }
-              _ => {
-                return Err(~"Invalid '@' in authority.");
-              }
-            }
-            begin = i+1;
-          }
-
-          '?' | '#' | '/' => {
-            end = i;
-            break;
-          }
-          _ => ()
-        }
-        end = i;
-    }
-
-    let end = end; // make end immutable so it can be captured
-
-    let host_is_end_plus_one: &fn() -> bool = || {
-        end+1 == len
-            && !['?', '#', '/'].contains(&(rawurl[end] as char))
-    };
-
-    // finish up
-    match st {
-      Start => {
-        if host_is_end_plus_one() {
-            host = str::slice(rawurl, begin, end+1).to_owned();
-        } else {
-            host = str::slice(rawurl, begin, end).to_owned();
-        }
-      }
-      PassHostPort | Ip6Port => {
-        if in != Digit {
-            return Err(~"Non-digit characters in port.");
-        }
-        host = str::slice(rawurl, begin, pos).to_owned();
-        port = Some(str::slice(rawurl, pos+1, end).to_owned());
-      }
-      Ip6Host | InHost => {
-        host = str::slice(rawurl, begin, end).to_owned();
-      }
-      InPort => {
-        if in != Digit {
-            return Err(~"Non-digit characters in port.");
-        }
-        port = Some(str::slice(rawurl, pos+1, end).to_owned());
-      }
-    }
-
-    let rest = if host_is_end_plus_one() { ~"" }
-    else { str::slice(rawurl, end, len).to_owned() };
-    return Ok((userinfo, host, port, rest));
-}
-
-
-// returns the path and unparsed part of url, or an error
-fn get_path(rawurl: &str, authority: bool) ->
-    Result<(~str, ~str), ~str> {
-    let len = str::len(rawurl);
-    let mut end = len;
-    for str::each_chari(rawurl) |i,c| {
-        match c {
-          'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '&' |'\'' | '(' | ')' | '.'
-          | '@' | ':' | '%' | '/' | '+' | '!' | '*' | ',' | ';' | '='
-          | '_' | '-' => {
-            loop;
-          }
-          '?' | '#' => {
-            end = i;
-            break;
-          }
-          _ => return Err(~"Invalid character in path.")
-        }
-    }
-
-    if authority {
-        if end != 0 && !str::starts_with(rawurl, "/") {
-            return Err(~"Non-empty path must begin with\
-                               '/' in presence of authority.");
-        }
-    }
-
-    return Ok((decode_component(str::slice(rawurl, 0, end).to_owned()),
-                    str::slice(rawurl, end, len).to_owned()));
-}
-
-// returns the parsed query and the fragment, if present
-fn get_query_fragment(rawurl: &str) ->
-    Result<(Query, Option<~str>), ~str> {
-    if !str::starts_with(rawurl, "?") {
-        if str::starts_with(rawurl, "#") {
-            let f = decode_component(str::slice(rawurl,
-                                                1,
-                                                str::len(rawurl)).to_owned());
-            return Ok((~[], Some(f)));
-        } else {
-            return Ok((~[], None));
-        }
-    }
-    let (q, r) = split_char_first(str::slice(rawurl, 1,
-                                             str::len(rawurl)).to_owned(), '#');
-    let f = if str::len(r) != 0 {
-        Some(decode_component(r)) } else { None };
-    return Ok((query_from_str(q), f));
-}
-
-/**
- * Parse a `str` to a `url`
- *
- * # Arguments
- *
- * `rawurl` - a string representing a full url, including scheme.
- *
- * # Returns
- *
- * a `url` that contains the parsed representation of the url.
- *
- */
-
-pub fn from_str(rawurl: &str) -> Result<Url, ~str> {
-    // scheme
-    let (scheme, rest) = match get_scheme(rawurl) {
-        Ok(val) => val,
-        Err(e) => return Err(e),
-    };
-
-    // authority
-    let (userinfo, host, port, rest) = match get_authority(rest) {
-        Ok(val) => val,
-        Err(e) => return Err(e),
-    };
-
-    // path
-    let has_authority = if host == ~"" { false } else { true };
-    let (path, rest) = match get_path(rest, has_authority) {
-        Ok(val) => val,
-        Err(e) => return Err(e),
-    };
-
-    // query and fragment
-    let (query, fragment) = match get_query_fragment(rest) {
-        Ok(val) => val,
-        Err(e) => return Err(e),
-    };
-
-    Ok(Url::new(scheme, userinfo, host, port, path, query, fragment))
-}
-
-impl FromStr for Url {
-    fn from_str(s: &str) -> Option<Url> {
-        match from_str(s) {
-            Ok(url) => Some(url),
-            Err(_) => None
-        }
-    }
-}
-
-/**
- * Format a `url` as a string
- *
- * # Arguments
- *
- * `url` - a url.
- *
- * # Returns
- *
- * a `str` that contains the formatted url. Note that this will usually
- * be an inverse of `from_str` but might strip out unneeded separators.
- * for example, "http://somehost.com?", when parsed and formatted, will
- * result in just "http://somehost.com".
- *
- */
-pub fn to_str(url: &Url) -> ~str {
-    let user = match url.user {
-        Some(ref user) => userinfo_to_str(user),
-        None => ~"",
-    };
-
-    let authority = if url.host.is_empty() {
-        ~""
-    } else {
-        fmt!("//%s%s", user, url.host)
-    };
-
-    let query = if url.query.is_empty() {
-        ~""
-    } else {
-        fmt!("?%s", query_to_str(&url.query))
-    };
-
-    let fragment = match url.fragment {
-        Some(ref fragment) => fmt!("#%s", encode_component(*fragment)),
-        None => ~"",
-    };
-
-    fmt!("%s:%s%s%s%s", url.scheme, authority, url.path, query, fragment)
-}
-
-impl ToStr for Url {
-    pub fn to_str(&self) -> ~str {
-        to_str(self)
-    }
-}
-
-impl IterBytes for Url {
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.to_str().iter_bytes(lsb0, f)
-    }
-}
-
-// Put a few tests outside of the 'test' module so they can test the internal
-// functions and those functions don't need 'pub'
-
-#[test]
-fn test_split_char_first() {
-    let (u,v) = split_char_first(~"hello, sweet world", ',');
-    assert_eq!(u, ~"hello");
-    assert_eq!(v, ~" sweet world");
-
-    let (u,v) = split_char_first(~"hello sweet world", ',');
-    assert_eq!(u, ~"hello sweet world");
-    assert_eq!(v, ~"");
-}
-
-#[test]
-fn test_get_authority() {
-    let (u, h, p, r) = get_authority(
-        "//user:pass@rust-lang.org/something").unwrap();
-    assert_eq!(u, Some(UserInfo::new(~"user", Some(~"pass"))));
-    assert_eq!(h, ~"rust-lang.org");
-    assert!(p.is_none());
-    assert_eq!(r, ~"/something");
-
-    let (u, h, p, r) = get_authority(
-        "//rust-lang.org:8000?something").unwrap();
-    assert!(u.is_none());
-    assert_eq!(h, ~"rust-lang.org");
-    assert_eq!(p, Some(~"8000"));
-    assert_eq!(r, ~"?something");
-
-    let (u, h, p, r) = get_authority(
-        "//rust-lang.org#blah").unwrap();
-    assert!(u.is_none());
-    assert_eq!(h, ~"rust-lang.org");
-    assert!(p.is_none());
-    assert_eq!(r, ~"#blah");
-
-    // ipv6 tests
-    let (_, h, _, _) = get_authority(
-        "//2001:0db8:85a3:0042:0000:8a2e:0370:7334#blah").unwrap();
-    assert_eq!(h, ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334");
-
-    let (_, h, p, _) = get_authority(
-        "//2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000#blah").unwrap();
-    assert_eq!(h, ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334");
-    assert_eq!(p, Some(~"8000"));
-
-    let (u, h, p, _) = get_authority(
-        "//us:p@2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000#blah"
-    ).unwrap();
-    assert_eq!(u, Some(UserInfo::new(~"us", Some(~"p"))));
-    assert_eq!(h, ~"2001:0db8:85a3:0042:0000:8a2e:0370:7334");
-    assert_eq!(p, Some(~"8000"));
-
-    // invalid authorities;
-    assert!(get_authority("//user:pass@rust-lang:something").is_err());
-    assert!(get_authority("//user@rust-lang:something:/path").is_err());
-    assert!(get_authority(
-        "//2001:0db8:85a3:0042:0000:8a2e:0370:7334:800a").is_err());
-    assert!(get_authority(
-        "//2001:0db8:85a3:0042:0000:8a2e:0370:7334:8000:00").is_err());
-
-    // these parse as empty, because they don't start with '//'
-    let (_, h, _, _) = get_authority(~"user:pass@rust-lang").unwrap();
-    assert_eq!(h, ~"");
-    let (_, h, _, _) = get_authority(~"rust-lang.org").unwrap();
-    assert_eq!(h, ~"");
-}
-
-#[test]
-fn test_get_path() {
-    let (p, r) = get_path("/something+%20orother", true).unwrap();
-    assert_eq!(p, ~"/something+ orother");
-    assert_eq!(r, ~"");
-    let (p, r) = get_path("test@email.com#fragment", false).unwrap();
-    assert_eq!(p, ~"test@email.com");
-    assert_eq!(r, ~"#fragment");
-    let (p, r) = get_path(~"/gen/:addr=?q=v", false).unwrap();
-    assert_eq!(p, ~"/gen/:addr=");
-    assert_eq!(r, ~"?q=v");
-
-    //failure cases
-    assert!(get_path(~"something?q", true).is_err());
-}
-
-#[cfg(test)]
-mod tests {
-
-    use net_url::*;
-
-    use core::hashmap::HashMap;
-
-    #[test]
-    fn test_url_parse() {
-        let url = ~"http://user:pass@rust-lang.org/doc?s=v#something";
-
-        let up = from_str(url);
-        let u = up.unwrap();
-        assert!(u.scheme == ~"http");
-        let userinfo = u.user.get_ref();
-        assert!(userinfo.user == ~"user");
-        assert!(userinfo.pass.get_ref() == &~"pass");
-        assert!(u.host == ~"rust-lang.org");
-        assert!(u.path == ~"/doc");
-        assert!(u.query == ~[(~"s", ~"v")]);
-        assert!(u.fragment.get_ref() == &~"something");
-    }
-
-    #[test]
-    fn test_url_parse_host_slash() {
-        let urlstr = ~"http://0.42.42.42/";
-        let url = from_str(urlstr).unwrap();
-        assert!(url.host == ~"0.42.42.42");
-        assert!(url.path == ~"/");
-    }
-
-    #[test]
-    fn test_url_with_underscores() {
-        let urlstr = ~"http://dotcom.com/file_name.html";
-        let url = from_str(urlstr).unwrap();
-        assert!(url.path == ~"/file_name.html");
-    }
-
-    #[test]
-    fn test_url_with_dashes() {
-        let urlstr = ~"http://dotcom.com/file-name.html";
-        let url = from_str(urlstr).unwrap();
-        assert!(url.path == ~"/file-name.html");
-    }
-
-    #[test]
-    fn test_no_scheme() {
-        assert!(get_scheme("noschemehere.html").is_err());
-    }
-
-    #[test]
-    fn test_invalid_scheme_errors() {
-        assert!(from_str("99://something").is_err());
-        assert!(from_str("://something").is_err());
-    }
-
-    #[test]
-    fn test_full_url_parse_and_format() {
-        let url = ~"http://user:pass@rust-lang.org/doc?s=v#something";
-        assert_eq!(from_str(url).unwrap().to_str(), url);
-    }
-
-    #[test]
-    fn test_userless_url_parse_and_format() {
-        let url = ~"http://rust-lang.org/doc?s=v#something";
-        assert_eq!(from_str(url).unwrap().to_str(), url);
-    }
-
-    #[test]
-    fn test_queryless_url_parse_and_format() {
-        let url = ~"http://user:pass@rust-lang.org/doc#something";
-        assert_eq!(from_str(url).unwrap().to_str(), url);
-    }
-
-    #[test]
-    fn test_empty_query_url_parse_and_format() {
-        let url = ~"http://user:pass@rust-lang.org/doc?#something";
-        let should_be = ~"http://user:pass@rust-lang.org/doc#something";
-        assert_eq!(from_str(url).unwrap().to_str(), should_be);
-    }
-
-    #[test]
-    fn test_fragmentless_url_parse_and_format() {
-        let url = ~"http://user:pass@rust-lang.org/doc?q=v";
-        assert_eq!(from_str(url).unwrap().to_str(), url);
-    }
-
-    #[test]
-    fn test_minimal_url_parse_and_format() {
-        let url = ~"http://rust-lang.org/doc";
-        assert_eq!(from_str(url).unwrap().to_str(), url);
-    }
-
-    #[test]
-    fn test_scheme_host_only_url_parse_and_format() {
-        let url = ~"http://rust-lang.org";
-        assert_eq!(from_str(url).unwrap().to_str(), url);
-    }
-
-    #[test]
-    fn test_pathless_url_parse_and_format() {
-        let url = ~"http://user:pass@rust-lang.org?q=v#something";
-        assert_eq!(from_str(url).unwrap().to_str(), url);
-    }
-
-    #[test]
-    fn test_scheme_host_fragment_only_url_parse_and_format() {
-        let url = ~"http://rust-lang.org#something";
-        assert_eq!(from_str(url).unwrap().to_str(), url);
-    }
-
-    #[test]
-    fn test_url_component_encoding() {
-        let url = ~"http://rust-lang.org/doc%20uments?ba%25d%20=%23%26%2B";
-        let u = from_str(url).unwrap();
-        assert!(u.path == ~"/doc uments");
-        assert!(u.query == ~[(~"ba%d ", ~"#&+")]);
-    }
-
-    #[test]
-    fn test_url_without_authority() {
-        let url = ~"mailto:test@email.com";
-        assert_eq!(from_str(url).unwrap().to_str(), url);
-    }
-
-    #[test]
-    fn test_encode() {
-        assert_eq!(encode(""), ~"");
-        assert_eq!(encode("http://example.com"), ~"http://example.com");
-        assert_eq!(encode("foo bar% baz"), ~"foo%20bar%25%20baz");
-        assert_eq!(encode(" "), ~"%20");
-        assert_eq!(encode("!"), ~"!");
-        assert_eq!(encode("\""), ~"\"");
-        assert_eq!(encode("#"), ~"#");
-        assert_eq!(encode("$"), ~"$");
-        assert_eq!(encode("%"), ~"%25");
-        assert_eq!(encode("&"), ~"&");
-        assert_eq!(encode("'"), ~"%27");
-        assert_eq!(encode("("), ~"(");
-        assert_eq!(encode(")"), ~")");
-        assert_eq!(encode("*"), ~"*");
-        assert_eq!(encode("+"), ~"+");
-        assert_eq!(encode(","), ~",");
-        assert_eq!(encode("/"), ~"/");
-        assert_eq!(encode(":"), ~":");
-        assert_eq!(encode(";"), ~";");
-        assert_eq!(encode("="), ~"=");
-        assert_eq!(encode("?"), ~"?");
-        assert_eq!(encode("@"), ~"@");
-        assert_eq!(encode("["), ~"[");
-        assert_eq!(encode("]"), ~"]");
-    }
-
-    #[test]
-    fn test_encode_component() {
-        assert_eq!(encode_component(""), ~"");
-        assert!(encode_component("http://example.com") ==
-            ~"http%3A%2F%2Fexample.com");
-        assert!(encode_component("foo bar% baz") ==
-            ~"foo%20bar%25%20baz");
-        assert_eq!(encode_component(" "), ~"%20");
-        assert_eq!(encode_component("!"), ~"%21");
-        assert_eq!(encode_component("#"), ~"%23");
-        assert_eq!(encode_component("$"), ~"%24");
-        assert_eq!(encode_component("%"), ~"%25");
-        assert_eq!(encode_component("&"), ~"%26");
-        assert_eq!(encode_component("'"), ~"%27");
-        assert_eq!(encode_component("("), ~"%28");
-        assert_eq!(encode_component(")"), ~"%29");
-        assert_eq!(encode_component("*"), ~"%2A");
-        assert_eq!(encode_component("+"), ~"%2B");
-        assert_eq!(encode_component(","), ~"%2C");
-        assert_eq!(encode_component("/"), ~"%2F");
-        assert_eq!(encode_component(":"), ~"%3A");
-        assert_eq!(encode_component(";"), ~"%3B");
-        assert_eq!(encode_component("="), ~"%3D");
-        assert_eq!(encode_component("?"), ~"%3F");
-        assert_eq!(encode_component("@"), ~"%40");
-        assert_eq!(encode_component("["), ~"%5B");
-        assert_eq!(encode_component("]"), ~"%5D");
-    }
-
-    #[test]
-    fn test_decode() {
-        assert_eq!(decode(""), ~"");
-        assert_eq!(decode("abc/def 123"), ~"abc/def 123");
-        assert_eq!(decode("abc%2Fdef%20123"), ~"abc%2Fdef 123");
-        assert_eq!(decode("%20"), ~" ");
-        assert_eq!(decode("%21"), ~"%21");
-        assert_eq!(decode("%22"), ~"%22");
-        assert_eq!(decode("%23"), ~"%23");
-        assert_eq!(decode("%24"), ~"%24");
-        assert_eq!(decode("%25"), ~"%");
-        assert_eq!(decode("%26"), ~"%26");
-        assert_eq!(decode("%27"), ~"'");
-        assert_eq!(decode("%28"), ~"%28");
-        assert_eq!(decode("%29"), ~"%29");
-        assert_eq!(decode("%2A"), ~"%2A");
-        assert_eq!(decode("%2B"), ~"%2B");
-        assert_eq!(decode("%2C"), ~"%2C");
-        assert_eq!(decode("%2F"), ~"%2F");
-        assert_eq!(decode("%3A"), ~"%3A");
-        assert_eq!(decode("%3B"), ~"%3B");
-        assert_eq!(decode("%3D"), ~"%3D");
-        assert_eq!(decode("%3F"), ~"%3F");
-        assert_eq!(decode("%40"), ~"%40");
-        assert_eq!(decode("%5B"), ~"%5B");
-        assert_eq!(decode("%5D"), ~"%5D");
-    }
-
-    #[test]
-    fn test_decode_component() {
-        assert_eq!(decode_component(""), ~"");
-        assert_eq!(decode_component("abc/def 123"), ~"abc/def 123");
-        assert_eq!(decode_component("abc%2Fdef%20123"), ~"abc/def 123");
-        assert_eq!(decode_component("%20"), ~" ");
-        assert_eq!(decode_component("%21"), ~"!");
-        assert_eq!(decode_component("%22"), ~"\"");
-        assert_eq!(decode_component("%23"), ~"#");
-        assert_eq!(decode_component("%24"), ~"$");
-        assert_eq!(decode_component("%25"), ~"%");
-        assert_eq!(decode_component("%26"), ~"&");
-        assert_eq!(decode_component("%27"), ~"'");
-        assert_eq!(decode_component("%28"), ~"(");
-        assert_eq!(decode_component("%29"), ~")");
-        assert_eq!(decode_component("%2A"), ~"*");
-        assert_eq!(decode_component("%2B"), ~"+");
-        assert_eq!(decode_component("%2C"), ~",");
-        assert_eq!(decode_component("%2F"), ~"/");
-        assert_eq!(decode_component("%3A"), ~":");
-        assert_eq!(decode_component("%3B"), ~";");
-        assert_eq!(decode_component("%3D"), ~"=");
-        assert_eq!(decode_component("%3F"), ~"?");
-        assert_eq!(decode_component("%40"), ~"@");
-        assert_eq!(decode_component("%5B"), ~"[");
-        assert_eq!(decode_component("%5D"), ~"]");
-    }
-
-    #[test]
-    fn test_encode_form_urlencoded() {
-        let mut m = HashMap::new();
-        assert_eq!(encode_form_urlencoded(&m), ~"");
-
-        m.insert(~"", ~[]);
-        m.insert(~"foo", ~[]);
-        assert_eq!(encode_form_urlencoded(&m), ~"");
-
-        let mut m = HashMap::new();
-        m.insert(~"foo", ~[~"bar", ~"123"]);
-        assert_eq!(encode_form_urlencoded(&m), ~"foo=bar&foo=123");
-
-        let mut m = HashMap::new();
-        m.insert(~"foo bar", ~[~"abc", ~"12 = 34"]);
-        assert!(encode_form_urlencoded(&m) ==
-            ~"foo+bar=abc&foo+bar=12+%3D+34");
-    }
-
-    #[test]
-    fn test_decode_form_urlencoded() {
-        // FIXME #4449: Commented out because this causes an ICE, but only
-        // on FreeBSD
-        /*
-        assert_eq!(decode_form_urlencoded(~[]).len(), 0);
-
-        let s = str::to_bytes("a=1&foo+bar=abc&foo+bar=12+%3D+34");
-        let form = decode_form_urlencoded(s);
-        assert_eq!(form.len(), 2);
-        assert_eq!(form.get_ref(&~"a"), &~[~"1"]);
-        assert_eq!(form.get_ref(&~"foo bar"), &~[~"abc", ~"12 = 34"]);
-        */
-    }
-}
diff --git a/src/libstd/nil.rs b/src/libstd/nil.rs
new file mode 100644
index 00000000000..833bd3459ce
--- /dev/null
+++ b/src/libstd/nil.rs
@@ -0,0 +1,50 @@
+// 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.
+
+/*!
+
+Functions for the unit type.
+
+*/
+
+#[cfg(not(test))]
+use prelude::*;
+
+#[cfg(not(test))]
+impl Eq for () {
+    #[inline(always)]
+    fn eq(&self, _other: &()) -> bool { true }
+    #[inline(always)]
+    fn ne(&self, _other: &()) -> bool { false }
+}
+
+#[cfg(not(test))]
+impl Ord for () {
+    #[inline(always)]
+    fn lt(&self, _other: &()) -> bool { false }
+    #[inline(always)]
+    fn le(&self, _other: &()) -> bool { true }
+    #[inline(always)]
+    fn ge(&self, _other: &()) -> bool { true }
+    #[inline(always)]
+    fn gt(&self, _other: &()) -> bool { false }
+}
+
+#[cfg(not(test))]
+impl TotalOrd for () {
+    #[inline(always)]
+    fn cmp(&self, _other: &()) -> Ordering { Equal }
+}
+
+#[cfg(not(test))]
+impl TotalEq for () {
+    #[inline(always)]
+    fn equals(&self, _other: &()) -> bool { true }
+}
diff --git a/src/libstd/num/bigint.rs b/src/libstd/num/bigint.rs
deleted file mode 100644
index 21685b03c07..00000000000
--- a/src/libstd/num/bigint.rs
+++ /dev/null
@@ -1,2021 +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.
-
-/*!
-
-A Big integer (signed version: BigInt, unsigned version: BigUint).
-
-A BigUint is represented as an array of BigDigits.
-A BigInt is a combination of BigUint and Sign.
-*/
-
-use core::cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
-use core::num::{IntConvertible, Zero, One, ToStrRadix, FromStrRadix, Orderable};
-
-/**
-A BigDigit is a BigUint's composing element.
-
-A BigDigit is half the size of machine word size.
-*/
-#[cfg(target_arch = "x86")]
-#[cfg(target_arch = "arm")]
-#[cfg(target_arch = "mips")]
-pub type BigDigit = u16;
-
-/**
-A BigDigit is a BigUint's composing element.
-
-A BigDigit is half the size of machine word size.
-*/
-#[cfg(target_arch = "x86_64")]
-pub type BigDigit = u32;
-
-pub mod BigDigit {
-    use bigint::BigDigit;
-
-    #[cfg(target_arch = "x86")]
-    #[cfg(target_arch = "arm")]
-    #[cfg(target_arch = "mips")]
-    pub static bits: uint = 16;
-
-    #[cfg(target_arch = "x86_64")]
-    pub static bits: uint = 32;
-
-    pub static base: uint = 1 << bits;
-    priv static hi_mask: uint = (-1 as uint) << bits;
-    priv static lo_mask: uint = (-1 as uint) >> bits;
-
-    #[inline(always)]
-    priv fn get_hi(n: uint) -> BigDigit { (n >> bits) as BigDigit }
-    #[inline(always)]
-    priv fn get_lo(n: uint) -> BigDigit { (n & lo_mask) as BigDigit }
-
-    /// Split one machine sized unsigned integer into two BigDigits.
-    #[inline(always)]
-    pub fn from_uint(n: uint) -> (BigDigit, BigDigit) {
-        (get_hi(n), get_lo(n))
-    }
-
-    /// Join two BigDigits into one machine sized unsigned integer
-    #[inline(always)]
-    pub fn to_uint(hi: BigDigit, lo: BigDigit) -> uint {
-        (lo as uint) | ((hi as uint) << bits)
-    }
-}
-
-/**
-A big unsigned integer type.
-
-A BigUint-typed value BigUint { data: @[a, b, c] } represents a number
-(a + b * BigDigit::base + c * BigDigit::base^2).
-*/
-#[deriving(Clone)]
-pub struct BigUint {
-    priv data: ~[BigDigit]
-}
-
-impl Eq for BigUint {
-    #[inline(always)]
-    fn eq(&self, other: &BigUint) -> bool { self.equals(other) }
-    #[inline(always)]
-    fn ne(&self, other: &BigUint) -> bool { !self.equals(other) }
-}
-
-impl TotalEq for BigUint {
-    #[inline(always)]
-    fn equals(&self, other: &BigUint) -> bool {
-        match self.cmp(other) { Equal => true, _ => false }
-    }
-}
-
-impl Ord for BigUint {
-    #[inline(always)]
-    fn lt(&self, other: &BigUint) -> bool {
-        match self.cmp(other) { Less => true, _ => false}
-    }
-    #[inline(always)]
-    fn le(&self, other: &BigUint) -> bool {
-        match self.cmp(other) { Less | Equal => true, _ => false }
-    }
-    #[inline(always)]
-    fn ge(&self, other: &BigUint) -> bool {
-        match self.cmp(other) { Greater | Equal => true, _ => false }
-    }
-    #[inline(always)]
-    fn gt(&self, other: &BigUint) -> bool {
-        match self.cmp(other) { Greater => true, _ => false }
-    }
-}
-
-impl TotalOrd for BigUint {
-    #[inline(always)]
-    fn cmp(&self, other: &BigUint) -> Ordering {
-        let s_len = self.data.len(), o_len = other.data.len();
-        if s_len < o_len { return Less; }
-        if s_len > o_len { return Greater;  }
-
-        for self.data.eachi_reverse |i, elm| {
-            match (*elm, other.data[i]) {
-                (l, r) if l < r => return Less,
-                (l, r) if l > r => return Greater,
-                _               => loop
-            };
-        }
-        return Equal;
-    }
-}
-
-impl ToStr for BigUint {
-    #[inline(always)]
-    fn to_str(&self) -> ~str { self.to_str_radix(10) }
-}
-
-impl FromStr for BigUint {
-    #[inline(always)]
-    fn from_str(s: &str) -> Option<BigUint> {
-        FromStrRadix::from_str_radix(s, 10)
-    }
-}
-
-impl Num for BigUint {}
-
-impl Orderable for BigUint {
-    #[inline(always)]
-    fn min(&self, other: &BigUint) -> BigUint {
-        if self < other { self.clone() } else { other.clone() }
-    }
-
-    #[inline(always)]
-    fn max(&self, other: &BigUint) -> BigUint {
-        if self > other { self.clone() } else { other.clone() }
-    }
-
-    #[inline(always)]
-    fn clamp(&self, mn: &BigUint, mx: &BigUint) -> BigUint {
-        if self > mx { mx.clone() } else
-        if self < mn { mn.clone() } else { self.clone() }
-    }
-}
-
-impl Shl<uint, BigUint> for BigUint {
-    #[inline(always)]
-    fn shl(&self, rhs: &uint) -> BigUint {
-        let n_unit = *rhs / BigDigit::bits;
-        let n_bits = *rhs % BigDigit::bits;
-        return self.shl_unit(n_unit).shl_bits(n_bits);
-    }
-}
-
-impl Shr<uint, BigUint> for BigUint {
-    #[inline(always)]
-    fn shr(&self, rhs: &uint) -> BigUint {
-        let n_unit = *rhs / BigDigit::bits;
-        let n_bits = *rhs % BigDigit::bits;
-        return self.shr_unit(n_unit).shr_bits(n_bits);
-    }
-}
-
-impl Zero for BigUint {
-    #[inline(always)]
-    fn zero() -> BigUint { BigUint::new(~[]) }
-
-    #[inline(always)]
-    fn is_zero(&self) -> bool { self.data.is_empty() }
-}
-
-impl One for BigUint {
-    #[inline(always)]
-    fn one() -> BigUint { BigUint::new(~[1]) }
-}
-
-impl Unsigned for BigUint {}
-
-impl Add<BigUint, BigUint> for BigUint {
-    #[inline(always)]
-    fn add(&self, other: &BigUint) -> BigUint {
-        let new_len = uint::max(self.data.len(), other.data.len());
-
-        let mut carry = 0;
-        let sum = do vec::from_fn(new_len) |i| {
-            let ai = if i < self.data.len()  { self.data[i]  } else { 0 };
-            let bi = if i < other.data.len() { other.data[i] } else { 0 };
-            let (hi, lo) = BigDigit::from_uint(
-                (ai as uint) + (bi as uint) + (carry as uint)
-            );
-            carry = hi;
-            lo
-        };
-        if carry == 0 { return BigUint::new(sum) };
-        return BigUint::new(sum + [carry]);
-    }
-}
-
-impl Sub<BigUint, BigUint> for BigUint {
-    #[inline(always)]
-    fn sub(&self, other: &BigUint) -> BigUint {
-        let new_len = uint::max(self.data.len(), other.data.len());
-
-        let mut borrow = 0;
-        let diff = do vec::from_fn(new_len) |i| {
-            let ai = if i < self.data.len()  { self.data[i]  } else { 0 };
-            let bi = if i < other.data.len() { other.data[i] } else { 0 };
-            let (hi, lo) = BigDigit::from_uint(
-                (BigDigit::base) +
-                (ai as uint) - (bi as uint) - (borrow as uint)
-            );
-            /*
-            hi * (base) + lo == 1*(base) + ai - bi - borrow
-            => ai - bi - borrow < 0 <=> hi == 0
-            */
-            borrow = if hi == 0 { 1 } else { 0 };
-            lo
-        };
-
-        assert_eq!(borrow, 0);     // <=> assert!((self >= other));
-        return BigUint::new(diff);
-    }
-}
-
-impl Mul<BigUint, BigUint> for BigUint {
-    fn mul(&self, other: &BigUint) -> BigUint {
-        if self.is_zero() || other.is_zero() { return Zero::zero(); }
-
-        let s_len = self.data.len(), o_len = other.data.len();
-        if s_len == 1 { return mul_digit(other, self.data[0]);  }
-        if o_len == 1 { return mul_digit(self,  other.data[0]); }
-
-        // Using Karatsuba multiplication
-        // (a1 * base + a0) * (b1 * base + b0)
-        // = a1*b1 * base^2 +
-        //   (a1*b1 + a0*b0 - (a1-b0)*(b1-a0)) * base +
-        //   a0*b0
-        let half_len = uint::max(s_len, o_len) / 2;
-        let (sHi, sLo) = cut_at(self,  half_len);
-        let (oHi, oLo) = cut_at(other, half_len);
-
-        let ll = sLo * oLo;
-        let hh = sHi * oHi;
-        let mm = {
-            let (s1, n1) = sub_sign(sHi, sLo);
-            let (s2, n2) = sub_sign(oHi, oLo);
-            match (s1, s2) {
-                (Equal, _) | (_, Equal) => hh + ll,
-                (Less, Greater) | (Greater, Less) => hh + ll + (n1 * n2),
-                (Less, Less) | (Greater, Greater) => hh + ll - (n1 * n2)
-            }
-        };
-
-        return ll + mm.shl_unit(half_len) + hh.shl_unit(half_len * 2);
-
-        #[inline(always)]
-        fn mul_digit(a: &BigUint, n: BigDigit) -> BigUint {
-            if n == 0 { return Zero::zero(); }
-            if n == 1 { return copy *a; }
-
-            let mut carry = 0;
-            let prod = do vec::map(a.data) |ai| {
-                let (hi, lo) = BigDigit::from_uint(
-                    (*ai as uint) * (n as uint) + (carry as uint)
-                );
-                carry = hi;
-                lo
-            };
-            if carry == 0 { return BigUint::new(prod) };
-            return BigUint::new(prod + [carry]);
-        }
-
-        #[inline(always)]
-        fn cut_at(a: &BigUint, n: uint) -> (BigUint, BigUint) {
-            let mid = uint::min(a.data.len(), n);
-            return (BigUint::from_slice(vec::slice(a.data, mid,
-                                                   a.data.len())),
-                    BigUint::from_slice(vec::slice(a.data, 0, mid)));
-        }
-
-        #[inline(always)]
-        fn sub_sign(a: BigUint, b: BigUint) -> (Ordering, BigUint) {
-            match a.cmp(&b) {
-                Less    => (Less,    b - a),
-                Greater => (Greater, a - b),
-                _       => (Equal,   Zero::zero())
-            }
-        }
-    }
-}
-
-impl Div<BigUint, BigUint> for BigUint {
-    #[inline(always)]
-    fn div(&self, other: &BigUint) -> BigUint {
-        let (q, _) = self.div_rem(other);
-        return q;
-    }
-}
-
-impl Rem<BigUint, BigUint> for BigUint {
-    #[inline(always)]
-    fn rem(&self, other: &BigUint) -> BigUint {
-        let (_, r) = self.div_rem(other);
-        return r;
-    }
-}
-
-impl Neg<BigUint> for BigUint {
-    #[inline(always)]
-    fn neg(&self) -> BigUint { fail!() }
-}
-
-impl Integer for BigUint {
-    #[inline(always)]
-    fn div_rem(&self, other: &BigUint) -> (BigUint, BigUint) {
-        self.div_mod_floor(other)
-    }
-
-    #[inline(always)]
-    fn div_floor(&self, other: &BigUint) -> BigUint {
-        let (d, _) = self.div_mod_floor(other);
-        return d;
-    }
-
-    #[inline(always)]
-    fn mod_floor(&self, other: &BigUint) -> BigUint {
-        let (_, m) = self.div_mod_floor(other);
-        return m;
-    }
-
-    #[inline(always)]
-    fn div_mod_floor(&self, other: &BigUint) -> (BigUint, BigUint) {
-        if other.is_zero() { fail!() }
-        if self.is_zero() { return (Zero::zero(), Zero::zero()); }
-        if *other == One::one() { return (copy *self, Zero::zero()); }
-
-        match self.cmp(other) {
-            Less    => return (Zero::zero(), copy *self),
-            Equal   => return (One::one(), Zero::zero()),
-            Greater => {} // Do nothing
-        }
-
-        let mut shift = 0;
-        let mut n = *other.data.last();
-        while n < (1 << BigDigit::bits - 2) {
-            n <<= 1;
-            shift += 1;
-        }
-        assert!(shift < BigDigit::bits);
-        let (d, m) = div_mod_floor_inner(self << shift, other << shift);
-        return (d, m >> shift);
-
-        #[inline(always)]
-        fn div_mod_floor_inner(a: BigUint, b: BigUint) -> (BigUint, BigUint) {
-            let mut m = a;
-            let mut d = Zero::zero::<BigUint>();
-            let mut n = 1;
-            while m >= b {
-                let mut (d0, d_unit, b_unit) = div_estimate(&m, &b, n);
-                let mut prod = b * d0;
-                while prod > m {
-                    // FIXME(#6050): overloaded operators force moves with generic types
-                    // d0 -= d_unit
-                    d0   = d0 - d_unit;
-                    // FIXME(#6050): overloaded operators force moves with generic types
-                    // prod = prod - b_unit;
-                    prod = prod - b_unit
-                }
-                if d0.is_zero() {
-                    n = 2;
-                    loop;
-                }
-                n = 1;
-                // FIXME(#6102): Assignment operator for BigInt causes ICE
-                // d += d0;
-                d = d + d0;
-                // FIXME(#6102): Assignment operator for BigInt causes ICE
-                // m -= prod;
-                m = m - prod;
-            }
-            return (d, m);
-        }
-
-        #[inline(always)]
-        fn div_estimate(a: &BigUint, b: &BigUint, n: uint)
-            -> (BigUint, BigUint, BigUint) {
-            if a.data.len() < n {
-                return (Zero::zero(), Zero::zero(), copy *a);
-            }
-
-            let an = vec::slice(a.data, a.data.len() - n, a.data.len());
-            let bn = *b.data.last();
-            let mut d = ~[];
-            let mut carry = 0;
-            for an.each_reverse |elt| {
-                let ai = BigDigit::to_uint(carry, *elt);
-                let di = ai / (bn as uint);
-                assert!(di < BigDigit::base);
-                carry = (ai % (bn as uint)) as BigDigit;
-                d = ~[di as BigDigit] + d;
-            }
-
-            let shift = (a.data.len() - an.len()) - (b.data.len() - 1);
-            if shift == 0 {
-                return (BigUint::new(d), One::one(), copy *b);
-            }
-            return (BigUint::from_slice(d).shl_unit(shift),
-                    One::one::<BigUint>().shl_unit(shift),
-                    b.shl_unit(shift));
-        }
-    }
-
-    /**
-     * Calculates the Greatest Common Divisor (GCD) of the number and `other`
-     *
-     * The result is always positive
-     */
-    #[inline(always)]
-    fn gcd(&self, other: &BigUint) -> BigUint {
-        // Use Euclid's algorithm
-        let mut m = copy *self, n = copy *other;
-        while !m.is_zero() {
-            let temp = m;
-            m = n % temp;
-            n = temp;
-        }
-        return n;
-    }
-
-    /**
-     * Calculates the Lowest Common Multiple (LCM) of the number and `other`
-     */
-    #[inline(always)]
-    fn lcm(&self, other: &BigUint) -> BigUint { ((*self * *other) / self.gcd(other)) }
-
-    /// Returns `true` if the number can be divided by `other` without leaving a remainder
-    #[inline(always)]
-    fn is_multiple_of(&self, other: &BigUint) -> bool { (*self % *other).is_zero() }
-
-    /// Returns `true` if the number is divisible by `2`
-    #[inline(always)]
-    fn is_even(&self) -> bool {
-        // Considering only the last digit.
-        if self.data.is_empty() {
-            true
-        } else {
-            self.data[0].is_even()
-        }
-    }
-
-    /// Returns `true` if the number is not divisible by `2`
-    #[inline(always)]
-    fn is_odd(&self) -> bool { !self.is_even() }
-}
-
-impl IntConvertible for BigUint {
-    #[inline(always)]
-    fn to_int(&self) -> int {
-        uint::min(self.to_uint(), int::max_value as uint) as int
-    }
-
-    #[inline(always)]
-    fn from_int(n: int) -> BigUint {
-        if (n < 0) { Zero::zero() } else { BigUint::from_uint(n as uint) }
-    }
-}
-
-impl ToStrRadix for BigUint {
-    #[inline(always)]
-    fn to_str_radix(&self, radix: uint) -> ~str {
-        assert!(1 < radix && radix <= 16);
-        let (base, max_len) = get_radix_base(radix);
-        if base == BigDigit::base {
-            return fill_concat(self.data, radix, max_len)
-        }
-        return fill_concat(convert_base(copy *self, base), radix, max_len);
-
-        #[inline(always)]
-        fn convert_base(n: BigUint, base: uint) -> ~[BigDigit] {
-            let divider    = BigUint::from_uint(base);
-            let mut result = ~[];
-            let mut m      = n;
-            while m > divider {
-                let (d, m0) = m.div_mod_floor(&divider);
-                result += [m0.to_uint() as BigDigit];
-                m = d;
-            }
-            if !m.is_zero() {
-                result += [m.to_uint() as BigDigit];
-            }
-            return result;
-        }
-
-        #[inline(always)]
-        fn fill_concat(v: &[BigDigit], radix: uint, l: uint) -> ~str {
-            if v.is_empty() { return ~"0" }
-            let s = str::concat(vec::reversed(v).map(|n| {
-                let s = uint::to_str_radix(*n as uint, radix);
-                str::from_chars(vec::from_elem(l - s.len(), '0')) + s
-            }));
-            str::trim_left_chars(s, ['0']).to_owned()
-        }
-    }
-}
-
-impl FromStrRadix for BigUint {
-    /// Creates and initializes an BigUint.
-    #[inline(always)]
-    pub fn from_str_radix(s: &str, radix: uint)
-        -> Option<BigUint> {
-        BigUint::parse_bytes(str::to_bytes(s), radix)
-    }
-}
-
-impl BigUint {
-    /// Creates and initializes an BigUint.
-    #[inline(always)]
-    pub fn new(v: ~[BigDigit]) -> BigUint {
-        // omit trailing zeros
-        let new_len = v.rposition(|n| *n != 0).map_default(0, |p| *p + 1);
-
-        if new_len == v.len() { return BigUint { data: v }; }
-        let mut v = v;
-        v.truncate(new_len);
-        return BigUint { data: v };
-    }
-
-    /// Creates and initializes an BigUint.
-    #[inline(always)]
-    pub fn from_uint(n: uint) -> BigUint {
-        match BigDigit::from_uint(n) {
-            (0,  0)  => Zero::zero(),
-            (0,  n0) => BigUint::new(~[n0]),
-            (n1, n0) => BigUint::new(~[n0, n1])
-        }
-    }
-
-    /// Creates and initializes an BigUint.
-    #[inline(always)]
-    pub fn from_slice(slice: &[BigDigit]) -> BigUint {
-        return BigUint::new(vec::to_owned(slice));
-    }
-
-    /// Creates and initializes an BigUint.
-    #[inline(always)]
-    pub fn parse_bytes(buf: &[u8], radix: uint)
-        -> Option<BigUint> {
-        let (base, unit_len) = get_radix_base(radix);
-        let base_num: BigUint = BigUint::from_uint(base);
-
-        let mut end             = buf.len();
-        let mut n: BigUint      = Zero::zero();
-        let mut power: BigUint  = One::one();
-        loop {
-            let start = uint::max(end, unit_len) - unit_len;
-            match uint::parse_bytes(vec::slice(buf, start, end), radix) {
-                // FIXME(#6102): Assignment operator for BigInt causes ICE
-                // Some(d) => n += BigUint::from_uint(d) * power,
-                Some(d) => n = n + BigUint::from_uint(d) * power,
-                None    => return None
-            }
-            if end <= unit_len {
-                return Some(n);
-            }
-            end -= unit_len;
-            // FIXME(#6050): overloaded operators force moves with generic types
-            // power *= base_num;
-            power = power * base_num;
-        }
-    }
-
-    #[inline(always)]
-    pub fn to_uint(&self) -> uint {
-        match self.data.len() {
-            0 => 0,
-            1 => self.data[0] as uint,
-            2 => BigDigit::to_uint(self.data[1], self.data[0]),
-            _ => uint::max_value
-        }
-    }
-
-    #[inline(always)]
-    priv fn shl_unit(&self, n_unit: uint) -> BigUint {
-        if n_unit == 0 || self.is_zero() { return copy *self; }
-
-        return BigUint::new(vec::from_elem(n_unit, 0) + self.data);
-    }
-
-    #[inline(always)]
-    priv fn shl_bits(&self, n_bits: uint) -> BigUint {
-        if n_bits == 0 || self.is_zero() { return copy *self; }
-
-        let mut carry = 0;
-        let shifted = do vec::map(self.data) |elem| {
-            let (hi, lo) = BigDigit::from_uint(
-                (*elem as uint) << n_bits | (carry as uint)
-            );
-            carry = hi;
-            lo
-        };
-        if carry == 0 { return BigUint::new(shifted); }
-        return BigUint::new(shifted + [carry]);
-    }
-
-    #[inline(always)]
-    priv fn shr_unit(&self, n_unit: uint) -> BigUint {
-        if n_unit == 0 { return copy *self; }
-        if self.data.len() < n_unit { return Zero::zero(); }
-        return BigUint::from_slice(
-            vec::slice(self.data, n_unit, self.data.len())
-        );
-    }
-
-    #[inline(always)]
-    priv fn shr_bits(&self, n_bits: uint) -> BigUint {
-        if n_bits == 0 || self.data.is_empty() { return copy *self; }
-
-        let mut borrow = 0;
-        let mut shifted = ~[];
-        for self.data.each_reverse |elem| {
-            shifted = ~[(*elem >> n_bits) | borrow] + shifted;
-            borrow = *elem << (BigDigit::bits - n_bits);
-        }
-        return BigUint::new(shifted);
-    }
-}
-
-#[cfg(target_arch = "x86_64")]
-#[inline(always)]
-priv fn get_radix_base(radix: uint) -> (uint, uint) {
-    assert!(1 < radix && radix <= 16);
-    match radix {
-        2  => (4294967296, 32),
-        3  => (3486784401, 20),
-        4  => (4294967296, 16),
-        5  => (1220703125, 13),
-        6  => (2176782336, 12),
-        7  => (1977326743, 11),
-        8  => (1073741824, 10),
-        9  => (3486784401, 10),
-        10 => (1000000000, 9),
-        11 => (2357947691, 9),
-        12 => (429981696,  8),
-        13 => (815730721,  8),
-        14 => (1475789056, 8),
-        15 => (2562890625, 8),
-        16 => (4294967296, 8),
-        _  => fail!()
-    }
-}
-
-#[cfg(target_arch = "arm")]
-#[cfg(target_arch = "x86")]
-#[cfg(target_arch = "mips")]
-#[inline(always)]
-priv fn get_radix_base(radix: uint) -> (uint, uint) {
-    assert!(1 < radix && radix <= 16);
-    match radix {
-        2  => (65536, 16),
-        3  => (59049, 10),
-        4  => (65536, 8),
-        5  => (15625, 6),
-        6  => (46656, 6),
-        7  => (16807, 5),
-        8  => (32768, 5),
-        9  => (59049, 5),
-        10 => (10000, 4),
-        11 => (14641, 4),
-        12 => (20736, 4),
-        13 => (28561, 4),
-        14 => (38416, 4),
-        15 => (50625, 4),
-        16 => (65536, 4),
-        _  => fail!()
-    }
-}
-
-/// A Sign is a BigInt's composing element.
-#[deriving(Eq, Clone)]
-pub enum Sign { Minus, Zero, Plus }
-
-impl Ord for Sign {
-    #[inline(always)]
-    fn lt(&self, other: &Sign) -> bool {
-        match self.cmp(other) { Less => true, _ => false}
-    }
-    #[inline(always)]
-    fn le(&self, other: &Sign) -> bool {
-        match self.cmp(other) { Less | Equal => true, _ => false }
-    }
-    #[inline(always)]
-    fn ge(&self, other: &Sign) -> bool {
-        match self.cmp(other) { Greater | Equal => true, _ => false }
-    }
-    #[inline(always)]
-    fn gt(&self, other: &Sign) -> bool {
-        match self.cmp(other) { Greater => true, _ => false }
-    }
-}
-
-impl TotalOrd for Sign {
-    #[inline(always)]
-    fn cmp(&self, other: &Sign) -> Ordering {
-        match (*self, *other) {
-          (Minus, Minus) | (Zero,  Zero) | (Plus, Plus) => Equal,
-          (Minus, Zero)  | (Minus, Plus) | (Zero, Plus) => Less,
-          _                                             => Greater
-        }
-    }
-}
-
-impl Neg<Sign> for Sign {
-    /// Negate Sign value.
-    #[inline(always)]
-    fn neg(&self) -> Sign {
-        match *self {
-          Minus => Plus,
-          Zero  => Zero,
-          Plus  => Minus
-        }
-    }
-}
-
-/// A big signed integer type.
-#[deriving(Clone)]
-pub struct BigInt {
-    priv sign: Sign,
-    priv data: BigUint
-}
-
-impl Eq for BigInt {
-    #[inline(always)]
-    fn eq(&self, other: &BigInt) -> bool { self.equals(other) }
-    #[inline(always)]
-    fn ne(&self, other: &BigInt) -> bool { !self.equals(other) }
-}
-
-impl TotalEq for BigInt {
-    #[inline(always)]
-    fn equals(&self, other: &BigInt) -> bool {
-        match self.cmp(other) { Equal => true, _ => false }
-    }
-}
-
-impl Ord for BigInt {
-    #[inline(always)]
-    fn lt(&self, other: &BigInt) -> bool {
-        match self.cmp(other) { Less => true, _ => false}
-    }
-    #[inline(always)]
-    fn le(&self, other: &BigInt) -> bool {
-        match self.cmp(other) { Less | Equal => true, _ => false }
-    }
-    #[inline(always)]
-    fn ge(&self, other: &BigInt) -> bool {
-        match self.cmp(other) { Greater | Equal => true, _ => false }
-    }
-    #[inline(always)]
-    fn gt(&self, other: &BigInt) -> bool {
-        match self.cmp(other) { Greater => true, _ => false }
-    }
-}
-
-impl TotalOrd for BigInt {
-    #[inline(always)]
-    fn cmp(&self, other: &BigInt) -> Ordering {
-        let scmp = self.sign.cmp(&other.sign);
-        if scmp != Equal { return scmp; }
-
-        match self.sign {
-            Zero  => Equal,
-            Plus  => self.data.cmp(&other.data),
-            Minus => other.data.cmp(&self.data),
-        }
-    }
-}
-
-impl ToStr for BigInt {
-    #[inline(always)]
-    fn to_str(&self) -> ~str { self.to_str_radix(10) }
-}
-
-impl FromStr for BigInt {
-    #[inline(always)]
-    fn from_str(s: &str) -> Option<BigInt> {
-        FromStrRadix::from_str_radix(s, 10)
-    }
-}
-
-impl Num for BigInt {}
-
-impl Orderable for BigInt {
-    #[inline(always)]
-    fn min(&self, other: &BigInt) -> BigInt {
-        if self < other { self.clone() } else { other.clone() }
-    }
-
-    #[inline(always)]
-    fn max(&self, other: &BigInt) -> BigInt {
-        if self > other { self.clone() } else { other.clone() }
-    }
-
-    #[inline(always)]
-    fn clamp(&self, mn: &BigInt, mx: &BigInt) -> BigInt {
-        if self > mx { mx.clone() } else
-        if self < mn { mn.clone() } else { self.clone() }
-    }
-}
-
-impl Shl<uint, BigInt> for BigInt {
-    #[inline(always)]
-    fn shl(&self, rhs: &uint) -> BigInt {
-        BigInt::from_biguint(self.sign, self.data << *rhs)
-    }
-}
-
-impl Shr<uint, BigInt> for BigInt {
-    #[inline(always)]
-    fn shr(&self, rhs: &uint) -> BigInt {
-        BigInt::from_biguint(self.sign, self.data >> *rhs)
-    }
-}
-
-impl Zero for BigInt {
-    #[inline(always)]
-    fn zero() -> BigInt {
-        BigInt::from_biguint(Zero, Zero::zero())
-    }
-
-    #[inline(always)]
-    fn is_zero(&self) -> bool { self.sign == Zero }
-}
-
-impl One for BigInt {
-    #[inline(always)]
-    fn one() -> BigInt {
-        BigInt::from_biguint(Plus, One::one())
-    }
-}
-
-impl Signed for BigInt {
-    #[inline(always)]
-    fn abs(&self) -> BigInt {
-        match self.sign {
-            Plus | Zero => self.clone(),
-            Minus => BigInt::from_biguint(Plus, self.data.clone())
-        }
-    }
-
-    #[inline(always)]
-    fn abs_sub(&self, other: &BigInt) -> BigInt {
-        if *self <= *other { Zero::zero() } else { *self - *other }
-    }
-
-    #[inline(always)]
-    fn signum(&self) -> BigInt {
-        match self.sign {
-            Plus  => BigInt::from_biguint(Plus, One::one()),
-            Minus => BigInt::from_biguint(Minus, One::one()),
-            Zero  => Zero::zero(),
-        }
-    }
-
-    #[inline(always)]
-    fn is_positive(&self) -> bool { self.sign == Plus }
-
-    #[inline(always)]
-    fn is_negative(&self) -> bool { self.sign == Minus }
-}
-
-impl Add<BigInt, BigInt> for BigInt {
-    #[inline(always)]
-    fn add(&self, other: &BigInt) -> BigInt {
-        match (self.sign, other.sign) {
-            (Zero, _)      => other.clone(),
-            (_,    Zero)   => self.clone(),
-            (Plus, Plus)   => BigInt::from_biguint(Plus,
-                                                   self.data + other.data),
-            (Plus, Minus)  => self - (-*other),
-            (Minus, Plus)  => other - (-*self),
-            (Minus, Minus) => -((-self) + (-*other))
-        }
-    }
-}
-
-impl Sub<BigInt, BigInt> for BigInt {
-    #[inline(always)]
-    fn sub(&self, other: &BigInt) -> BigInt {
-        match (self.sign, other.sign) {
-            (Zero, _)    => -other,
-            (_,    Zero) => self.clone(),
-            (Plus, Plus) => match self.data.cmp(&other.data) {
-                Less    => BigInt::from_biguint(Minus, other.data - self.data),
-                Greater => BigInt::from_biguint(Plus, self.data - other.data),
-                Equal   => Zero::zero()
-            },
-            (Plus, Minus) => self + (-*other),
-            (Minus, Plus) => -((-self) + *other),
-            (Minus, Minus) => (-other) - (-*self)
-        }
-    }
-}
-
-impl Mul<BigInt, BigInt> for BigInt {
-    #[inline(always)]
-    fn mul(&self, other: &BigInt) -> BigInt {
-        match (self.sign, other.sign) {
-            (Zero, _)     | (_,     Zero)  => Zero::zero(),
-            (Plus, Plus)  | (Minus, Minus) => {
-                BigInt::from_biguint(Plus, self.data * other.data)
-            },
-            (Plus, Minus) | (Minus, Plus) => {
-                BigInt::from_biguint(Minus, self.data * other.data)
-            }
-        }
-    }
-}
-
-impl Div<BigInt, BigInt> for BigInt {
-    #[inline(always)]
-    fn div(&self, other: &BigInt) -> BigInt {
-        let (q, _) = self.div_rem(other);
-        return q;
-    }
-}
-
-impl Rem<BigInt, BigInt> for BigInt {
-    #[inline(always)]
-    fn rem(&self, other: &BigInt) -> BigInt {
-        let (_, r) = self.div_rem(other);
-        return r;
-    }
-}
-
-impl Neg<BigInt> for BigInt {
-    #[inline(always)]
-    fn neg(&self) -> BigInt {
-        BigInt::from_biguint(self.sign.neg(), self.data.clone())
-    }
-}
-
-impl Integer for BigInt {
-    #[inline(always)]
-    fn div_rem(&self, other: &BigInt) -> (BigInt, BigInt) {
-        // r.sign == self.sign
-        let (d_ui, r_ui) = self.data.div_mod_floor(&other.data);
-        let d = BigInt::from_biguint(Plus, d_ui);
-        let r = BigInt::from_biguint(Plus, r_ui);
-        match (self.sign, other.sign) {
-            (_,    Zero)   => fail!(),
-            (Plus, Plus)  | (Zero, Plus)  => ( d,  r),
-            (Plus, Minus) | (Zero, Minus) => (-d,  r),
-            (Minus, Plus)                 => (-d, -r),
-            (Minus, Minus)                => ( d, -r)
-        }
-    }
-
-    #[inline(always)]
-    fn div_floor(&self, other: &BigInt) -> BigInt {
-        let (d, _) = self.div_mod_floor(other);
-        return d;
-    }
-
-    #[inline(always)]
-    fn mod_floor(&self, other: &BigInt) -> BigInt {
-        let (_, m) = self.div_mod_floor(other);
-        return m;
-    }
-
-    #[inline(always)]
-    fn div_mod_floor(&self, other: &BigInt) -> (BigInt, BigInt) {
-        // m.sign == other.sign
-        let (d_ui, m_ui) = self.data.div_rem(&other.data);
-        let d = BigInt::from_biguint(Plus, d_ui),
-            m = BigInt::from_biguint(Plus, m_ui);
-        match (self.sign, other.sign) {
-            (_,    Zero)   => fail!(),
-            (Plus, Plus)  | (Zero, Plus)  => (d, m),
-            (Plus, Minus) | (Zero, Minus) => if m.is_zero() {
-                (-d, Zero::zero())
-            } else {
-                (-d - One::one(), m + *other)
-            },
-            (Minus, Plus) => if m.is_zero() {
-                (-d, Zero::zero())
-            } else {
-                (-d - One::one(), other - m)
-            },
-            (Minus, Minus) => (d, -m)
-        }
-    }
-
-    /**
-     * Calculates the Greatest Common Divisor (GCD) of the number and `other`
-     *
-     * The result is always positive
-     */
-    #[inline(always)]
-    fn gcd(&self, other: &BigInt) -> BigInt {
-        BigInt::from_biguint(Plus, self.data.gcd(&other.data))
-    }
-
-    /**
-     * Calculates the Lowest Common Multiple (LCM) of the number and `other`
-     */
-    #[inline(always)]
-    fn lcm(&self, other: &BigInt) -> BigInt {
-        BigInt::from_biguint(Plus, self.data.lcm(&other.data))
-    }
-
-    /// Returns `true` if the number can be divided by `other` without leaving a remainder
-    #[inline(always)]
-    fn is_multiple_of(&self, other: &BigInt) -> bool { self.data.is_multiple_of(&other.data) }
-
-    /// Returns `true` if the number is divisible by `2`
-    #[inline(always)]
-    fn is_even(&self) -> bool { self.data.is_even() }
-
-    /// Returns `true` if the number is not divisible by `2`
-    #[inline(always)]
-    fn is_odd(&self) -> bool { self.data.is_odd() }
-}
-
-impl IntConvertible for BigInt {
-    #[inline(always)]
-    fn to_int(&self) -> int {
-        match self.sign {
-            Plus  => uint::min(self.to_uint(), int::max_value as uint) as int,
-            Zero  => 0,
-            Minus => uint::min((-self).to_uint(),
-                               (int::max_value as uint) + 1) as int
-        }
-    }
-
-    #[inline(always)]
-    fn from_int(n: int) -> BigInt {
-        if n > 0 {
-           return BigInt::from_biguint(Plus,  BigUint::from_uint(n as uint));
-        }
-        if n < 0 {
-            return BigInt::from_biguint(
-                Minus, BigUint::from_uint(uint::max_value - (n as uint) + 1)
-            );
-        }
-        return Zero::zero();
-    }
-}
-
-impl ToStrRadix for BigInt {
-    #[inline(always)]
-    fn to_str_radix(&self, radix: uint) -> ~str {
-        match self.sign {
-            Plus  => self.data.to_str_radix(radix),
-            Zero  => ~"0",
-            Minus => ~"-" + self.data.to_str_radix(radix)
-        }
-    }
-}
-
-impl FromStrRadix for BigInt {
-    /// Creates and initializes an BigInt.
-    #[inline(always)]
-    fn from_str_radix(s: &str, radix: uint)
-        -> Option<BigInt> {
-        BigInt::parse_bytes(str::to_bytes(s), radix)
-    }
-}
-
-pub impl BigInt {
-    /// Creates and initializes an BigInt.
-    #[inline(always)]
-    pub fn new(sign: Sign, v: ~[BigDigit]) -> BigInt {
-        BigInt::from_biguint(sign, BigUint::new(v))
-    }
-
-    /// Creates and initializes an BigInt.
-    #[inline(always)]
-    pub fn from_biguint(sign: Sign, data: BigUint) -> BigInt {
-        if sign == Zero || data.is_zero() {
-            return BigInt { sign: Zero, data: Zero::zero() };
-        }
-        return BigInt { sign: sign, data: data };
-    }
-
-    /// Creates and initializes an BigInt.
-    #[inline(always)]
-    pub fn from_uint(n: uint) -> BigInt {
-        if n == 0 { return Zero::zero(); }
-        return BigInt::from_biguint(Plus, BigUint::from_uint(n));
-    }
-
-    /// Creates and initializes an BigInt.
-    #[inline(always)]
-    pub fn from_slice(sign: Sign, slice: &[BigDigit]) -> BigInt {
-        BigInt::from_biguint(sign, BigUint::from_slice(slice))
-    }
-
-    /// Creates and initializes an BigInt.
-    #[inline(always)]
-    pub fn parse_bytes(buf: &[u8], radix: uint)
-        -> Option<BigInt> {
-        if buf.is_empty() { return None; }
-        let mut sign  = Plus;
-        let mut start = 0;
-        if buf[0] == ('-' as u8) {
-            sign  = Minus;
-            start = 1;
-        }
-        return BigUint::parse_bytes(vec::slice(buf, start, buf.len()), radix)
-            .map_consume(|bu| BigInt::from_biguint(sign, bu));
-    }
-
-    #[inline(always)]
-    fn to_uint(&self) -> uint {
-        match self.sign {
-            Plus  => self.data.to_uint(),
-            Zero  => 0,
-            Minus => 0
-        }
-    }
-}
-
-#[cfg(test)]
-mod biguint_tests {
-    use super::*;
-    use core::num::{IntConvertible, Zero, One, FromStrRadix};
-    use core::cmp::{Less, Equal, Greater};
-
-    #[test]
-    fn test_from_slice() {
-        fn check(slice: &[BigDigit], data: &[BigDigit]) {
-            assert!(data == BigUint::from_slice(slice).data);
-        }
-        check(~[1], ~[1]);
-        check(~[0, 0, 0], ~[]);
-        check(~[1, 2, 0, 0], ~[1, 2]);
-        check(~[0, 0, 1, 2], ~[0, 0, 1, 2]);
-        check(~[0, 0, 1, 2, 0, 0], ~[0, 0, 1, 2]);
-        check(~[-1], ~[-1]);
-    }
-
-    #[test]
-    fn test_cmp() {
-        let data = [ &[], &[1], &[2], &[-1], &[0, 1], &[2, 1], &[1, 1, 1]  ]
-            .map(|v| BigUint::from_slice(*v));
-        for data.eachi |i, ni| {
-            for vec::slice(data, i, data.len()).eachi |j0, nj| {
-                let j = j0 + i;
-                if i == j {
-                    assert_eq!(ni.cmp(nj), Equal);
-                    assert_eq!(nj.cmp(ni), Equal);
-                    assert_eq!(ni, nj);
-                    assert!(!(ni != nj));
-                    assert!(ni <= nj);
-                    assert!(ni >= nj);
-                    assert!(!(ni < nj));
-                    assert!(!(ni > nj));
-                } else {
-                    assert_eq!(ni.cmp(nj), Less);
-                    assert_eq!(nj.cmp(ni), Greater);
-
-                    assert!(!(ni == nj));
-                    assert!(ni != nj);
-
-                    assert!(ni <= nj);
-                    assert!(!(ni >= nj));
-                    assert!(ni < nj);
-                    assert!(!(ni > nj));
-
-                    assert!(!(nj <= ni));
-                    assert!(nj >= ni);
-                    assert!(!(nj < ni));
-                    assert!(nj > ni);
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn test_shl() {
-        fn check(v: ~[BigDigit], shift: uint, ans: ~[BigDigit]) {
-            assert_eq!(BigUint::new(v) << shift, BigUint::new(ans));
-        }
-
-        check(~[], 3, ~[]);
-        check(~[1, 1, 1], 3, ~[1 << 3, 1 << 3, 1 << 3]);
-        check(~[1 << (BigDigit::bits - 2)], 2, ~[0, 1]);
-        check(~[1 << (BigDigit::bits - 2)], 3, ~[0, 2]);
-        check(~[1 << (BigDigit::bits - 2)], 3 + BigDigit::bits, ~[0, 0, 2]);
-
-        test_shl_bits();
-
-        #[cfg(target_arch = "x86_64")]
-        fn test_shl_bits() {
-            check(~[0x7654_3210, 0xfedc_ba98,
-                    0x7654_3210, 0xfedc_ba98], 4,
-                  ~[0x6543_2100, 0xedcb_a987,
-                    0x6543_210f, 0xedcb_a987, 0xf]);
-            check(~[0x2222_1111, 0x4444_3333,
-                    0x6666_5555, 0x8888_7777], 16,
-                  ~[0x1111_0000, 0x3333_2222,
-                    0x5555_4444, 0x7777_6666, 0x8888]);
-        }
-
-        #[cfg(target_arch = "arm")]
-        #[cfg(target_arch = "x86")]
-        #[cfg(target_arch = "mips")]
-        fn test_shl_bits() {
-            check(~[0x3210, 0x7654, 0xba98, 0xfedc,
-                    0x3210, 0x7654, 0xba98, 0xfedc], 4,
-                  ~[0x2100, 0x6543, 0xa987, 0xedcb,
-                    0x210f, 0x6543, 0xa987, 0xedcb, 0xf]);
-            check(~[0x1111, 0x2222, 0x3333, 0x4444,
-                    0x5555, 0x6666, 0x7777, 0x8888], 16,
-                  ~[0x0000, 0x1111, 0x2222, 0x3333,
-                    0x4444, 0x5555, 0x6666, 0x7777, 0x8888]);
-        }
-
-    }
-
-    #[test]
-    #[ignore(cfg(target_arch = "x86"))]
-    #[ignore(cfg(target_arch = "arm"))]
-    #[ignore(cfg(target_arch = "mips"))]
-    fn test_shr() {
-        fn check(v: ~[BigDigit], shift: uint, ans: ~[BigDigit]) {
-            assert_eq!(BigUint::new(v) >> shift, BigUint::new(ans));
-        }
-
-        check(~[], 3, ~[]);
-        check(~[1, 1, 1], 3,
-              ~[1 << (BigDigit::bits - 3), 1 << (BigDigit::bits - 3)]);
-        check(~[1 << 2], 2, ~[1]);
-        check(~[1, 2], 3, ~[1 << (BigDigit::bits - 2)]);
-        check(~[1, 1, 2], 3 + BigDigit::bits, ~[1 << (BigDigit::bits - 2)]);
-        check(~[0, 1], 1, ~[0x80000000]);
-        test_shr_bits();
-
-        #[cfg(target_arch = "x86_64")]
-        fn test_shr_bits() {
-            check(~[0x6543_2100, 0xedcb_a987,
-                    0x6543_210f, 0xedcb_a987, 0xf], 4,
-                  ~[0x7654_3210, 0xfedc_ba98,
-                    0x7654_3210, 0xfedc_ba98]);
-            check(~[0x1111_0000, 0x3333_2222,
-                    0x5555_4444, 0x7777_6666, 0x8888], 16,
-                  ~[0x2222_1111, 0x4444_3333,
-                    0x6666_5555, 0x8888_7777]);
-        }
-
-        #[cfg(target_arch = "arm")]
-        #[cfg(target_arch = "x86")]
-        #[cfg(target_arch = "mips")]
-        fn test_shr_bits() {
-            check(~[0x2100, 0x6543, 0xa987, 0xedcb,
-                    0x210f, 0x6543, 0xa987, 0xedcb, 0xf], 4,
-                  ~[0x3210, 0x7654, 0xba98, 0xfedc,
-                    0x3210, 0x7654, 0xba98, 0xfedc]);
-            check(~[0x0000, 0x1111, 0x2222, 0x3333,
-                    0x4444, 0x5555, 0x6666, 0x7777, 0x8888], 16,
-                  ~[0x1111, 0x2222, 0x3333, 0x4444,
-                    0x5555, 0x6666, 0x7777, 0x8888]);
-        }
-    }
-
-    #[test]
-    fn test_convert_int() {
-        fn check(v: ~[BigDigit], i: int) {
-            let b = BigUint::new(v);
-            assert!(b == IntConvertible::from_int(i));
-            assert!(b.to_int() == i);
-        }
-
-        check(~[], 0);
-        check(~[1], 1);
-        check(~[-1], (uint::max_value >> BigDigit::bits) as int);
-        check(~[ 0,  1], ((uint::max_value >> BigDigit::bits) + 1) as int);
-        check(~[-1, -1 >> 1], int::max_value);
-
-        assert_eq!(BigUint::new(~[0, -1]).to_int(), int::max_value);
-        assert_eq!(BigUint::new(~[0, 0, 1]).to_int(), int::max_value);
-        assert_eq!(BigUint::new(~[0, 0, -1]).to_int(), int::max_value);
-    }
-
-    #[test]
-    fn test_convert_uint() {
-        fn check(v: ~[BigDigit], u: uint) {
-            let b = BigUint::new(v);
-            assert!(b == BigUint::from_uint(u));
-            assert!(b.to_uint() == u);
-        }
-
-        check(~[], 0);
-        check(~[ 1], 1);
-        check(~[-1], uint::max_value >> BigDigit::bits);
-        check(~[ 0,  1], (uint::max_value >> BigDigit::bits) + 1);
-        check(~[ 0, -1], uint::max_value << BigDigit::bits);
-        check(~[-1, -1], uint::max_value);
-
-        assert_eq!(BigUint::new(~[0, 0, 1]).to_uint(), uint::max_value);
-        assert_eq!(BigUint::new(~[0, 0, -1]).to_uint(), uint::max_value);
-    }
-
-    static sum_triples: &'static [(&'static [BigDigit],
-                                   &'static [BigDigit],
-                                   &'static [BigDigit])] = &[
-        (&[],          &[],       &[]),
-        (&[],          &[ 1],     &[ 1]),
-        (&[ 1],        &[ 1],     &[ 2]),
-        (&[ 1],        &[ 1,  1], &[ 2,  1]),
-        (&[ 1],        &[-1],     &[ 0,  1]),
-        (&[ 1],        &[-1, -1], &[ 0,  0, 1]),
-        (&[-1, -1],    &[-1, -1], &[-2, -1, 1]),
-        (&[ 1,  1, 1], &[-1, -1], &[ 0,  1, 2]),
-        (&[ 2,  2, 1], &[-1, -2], &[ 1,  1, 2])
-    ];
-
-    #[test]
-    fn test_add() {
-        for sum_triples.each |elm| {
-            let (aVec, bVec, cVec) = *elm;
-            let a = BigUint::from_slice(aVec);
-            let b = BigUint::from_slice(bVec);
-            let c = BigUint::from_slice(cVec);
-
-            assert!(a + b == c);
-            assert!(b + a == c);
-        }
-    }
-
-    #[test]
-    fn test_sub() {
-        for sum_triples.each |elm| {
-            let (aVec, bVec, cVec) = *elm;
-            let a = BigUint::from_slice(aVec);
-            let b = BigUint::from_slice(bVec);
-            let c = BigUint::from_slice(cVec);
-
-            assert!(c - a == b);
-            assert!(c - b == a);
-        }
-    }
-
-    static mul_triples: &'static [(&'static [BigDigit],
-                                   &'static [BigDigit],
-                                   &'static [BigDigit])] = &[
-        (&[],               &[],               &[]),
-        (&[],               &[ 1],             &[]),
-        (&[ 2],             &[],               &[]),
-        (&[ 1],             &[ 1],             &[1]),
-        (&[ 2],             &[ 3],             &[ 6]),
-        (&[ 1],             &[ 1,  1,  1],     &[1, 1,  1]),
-        (&[ 1,  2,  3],     &[ 3],             &[ 3,  6,  9]),
-        (&[ 1,  1,  1],     &[-1],             &[-1, -1, -1]),
-        (&[ 1,  2,  3],     &[-1],             &[-1, -2, -2, 2]),
-        (&[ 1,  2,  3,  4], &[-1],             &[-1, -2, -2, -2, 3]),
-        (&[-1],             &[-1],             &[ 1, -2]),
-        (&[-1, -1],         &[-1],             &[ 1, -1, -2]),
-        (&[-1, -1, -1],     &[-1],             &[ 1, -1, -1, -2]),
-        (&[-1, -1, -1, -1], &[-1],             &[ 1, -1, -1, -1, -2]),
-        (&[-1/2 + 1],       &[ 2],             &[ 0,  1]),
-        (&[0, -1/2 + 1],    &[ 2],             &[ 0,  0,  1]),
-        (&[ 1,  2],         &[ 1,  2,  3],     &[1, 4,  7,  6]),
-        (&[-1, -1],         &[-1, -1, -1],     &[1, 0, -1, -2, -1]),
-        (&[-1, -1, -1],     &[-1, -1, -1, -1], &[1, 0,  0, -1, -2, -1, -1]),
-        (&[ 0,  0,  1],     &[ 1,  2,  3],     &[0, 0,  1,  2,  3]),
-        (&[ 0,  0,  1],     &[ 0,  0,  0,  1], &[0, 0,  0,  0,  0,  1])
-    ];
-
-    static div_rem_quadruples: &'static [(&'static [BigDigit],
-                                           &'static [BigDigit],
-                                           &'static [BigDigit],
-                                           &'static [BigDigit])]
-        = &[
-            (&[ 1],        &[ 2], &[],               &[1]),
-            (&[ 1,  1],    &[ 2], &[-1/2+1],         &[1]),
-            (&[ 1,  1, 1], &[ 2], &[-1/2+1, -1/2+1], &[1]),
-            (&[ 0,  1],    &[-1], &[1],              &[1]),
-            (&[-1, -1],    &[-2], &[2, 1],           &[3])
-        ];
-
-    #[test]
-    fn test_mul() {
-        for mul_triples.each |elm| {
-            let (aVec, bVec, cVec) = *elm;
-            let a = BigUint::from_slice(aVec);
-            let b = BigUint::from_slice(bVec);
-            let c = BigUint::from_slice(cVec);
-
-            assert!(a * b == c);
-            assert!(b * a == c);
-        }
-
-        for div_rem_quadruples.each |elm| {
-            let (aVec, bVec, cVec, dVec) = *elm;
-            let a = BigUint::from_slice(aVec);
-            let b = BigUint::from_slice(bVec);
-            let c = BigUint::from_slice(cVec);
-            let d = BigUint::from_slice(dVec);
-
-            assert!(a == b * c + d);
-            assert!(a == c * b + d);
-        }
-    }
-
-    #[test]
-    fn test_div_rem() {
-        for mul_triples.each |elm| {
-            let (aVec, bVec, cVec) = *elm;
-            let a = BigUint::from_slice(aVec);
-            let b = BigUint::from_slice(bVec);
-            let c = BigUint::from_slice(cVec);
-
-            if !a.is_zero() {
-                assert_eq!(c.div_rem(&a), (b.clone(), Zero::zero()));
-            }
-            if !b.is_zero() {
-                assert_eq!(c.div_rem(&b), (a.clone(), Zero::zero()));
-            }
-        }
-
-        for div_rem_quadruples.each |elm| {
-            let (aVec, bVec, cVec, dVec) = *elm;
-            let a = BigUint::from_slice(aVec);
-            let b = BigUint::from_slice(bVec);
-            let c = BigUint::from_slice(cVec);
-            let d = BigUint::from_slice(dVec);
-
-            if !b.is_zero() { assert!(a.div_rem(&b) == (c, d)); }
-        }
-    }
-
-    #[test]
-    fn test_gcd() {
-        fn check(a: uint, b: uint, c: uint) {
-            let big_a = BigUint::from_uint(a);
-            let big_b = BigUint::from_uint(b);
-            let big_c = BigUint::from_uint(c);
-
-            assert_eq!(big_a.gcd(&big_b), big_c);
-        }
-
-        check(10, 2, 2);
-        check(10, 3, 1);
-        check(0, 3, 3);
-        check(3, 3, 3);
-        check(56, 42, 14);
-    }
-
-    #[test]
-    fn test_lcm() {
-        fn check(a: uint, b: uint, c: uint) {
-            let big_a = BigUint::from_uint(a);
-            let big_b = BigUint::from_uint(b);
-            let big_c = BigUint::from_uint(c);
-
-            assert_eq!(big_a.lcm(&big_b), big_c);
-        }
-
-        check(1, 0, 0);
-        check(0, 1, 0);
-        check(1, 1, 1);
-        check(8, 9, 72);
-        check(11, 5, 55);
-        check(99, 17, 1683);
-    }
-
-    #[test]
-    fn test_is_even() {
-        assert!(FromStr::from_str::<BigUint>("1").get().is_odd());
-        assert!(FromStr::from_str::<BigUint>("2").get().is_even());
-        assert!(FromStr::from_str::<BigUint>("1000").get().is_even());
-        assert!(FromStr::from_str::<BigUint>("1000000000000000000000").get().is_even());
-        assert!(FromStr::from_str::<BigUint>("1000000000000000000001").get().is_odd());
-        assert!((BigUint::from_uint(1) << 64).is_even());
-        assert!(((BigUint::from_uint(1) << 64) + BigUint::from_uint(1)).is_odd());
-    }
-
-    fn to_str_pairs() -> ~[ (BigUint, ~[(uint, ~str)]) ] {
-        let bits = BigDigit::bits;
-        ~[( Zero::zero(), ~[
-            (2, ~"0"), (3, ~"0")
-        ]), ( BigUint::from_slice([ 0xff ]), ~[
-            (2,  ~"11111111"),
-            (3,  ~"100110"),
-            (4,  ~"3333"),
-            (5,  ~"2010"),
-            (6,  ~"1103"),
-            (7,  ~"513"),
-            (8,  ~"377"),
-            (9,  ~"313"),
-            (10, ~"255"),
-            (11, ~"212"),
-            (12, ~"193"),
-            (13, ~"168"),
-            (14, ~"143"),
-            (15, ~"120"),
-            (16, ~"ff")
-        ]), ( BigUint::from_slice([ 0xfff ]), ~[
-            (2,  ~"111111111111"),
-            (4,  ~"333333"),
-            (16, ~"fff")
-        ]), ( BigUint::from_slice([ 1, 2 ]), ~[
-            (2,
-             ~"10" +
-             str::from_chars(vec::from_elem(bits - 1, '0')) + "1"),
-            (4,
-             ~"2" +
-             str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "1"),
-            (10, match bits {
-                32 => ~"8589934593", 16 => ~"131073", _ => fail!()
-            }),
-            (16,
-             ~"2" +
-             str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "1")
-        ]), ( BigUint::from_slice([ 1, 2, 3 ]), ~[
-            (2,
-             ~"11" +
-             str::from_chars(vec::from_elem(bits - 2, '0')) + "10" +
-             str::from_chars(vec::from_elem(bits - 1, '0')) + "1"),
-            (4,
-             ~"3" +
-             str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "2" +
-             str::from_chars(vec::from_elem(bits / 2 - 1, '0')) + "1"),
-            (10, match bits {
-                32 => ~"55340232229718589441",
-                16 => ~"12885032961",
-                _ => fail!()
-            }),
-            (16, ~"3" +
-             str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "2" +
-             str::from_chars(vec::from_elem(bits / 4 - 1, '0')) + "1")
-        ]) ]
-    }
-
-    #[test]
-    fn test_to_str_radix() {
-        for to_str_pairs().each |num_pair| {
-            let &(n, rs) = num_pair;
-            for rs.each |str_pair| {
-                let &(radix, str) = str_pair;
-                assert_eq!(n.to_str_radix(radix), str);
-            }
-        }
-    }
-
-    #[test]
-    fn test_from_str_radix() {
-        for to_str_pairs().each |num_pair| {
-            let &(n, rs) = num_pair;
-            for rs.each |str_pair| {
-                let &(radix, str) = str_pair;
-                assert_eq!(&n, &FromStrRadix::from_str_radix(str, radix).get());
-            }
-        }
-
-        assert_eq!(FromStrRadix::from_str_radix::<BigUint>(~"Z", 10), None);
-        assert_eq!(FromStrRadix::from_str_radix::<BigUint>(~"_", 2), None);
-        assert_eq!(FromStrRadix::from_str_radix::<BigUint>(~"-1", 10), None);
-    }
-
-    #[test]
-    fn test_factor() {
-        fn factor(n: uint) -> BigUint {
-            let mut f= One::one::<BigUint>();
-            for uint::range(2, n + 1) |i| {
-                // FIXME(#6102): Assignment operator for BigInt causes ICE
-                // f *= BigUint::from_uint(i);
-                f = f * BigUint::from_uint(i);
-            }
-            return f;
-        }
-
-        fn check(n: uint, s: &str) {
-            let n = factor(n);
-            let ans = match FromStrRadix::from_str_radix(s, 10) {
-                Some(x) => x, None => fail!()
-            };
-            assert_eq!(n, ans);
-        }
-
-        check(3, "6");
-        check(10, "3628800");
-        check(20, "2432902008176640000");
-        check(30, "265252859812191058636308480000000");
-    }
-}
-
-#[cfg(test)]
-mod bigint_tests {
-    use super::*;
-    use core::cmp::{Less, Equal, Greater};
-    use core::num::{IntConvertible, Zero, One, FromStrRadix};
-
-    #[test]
-    fn test_from_biguint() {
-        fn check(inp_s: Sign, inp_n: uint, ans_s: Sign, ans_n: uint) {
-            let inp = BigInt::from_biguint(inp_s, BigUint::from_uint(inp_n));
-            let ans = BigInt { sign: ans_s, data: BigUint::from_uint(ans_n)};
-            assert_eq!(inp, ans);
-        }
-        check(Plus, 1, Plus, 1);
-        check(Plus, 0, Zero, 0);
-        check(Minus, 1, Minus, 1);
-        check(Zero, 1, Zero, 0);
-    }
-
-    #[test]
-    fn test_cmp() {
-        let vs = [ &[2], &[1, 1], &[2, 1], &[1, 1, 1] ];
-        let mut nums = vec::reversed(vs)
-            .map(|s| BigInt::from_slice(Minus, *s));
-        nums.push(Zero::zero());
-        nums.push_all_move(vs.map(|s| BigInt::from_slice(Plus, *s)));
-
-        for nums.eachi |i, ni| {
-            for vec::slice(nums, i, nums.len()).eachi |j0, nj| {
-                let j = i + j0;
-                if i == j {
-                    assert_eq!(ni.cmp(nj), Equal);
-                    assert_eq!(nj.cmp(ni), Equal);
-                    assert_eq!(ni, nj);
-                    assert!(!(ni != nj));
-                    assert!(ni <= nj);
-                    assert!(ni >= nj);
-                    assert!(!(ni < nj));
-                    assert!(!(ni > nj));
-                } else {
-                    assert_eq!(ni.cmp(nj), Less);
-                    assert_eq!(nj.cmp(ni), Greater);
-
-                    assert!(!(ni == nj));
-                    assert!(ni != nj);
-
-                    assert!(ni <= nj);
-                    assert!(!(ni >= nj));
-                    assert!(ni < nj);
-                    assert!(!(ni > nj));
-
-                    assert!(!(nj <= ni));
-                    assert!(nj >= ni);
-                    assert!(!(nj < ni));
-                    assert!(nj > ni);
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn test_convert_int() {
-        fn check(b: BigInt, i: int) {
-            assert!(b == IntConvertible::from_int(i));
-            assert!(b.to_int() == i);
-        }
-
-        check(Zero::zero(), 0);
-        check(One::one(), 1);
-        check(BigInt::from_biguint(
-            Plus, BigUint::from_uint(int::max_value as uint)
-        ), int::max_value);
-
-        assert!(BigInt::from_biguint(
-            Plus, BigUint::from_uint(int::max_value as uint + 1)
-        ).to_int() == int::max_value);
-        assert!(BigInt::from_biguint(
-            Plus, BigUint::new(~[1, 2, 3])
-        ).to_int() == int::max_value);
-
-        check(BigInt::from_biguint(
-            Minus, BigUint::from_uint(-int::min_value as uint)
-        ), int::min_value);
-        assert!(BigInt::from_biguint(
-            Minus, BigUint::from_uint(-int::min_value as uint + 1)
-        ).to_int() == int::min_value);
-        assert!(BigInt::from_biguint(
-            Minus, BigUint::new(~[1, 2, 3])
-        ).to_int() == int::min_value);
-    }
-
-    #[test]
-    fn test_convert_uint() {
-        fn check(b: BigInt, u: uint) {
-            assert!(b == BigInt::from_uint(u));
-            assert!(b.to_uint() == u);
-        }
-
-        check(Zero::zero(), 0);
-        check(One::one(), 1);
-
-        check(
-            BigInt::from_biguint(Plus, BigUint::from_uint(uint::max_value)),
-            uint::max_value);
-        assert!(BigInt::from_biguint(
-            Plus, BigUint::new(~[1, 2, 3])
-        ).to_uint() == uint::max_value);
-
-        assert!(BigInt::from_biguint(
-            Minus, BigUint::from_uint(uint::max_value)
-        ).to_uint() == 0);
-        assert!(BigInt::from_biguint(
-            Minus, BigUint::new(~[1, 2, 3])
-        ).to_uint() == 0);
-    }
-
-    static sum_triples: &'static [(&'static [BigDigit],
-                                   &'static [BigDigit],
-                                   &'static [BigDigit])] = &[
-        (&[],          &[],       &[]),
-        (&[],          &[ 1],     &[ 1]),
-        (&[ 1],        &[ 1],     &[ 2]),
-        (&[ 1],        &[ 1,  1], &[ 2,  1]),
-        (&[ 1],        &[-1],     &[ 0,  1]),
-        (&[ 1],        &[-1, -1], &[ 0,  0, 1]),
-        (&[-1, -1],    &[-1, -1], &[-2, -1, 1]),
-        (&[ 1,  1, 1], &[-1, -1], &[ 0,  1, 2]),
-        (&[ 2,  2, 1], &[-1, -2], &[ 1,  1, 2])
-    ];
-
-    #[test]
-    fn test_add() {
-        for sum_triples.each |elm| {
-            let (aVec, bVec, cVec) = *elm;
-            let a = BigInt::from_slice(Plus, aVec);
-            let b = BigInt::from_slice(Plus, bVec);
-            let c = BigInt::from_slice(Plus, cVec);
-
-            assert!(a + b == c);
-            assert!(b + a == c);
-            assert!(c + (-a) == b);
-            assert!(c + (-b) == a);
-            assert!(a + (-c) == (-b));
-            assert!(b + (-c) == (-a));
-            assert!((-a) + (-b) == (-c))
-            assert!(a + (-a) == Zero::zero());
-        }
-    }
-
-    #[test]
-    fn test_sub() {
-        for sum_triples.each |elm| {
-            let (aVec, bVec, cVec) = *elm;
-            let a = BigInt::from_slice(Plus, aVec);
-            let b = BigInt::from_slice(Plus, bVec);
-            let c = BigInt::from_slice(Plus, cVec);
-
-            assert!(c - a == b);
-            assert!(c - b == a);
-            assert!((-b) - a == (-c))
-            assert!((-a) - b == (-c))
-            assert!(b - (-a) == c);
-            assert!(a - (-b) == c);
-            assert!((-c) - (-a) == (-b));
-            assert!(a - a == Zero::zero());
-        }
-    }
-
-    static mul_triples: &'static [(&'static [BigDigit],
-                                   &'static [BigDigit],
-                                   &'static [BigDigit])] = &[
-        (&[],               &[],               &[]),
-        (&[],               &[ 1],             &[]),
-        (&[ 2],             &[],               &[]),
-        (&[ 1],             &[ 1],             &[1]),
-        (&[ 2],             &[ 3],             &[ 6]),
-        (&[ 1],             &[ 1,  1,  1],     &[1, 1,  1]),
-        (&[ 1,  2,  3],     &[ 3],             &[ 3,  6,  9]),
-        (&[ 1,  1,  1],     &[-1],             &[-1, -1, -1]),
-        (&[ 1,  2,  3],     &[-1],             &[-1, -2, -2, 2]),
-        (&[ 1,  2,  3,  4], &[-1],             &[-1, -2, -2, -2, 3]),
-        (&[-1],             &[-1],             &[ 1, -2]),
-        (&[-1, -1],         &[-1],             &[ 1, -1, -2]),
-        (&[-1, -1, -1],     &[-1],             &[ 1, -1, -1, -2]),
-        (&[-1, -1, -1, -1], &[-1],             &[ 1, -1, -1, -1, -2]),
-        (&[-1/2 + 1],       &[ 2],             &[ 0,  1]),
-        (&[0, -1/2 + 1],    &[ 2],             &[ 0,  0,  1]),
-        (&[ 1,  2],         &[ 1,  2,  3],     &[1, 4,  7,  6]),
-        (&[-1, -1],         &[-1, -1, -1],     &[1, 0, -1, -2, -1]),
-        (&[-1, -1, -1],     &[-1, -1, -1, -1], &[1, 0,  0, -1, -2, -1, -1]),
-        (&[ 0,  0,  1],     &[ 1,  2,  3],     &[0, 0,  1,  2,  3]),
-        (&[ 0,  0,  1],     &[ 0,  0,  0,  1], &[0, 0,  0,  0,  0,  1])
-    ];
-
-    static div_rem_quadruples: &'static [(&'static [BigDigit],
-                                          &'static [BigDigit],
-                                          &'static [BigDigit],
-                                          &'static [BigDigit])]
-        = &[
-            (&[ 1],        &[ 2], &[],               &[1]),
-            (&[ 1,  1],    &[ 2], &[-1/2+1],         &[1]),
-            (&[ 1,  1, 1], &[ 2], &[-1/2+1, -1/2+1], &[1]),
-            (&[ 0,  1],    &[-1], &[1],              &[1]),
-            (&[-1, -1],    &[-2], &[2, 1],           &[3])
-        ];
-
-    #[test]
-    fn test_mul() {
-        for mul_triples.each |elm| {
-            let (aVec, bVec, cVec) = *elm;
-            let a = BigInt::from_slice(Plus, aVec);
-            let b = BigInt::from_slice(Plus, bVec);
-            let c = BigInt::from_slice(Plus, cVec);
-
-            assert!(a * b == c);
-            assert!(b * a == c);
-
-            assert!((-a) * b == -c);
-            assert!((-b) * a == -c);
-        }
-
-        for div_rem_quadruples.each |elm| {
-            let (aVec, bVec, cVec, dVec) = *elm;
-            let a = BigInt::from_slice(Plus, aVec);
-            let b = BigInt::from_slice(Plus, bVec);
-            let c = BigInt::from_slice(Plus, cVec);
-            let d = BigInt::from_slice(Plus, dVec);
-
-            assert!(a == b * c + d);
-            assert!(a == c * b + d);
-        }
-    }
-
-    #[test]
-    fn test_div_mod_floor() {
-        fn check_sub(a: &BigInt, b: &BigInt, ans_d: &BigInt, ans_m: &BigInt) {
-            let (d, m) = a.div_mod_floor(b);
-            if !m.is_zero() {
-                assert_eq!(m.sign, b.sign);
-            }
-            assert!(m.abs() <= b.abs());
-            assert!(*a == b * d + m);
-            assert!(d == *ans_d);
-            assert!(m == *ans_m);
-        }
-
-        fn check(a: &BigInt, b: &BigInt, d: &BigInt, m: &BigInt) {
-            if m.is_zero() {
-                check_sub(a, b, d, m);
-                check_sub(a, &b.neg(), &d.neg(), m);
-                check_sub(&a.neg(), b, &d.neg(), m);
-                check_sub(&a.neg(), &b.neg(), d, m);
-            } else {
-                check_sub(a, b, d, m);
-                check_sub(a, &b.neg(), &(d.neg() - One::one()), &(m - *b));
-                check_sub(&a.neg(), b, &(d.neg() - One::one()), &(b - *m));
-                check_sub(&a.neg(), &b.neg(), d, &m.neg());
-            }
-        }
-
-        for mul_triples.each |elm| {
-            let (aVec, bVec, cVec) = *elm;
-            let a = BigInt::from_slice(Plus, aVec);
-            let b = BigInt::from_slice(Plus, bVec);
-            let c = BigInt::from_slice(Plus, cVec);
-
-            if !a.is_zero() { check(&c, &a, &b, &Zero::zero()); }
-            if !b.is_zero() { check(&c, &b, &a, &Zero::zero()); }
-        }
-
-        for div_rem_quadruples.each |elm| {
-            let (aVec, bVec, cVec, dVec) = *elm;
-            let a = BigInt::from_slice(Plus, aVec);
-            let b = BigInt::from_slice(Plus, bVec);
-            let c = BigInt::from_slice(Plus, cVec);
-            let d = BigInt::from_slice(Plus, dVec);
-
-            if !b.is_zero() {
-                check(&a, &b, &c, &d);
-            }
-        }
-    }
-
-
-    #[test]
-    fn test_div_rem() {
-        fn check_sub(a: &BigInt, b: &BigInt, ans_q: &BigInt, ans_r: &BigInt) {
-            let (q, r) = a.div_rem(b);
-            if !r.is_zero() {
-                assert_eq!(r.sign, a.sign);
-            }
-            assert!(r.abs() <= b.abs());
-            assert!(*a == b * q + r);
-            assert!(q == *ans_q);
-            assert!(r == *ans_r);
-        }
-
-        fn check(a: &BigInt, b: &BigInt, q: &BigInt, r: &BigInt) {
-            check_sub(a, b, q, r);
-            check_sub(a, &b.neg(), &q.neg(), r);
-            check_sub(&a.neg(), b, &q.neg(), &r.neg());
-            check_sub(&a.neg(), &b.neg(), q, &r.neg());
-        }
-        for mul_triples.each |elm| {
-            let (aVec, bVec, cVec) = *elm;
-            let a = BigInt::from_slice(Plus, aVec);
-            let b = BigInt::from_slice(Plus, bVec);
-            let c = BigInt::from_slice(Plus, cVec);
-
-            if !a.is_zero() { check(&c, &a, &b, &Zero::zero()); }
-            if !b.is_zero() { check(&c, &b, &a, &Zero::zero()); }
-        }
-
-        for div_rem_quadruples.each |elm| {
-            let (aVec, bVec, cVec, dVec) = *elm;
-            let a = BigInt::from_slice(Plus, aVec);
-            let b = BigInt::from_slice(Plus, bVec);
-            let c = BigInt::from_slice(Plus, cVec);
-            let d = BigInt::from_slice(Plus, dVec);
-
-            if !b.is_zero() {
-                check(&a, &b, &c, &d);
-            }
-        }
-    }
-
-    #[test]
-    fn test_gcd() {
-        fn check(a: int, b: int, c: int) {
-            let big_a: BigInt = IntConvertible::from_int(a);
-            let big_b: BigInt = IntConvertible::from_int(b);
-            let big_c: BigInt = IntConvertible::from_int(c);
-
-            assert_eq!(big_a.gcd(&big_b), big_c);
-        }
-
-        check(10, 2, 2);
-        check(10, 3, 1);
-        check(0, 3, 3);
-        check(3, 3, 3);
-        check(56, 42, 14);
-        check(3, -3, 3);
-        check(-6, 3, 3);
-        check(-4, -2, 2);
-    }
-
-    #[test]
-    fn test_lcm() {
-        fn check(a: int, b: int, c: int) {
-            let big_a: BigInt = IntConvertible::from_int(a);
-            let big_b: BigInt = IntConvertible::from_int(b);
-            let big_c: BigInt = IntConvertible::from_int(c);
-
-            assert_eq!(big_a.lcm(&big_b), big_c);
-        }
-
-        check(1, 0, 0);
-        check(0, 1, 0);
-        check(1, 1, 1);
-        check(-1, 1, 1);
-        check(1, -1, 1);
-        check(-1, -1, 1);
-        check(8, 9, 72);
-        check(11, 5, 55);
-    }
-
-    #[test]
-    fn test_abs_sub() {
-        assert_eq!((-One::one::<BigInt>()).abs_sub(&One::one()), Zero::zero());
-        assert_eq!(One::one::<BigInt>().abs_sub(&One::one()), Zero::zero());
-        assert_eq!(One::one::<BigInt>().abs_sub(&Zero::zero()), One::one());
-        assert_eq!(One::one::<BigInt>().abs_sub(&-One::one::<BigInt>()),
-                   IntConvertible::from_int(2));
-    }
-
-    #[test]
-    fn test_to_str_radix() {
-        fn check(n: int, ans: &str) {
-            assert!(ans == IntConvertible::from_int::<BigInt>(n).to_str_radix(10));
-        }
-        check(10, "10");
-        check(1, "1");
-        check(0, "0");
-        check(-1, "-1");
-        check(-10, "-10");
-    }
-
-
-    #[test]
-    fn test_from_str_radix() {
-        fn check(s: &str, ans: Option<int>) {
-            let ans = ans.map(|&n| IntConvertible::from_int::<BigInt>(n));
-            assert_eq!(FromStrRadix::from_str_radix(s, 10), ans);
-        }
-        check("10", Some(10));
-        check("1", Some(1));
-        check("0", Some(0));
-        check("-1", Some(-1));
-        check("-10", Some(-10));
-        check("Z", None);
-        check("_", None);
-    }
-
-    #[test]
-    fn test_neg() {
-        assert!(-BigInt::new(Plus,  ~[1, 1, 1]) ==
-            BigInt::new(Minus, ~[1, 1, 1]));
-        assert!(-BigInt::new(Minus, ~[1, 1, 1]) ==
-            BigInt::new(Plus,  ~[1, 1, 1]));
-        assert_eq!(-Zero::zero::<BigInt>(), Zero::zero::<BigInt>());
-    }
-}
diff --git a/src/libstd/num/cmath.rs b/src/libstd/num/cmath.rs
new file mode 100644
index 00000000000..a80703fafa3
--- /dev/null
+++ b/src/libstd/num/cmath.rs
@@ -0,0 +1,270 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[doc(hidden)]; // FIXME #3538
+
+// function names are almost identical to C's libmath, a few have been
+// renamed, grep for "rename:"
+
+pub mod c_double_utils {
+    use libc::{c_double, c_int};
+
+    #[link_name = "m"]
+    #[abi = "cdecl"]
+    pub extern {
+        // Alpabetically sorted by link_name
+
+        unsafe fn acos(n: c_double) -> c_double;
+        unsafe fn asin(n: c_double) -> c_double;
+        unsafe fn atan(n: c_double) -> c_double;
+        unsafe fn atan2(a: c_double, b: c_double) -> c_double;
+        unsafe fn cbrt(n: c_double) -> c_double;
+        unsafe fn ceil(n: c_double) -> c_double;
+        unsafe fn copysign(x: c_double, y: c_double) -> c_double;
+        unsafe fn cos(n: c_double) -> c_double;
+        unsafe fn cosh(n: c_double) -> c_double;
+        unsafe fn erf(n: c_double) -> c_double;
+        unsafe fn erfc(n: c_double) -> c_double;
+        unsafe fn exp(n: c_double) -> c_double;
+        // rename: for consistency with underscore usage elsewhere
+        #[link_name="expm1"] unsafe fn exp_m1(n: c_double) -> c_double;
+        unsafe fn exp2(n: c_double) -> c_double;
+        #[link_name="fabs"] unsafe fn abs(n: c_double) -> c_double;
+        // rename: for clarity and consistency with add/sub/mul/div
+        #[link_name="fdim"]
+        unsafe fn abs_sub(a: c_double, b: c_double) -> c_double;
+        unsafe fn floor(n: c_double) -> c_double;
+        // rename: for clarity and consistency with add/sub/mul/div
+        #[link_name="fma"]
+        unsafe fn mul_add(a: c_double, b: c_double, c: c_double) -> c_double;
+        #[link_name="fmax"]
+        unsafe fn fmax(a: c_double, b: c_double) -> c_double;
+        #[link_name="fmin"]
+        unsafe fn fmin(a: c_double, b: c_double) -> c_double;
+        #[link_name="nextafter"]
+        unsafe fn next_after(x: c_double, y: c_double) -> c_double;
+        unsafe fn frexp(n: c_double, value: &mut c_int) -> c_double;
+        unsafe fn hypot(x: c_double, y: c_double) -> c_double;
+        unsafe fn ldexp(x: c_double, n: c_int) -> c_double;
+        #[cfg(unix)]
+        #[link_name="lgamma_r"]
+        unsafe fn lgamma(n: c_double, sign: &mut c_int) -> c_double;
+        #[cfg(windows)]
+        #[link_name="__lgamma_r"]
+        unsafe fn lgamma(n: c_double, sign: &mut c_int) -> c_double;
+        // renamed: log is a reserved keyword; ln seems more natural, too
+        #[link_name="log"] unsafe fn ln(n: c_double) -> c_double;
+        // renamed: "logb" /often/ is confused for log2 by beginners
+        #[link_name="logb"] unsafe fn log_radix(n: c_double) -> c_double;
+        // renamed: to be consitent with log as ln
+        #[link_name="log1p"] unsafe fn ln_1p(n: c_double) -> c_double;
+        unsafe fn log10(n: c_double) -> c_double;
+        unsafe fn log2(n: c_double) -> c_double;
+        #[link_name="ilogb"] unsafe fn ilog_radix(n: c_double) -> c_int;
+        unsafe fn modf(n: c_double, iptr: &mut c_double) -> c_double;
+        unsafe fn pow(n: c_double, e: c_double) -> c_double;
+    // FIXME (#1379): enable when rounding modes become available
+    //    unsafe fn rint(n: c_double) -> c_double;
+        unsafe fn round(n: c_double) -> c_double;
+        // rename: for consistency with logradix
+        #[link_name="scalbn"] unsafe fn ldexp_radix(n: c_double, i: c_int) ->
+            c_double;
+        unsafe fn sin(n: c_double) -> c_double;
+        unsafe fn sinh(n: c_double) -> c_double;
+        unsafe fn sqrt(n: c_double) -> c_double;
+        unsafe fn tan(n: c_double) -> c_double;
+        unsafe fn tanh(n: c_double) -> c_double;
+        unsafe fn tgamma(n: c_double) -> c_double;
+        unsafe fn trunc(n: c_double) -> c_double;
+
+        // These are commonly only available for doubles
+
+        unsafe fn j0(n: c_double) -> c_double;
+        unsafe fn j1(n: c_double) -> c_double;
+        unsafe fn jn(i: c_int, n: c_double) -> c_double;
+
+        unsafe fn y0(n: c_double) -> c_double;
+        unsafe fn y1(n: c_double) -> c_double;
+        unsafe fn yn(i: c_int, n: c_double) -> c_double;
+    }
+}
+
+pub mod c_float_utils {
+    use libc::{c_float, c_int};
+
+    #[link_name = "m"]
+    #[abi = "cdecl"]
+    pub extern {
+        // Alpabetically sorted by link_name
+
+        #[link_name="acosf"] unsafe fn acos(n: c_float) -> c_float;
+        #[link_name="asinf"] unsafe fn asin(n: c_float) -> c_float;
+        #[link_name="atanf"] unsafe fn atan(n: c_float) -> c_float;
+        #[link_name="atan2f"]
+        unsafe fn atan2(a: c_float, b: c_float) -> c_float;
+        #[link_name="cbrtf"] unsafe fn cbrt(n: c_float) -> c_float;
+        #[link_name="ceilf"] unsafe fn ceil(n: c_float) -> c_float;
+        #[link_name="copysignf"] unsafe fn copysign(x: c_float,
+                                                  y: c_float) -> c_float;
+        #[link_name="cosf"] unsafe fn cos(n: c_float) -> c_float;
+        #[link_name="coshf"] unsafe fn cosh(n: c_float) -> c_float;
+        #[link_name="erff"] unsafe fn erf(n: c_float) -> c_float;
+        #[link_name="erfcf"] unsafe fn erfc(n: c_float) -> c_float;
+        #[link_name="expf"] unsafe fn exp(n: c_float) -> c_float;
+        #[link_name="expm1f"]unsafe fn exp_m1(n: c_float) -> c_float;
+        #[link_name="exp2f"] unsafe fn exp2(n: c_float) -> c_float;
+        #[link_name="fabsf"] unsafe fn abs(n: c_float) -> c_float;
+        #[link_name="fdimf"]
+        unsafe fn abs_sub(a: c_float, b: c_float) -> c_float;
+        #[link_name="floorf"] unsafe fn floor(n: c_float) -> c_float;
+        #[link_name="frexpf"] unsafe fn frexp(n: c_float,
+                                            value: &mut c_int) -> c_float;
+        #[link_name="fmaf"]
+        unsafe fn mul_add(a: c_float, b: c_float, c: c_float) -> c_float;
+        #[link_name="fmaxf"]
+        unsafe fn fmax(a: c_float, b: c_float) -> c_float;
+        #[link_name="fminf"]
+        unsafe fn fmin(a: c_float, b: c_float) -> c_float;
+        #[link_name="nextafterf"]
+        unsafe fn next_after(x: c_float, y: c_float) -> c_float;
+        #[link_name="hypotf"]
+        unsafe fn hypot(x: c_float, y: c_float) -> c_float;
+        #[link_name="ldexpf"]
+        unsafe fn ldexp(x: c_float, n: c_int) -> c_float;
+
+        #[cfg(unix)]
+        #[link_name="lgammaf_r"] unsafe fn lgamma(n: c_float,
+                                                sign: &mut c_int) -> c_float;
+
+        #[cfg(windows)]
+        #[link_name="__lgammaf_r"]
+        unsafe fn lgamma(n: c_float, sign: &mut c_int) -> c_float;
+
+        #[link_name="logf"] unsafe fn ln(n: c_float) -> c_float;
+        #[link_name="logbf"] unsafe fn log_radix(n: c_float) -> c_float;
+        #[link_name="log1pf"] unsafe fn ln_1p(n: c_float) -> c_float;
+        #[link_name="log2f"] unsafe fn log2(n: c_float) -> c_float;
+        #[link_name="log10f"] unsafe fn log10(n: c_float) -> c_float;
+        #[link_name="ilogbf"] unsafe fn ilog_radix(n: c_float) -> c_int;
+        #[link_name="modff"] unsafe fn modf(n: c_float,
+                                          iptr: &mut c_float) -> c_float;
+        #[link_name="powf"] unsafe fn pow(n: c_float, e: c_float) -> c_float;
+    // FIXME (#1379): enable when rounding modes become available
+    //    #[link_name="rintf"] unsafe fn rint(n: c_float) -> c_float;
+        #[link_name="roundf"] unsafe fn round(n: c_float) -> c_float;
+        #[link_name="scalbnf"] unsafe fn ldexp_radix(n: c_float, i: c_int)
+            -> c_float;
+        #[link_name="sinf"] unsafe fn sin(n: c_float) -> c_float;
+        #[link_name="sinhf"] unsafe fn sinh(n: c_float) -> c_float;
+        #[link_name="sqrtf"] unsafe fn sqrt(n: c_float) -> c_float;
+        #[link_name="tanf"] unsafe fn tan(n: c_float) -> c_float;
+        #[link_name="tanhf"] unsafe fn tanh(n: c_float) -> c_float;
+        #[link_name="tgammaf"] unsafe fn tgamma(n: c_float) -> c_float;
+        #[link_name="truncf"] unsafe fn trunc(n: c_float) -> c_float;
+    }
+}
+
+// PORT check these by running src/etc/machconsts.c for your architecture
+
+// FIXME obtain machine float/math constants automatically (Issue #1986)
+
+pub mod c_float_targ_consts {
+    pub static radix: uint = 2u;
+    pub static mantissa_digits: uint = 24u;
+    pub static digits: uint = 6u;
+    pub static min_exp: uint = -125u;
+    pub static max_exp: uint = 128u;
+    pub static min_10_exp: int = -37;
+    pub static max_10_exp: int = 38;
+    // FIXME (#1433): this is wrong, replace with hexadecimal (%a) staticants
+    // below.
+    pub static min_value: f32 = 1.175494e-38_f32;
+    pub static max_value: f32 = 3.402823e+38_f32;
+    pub static epsilon: f32 = 0.000000_f32;
+}
+
+pub mod c_double_targ_consts {
+    pub static radix: uint = 2u;
+    pub static mantissa_digits: uint = 53u;
+    pub static digits: uint = 15u;
+    pub static min_exp: uint = -1021u;
+    pub static max_exp: uint = 1024u;
+    pub static min_10_exp: int = -307;
+    pub static max_10_exp: int = 308;
+    // FIXME (#1433): this is wrong, replace with hexadecimal (%a) staticants
+    // below.
+    pub static min_value: f64 = 2.225074e-308_f64;
+    pub static max_value: f64 = 1.797693e+308_f64;
+    pub static epsilon: f64 = 2.220446e-16_f64;
+}
+
+/*
+
+FIXME use these once they can be parsed (see Issue #1433)
+
+pub mod c_float_math_consts {
+    pub static pi: c_float = 0x1.921fb6p+1_f32;
+    pub static div_1_pi: c_float = 0x1.45f306p-2_f32;
+    pub static div_2_pi: c_float = 0x1.45f306p-1_f32;
+    pub static div_pi_2: c_float = 0x1.921fb6p+0_f32;
+    pub static div_pi_4: c_float = 0x1.921fb6p-1_f32;
+    pub static div_2_sqrtpi: c_float = 0x1.20dd76p+0_f32;
+    pub static e: c_float = 0x1.5bf0a8p+1_f32;
+    pub static log2_e: c_float = 0x1.715476p+0_f32;
+    pub static log10_e: c_float = 0x1.bcb7b2p-2_f32;
+    pub static ln_2: c_float = 0x1.62e43p-1_f32;
+    pub static ln_10: c_float = 0x1.26bb1cp+1_f32;
+    pub static sqrt2: c_float = 0x1.6a09e6p+0_f32;
+    pub static div_1_sqrt2: c_float = 0x1.6a09e6p-1_f32;
+}
+
+pub mod c_double_math_consts {
+    pub static pi: c_double = 0x1.921fb54442d18p+1_f64;
+    pub static div_1_pi: c_double = 0x1.45f306dc9c883p-2_f64;
+    pub static div_2_pi: c_double = 0x1.45f306dc9c883p-1_f64;
+    pub static div_pi_2: c_double = 0x1.921fb54442d18p+0_f64;
+    pub static div_pi_4: c_double = 0x1.921fb54442d18p-1_f64;
+    pub static div_2_sqrtpi: c_double = 0x1.20dd750429b6dp+0_f64;
+    pub static e: c_double = 0x1.5bf0a8b145769p+1_f64;
+    pub static log2_e: c_double = 0x1.71547652b82fep+0_f64;
+    pub static log10_e: c_double = 0x1.bcb7b1526e50ep-2_f64;
+    pub static ln_2: c_double = 0x1.62e42fefa39efp-1_f64;
+    pub static ln_10: c_double = 0x1.26bb1bbb55516p+1_f64;
+    pub static sqrt2: c_double = 0x1.6a09e667f3bcdp+0_f64;
+    pub static div_1_sqrt2: c_double = 0x1.6a09e667f3bcdp-1_f64;
+}
+
+pub mod c_float_targ_consts {
+    pub static radix: uint = 2u;
+    pub static mantissa_digits: uint = 24u;
+    pub static digits: uint = 6u;
+    pub static min_exp: int = -125;
+    pub static max_exp: int = 128;
+    pub static min_10_exp: int = -37;
+    pub static max_10_exp: int = 38;
+    pub static min_value: c_float = 0x1p-126_f32;
+    pub static max_value: c_float = 0x1.fffffep+127_f32;
+    pub static epsilon: c_float = 0x1p-23_f32;
+}
+
+pub mod c_double_targ_consts {
+    pub static radix: uint = 2u;
+    pub static mantissa_digits: uint = 53u;
+    pub static digits: uint = 15u;
+    pub static min_exp: int = -1021;
+    pub static max_exp: int = 1024;
+    pub static min_10_exp: int = -307;
+    pub static max_10_exp: int = 308;
+    pub static min_value: c_double = 0x1p-1022_f64;
+    pub static max_value: c_double = 0x1.fffffffffffffp+1023_f64;
+    pub static epsilon: c_double = 0x1p-52_f64;
+}
+
+*/
diff --git a/src/libstd/num/complex.rs b/src/libstd/num/complex.rs
deleted file mode 100644
index 41d2b4a101c..00000000000
--- a/src/libstd/num/complex.rs
+++ /dev/null
@@ -1,309 +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.
-
-
-//! Complex numbers.
-
-use core::num::{Zero,One,ToStrRadix};
-
-// FIXME #1284: handle complex NaN & infinity etc. This
-// probably doesn't map to C's _Complex correctly.
-
-// FIXME #5734:: Need generic sin/cos for .to/from_polar().
-// FIXME #5735: Need generic sqrt to implement .norm().
-
-
-/// A complex number in Cartesian form.
-#[deriving(Eq,Clone)]
-pub struct Cmplx<T> {
-    re: T,
-    im: T
-}
-
-pub type Complex = Cmplx<float>;
-pub type Complex32 = Cmplx<f32>;
-pub type Complex64 = Cmplx<f64>;
-
-impl<T: Copy + Num> Cmplx<T> {
-    /// Create a new Cmplx
-    #[inline]
-    pub fn new(re: T, im: T) -> Cmplx<T> {
-        Cmplx { re: re, im: im }
-    }
-
-    /**
-    Returns the square of the norm (since `T` doesn't necessarily
-    have a sqrt function), i.e. `re^2 + im^2`.
-    */
-    #[inline]
-    pub fn norm_sqr(&self) -> T {
-        self.re * self.re + self.im * self.im
-    }
-
-
-    /// Returns the complex conjugate. i.e. `re - i im`
-    #[inline]
-    pub fn conj(&self) -> Cmplx<T> {
-        Cmplx::new(self.re, -self.im)
-    }
-
-
-    /// Multiplies `self` by the scalar `t`.
-    #[inline]
-    pub fn scale(&self, t: T) -> Cmplx<T> {
-        Cmplx::new(self.re * t, self.im * t)
-    }
-
-    /// Divides `self` by the scalar `t`.
-    #[inline]
-    pub fn unscale(&self, t: T) -> Cmplx<T> {
-        Cmplx::new(self.re / t, self.im / t)
-    }
-
-    /// Returns `1/self`
-    #[inline]
-    pub fn inv(&self) -> Cmplx<T> {
-        let norm_sqr = self.norm_sqr();
-        Cmplx::new(self.re / norm_sqr,
-                    -self.im / norm_sqr)
-    }
-}
-
-/* arithmetic */
-// (a + i b) + (c + i d) == (a + c) + i (b + d)
-impl<T: Copy + Num> Add<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
-    #[inline]
-    fn add(&self, other: &Cmplx<T>) -> Cmplx<T> {
-        Cmplx::new(self.re + other.re, self.im + other.im)
-    }
-}
-// (a + i b) - (c + i d) == (a - c) + i (b - d)
-impl<T: Copy + Num> Sub<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
-    #[inline]
-    fn sub(&self, other: &Cmplx<T>) -> Cmplx<T> {
-        Cmplx::new(self.re - other.re, self.im - other.im)
-    }
-}
-// (a + i b) * (c + i d) == (a*c - b*d) + i (a*d + b*c)
-impl<T: Copy + Num> Mul<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
-    #[inline]
-    fn mul(&self, other: &Cmplx<T>) -> Cmplx<T> {
-        Cmplx::new(self.re*other.re - self.im*other.im,
-                     self.re*other.im + self.im*other.re)
-    }
-}
-
-// (a + i b) / (c + i d) == [(a + i b) * (c - i d)] / (c*c + d*d)
-//   == [(a*c + b*d) / (c*c + d*d)] + i [(b*c - a*d) / (c*c + d*d)]
-impl<T: Copy + Num> Div<Cmplx<T>, Cmplx<T>> for Cmplx<T> {
-    #[inline]
-    fn div(&self, other: &Cmplx<T>) -> Cmplx<T> {
-        let norm_sqr = other.norm_sqr();
-        Cmplx::new((self.re*other.re + self.im*other.im) / norm_sqr,
-                     (self.im*other.re - self.re*other.im) / norm_sqr)
-    }
-}
-
-impl<T: Copy + Num> Neg<Cmplx<T>> for Cmplx<T> {
-    #[inline]
-    fn neg(&self) -> Cmplx<T> {
-        Cmplx::new(-self.re, -self.im)
-    }
-}
-
-/* constants */
-impl<T: Copy + Num> Zero for Cmplx<T> {
-    #[inline]
-    fn zero() -> Cmplx<T> {
-        Cmplx::new(Zero::zero(), Zero::zero())
-    }
-
-    #[inline]
-    fn is_zero(&self) -> bool {
-        *self == Zero::zero()
-    }
-}
-
-impl<T: Copy + Num> One for Cmplx<T> {
-    #[inline]
-    fn one() -> Cmplx<T> {
-        Cmplx::new(One::one(), Zero::zero())
-    }
-}
-
-/* string conversions */
-impl<T: ToStr + Num + Ord> ToStr for Cmplx<T> {
-    fn to_str(&self) -> ~str {
-        if self.im < Zero::zero() {
-            fmt!("%s-%si", self.re.to_str(), (-self.im).to_str())
-        } else {
-            fmt!("%s+%si", self.re.to_str(), self.im.to_str())
-        }
-    }
-}
-
-impl<T: ToStrRadix + Num + Ord> ToStrRadix for Cmplx<T> {
-    fn to_str_radix(&self, radix: uint) -> ~str {
-        if self.im < Zero::zero() {
-            fmt!("%s-%si", self.re.to_str_radix(radix), (-self.im).to_str_radix(radix))
-        } else {
-            fmt!("%s+%si", self.re.to_str_radix(radix), self.im.to_str_radix(radix))
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use super::*;
-    use core::num::{Zero,One};
-
-    pub static _0_0i : Complex = Cmplx { re: 0f, im: 0f };
-    pub static _1_0i : Complex = Cmplx { re: 1f, im: 0f };
-    pub static _1_1i : Complex = Cmplx { re: 1f, im: 1f };
-    pub static _0_1i : Complex = Cmplx { re: 0f, im: 1f };
-    pub static _neg1_1i : Complex = Cmplx { re: -1f, im: 1f };
-    pub static _05_05i : Complex = Cmplx { re: 0.5f, im: 0.5f };
-    pub static all_consts : [Complex, .. 5] = [_0_0i, _1_0i, _1_1i, _neg1_1i, _05_05i];
-
-    #[test]
-    fn test_consts() {
-        // check our constants are what Cmplx::new creates
-        fn test(c : Complex, r : float, i: float) {
-            assert_eq!(c, Cmplx::new(r,i));
-        }
-        test(_0_0i, 0f, 0f);
-        test(_1_0i, 1f, 0f);
-        test(_1_1i, 1f, 1f);
-        test(_neg1_1i, -1f, 1f);
-        test(_05_05i, 0.5f, 0.5f);
-
-        assert_eq!(_0_0i, Zero::zero());
-        assert_eq!(_1_0i, One::one());
-    }
-
-    #[test]
-    fn test_norm_sqr() {
-        fn test(c: Complex, ns: float) {
-            assert_eq!(c.norm_sqr(), ns);
-        }
-        test(_0_0i, 0f);
-        test(_1_0i, 1f);
-        test(_1_1i, 2f);
-        test(_neg1_1i, 2f);
-        test(_05_05i, 0.5f);
-    }
-
-    #[test]
-    fn test_scale_unscale() {
-        assert_eq!(_05_05i.scale(2f), _1_1i);
-        assert_eq!(_1_1i.unscale(2f), _05_05i);
-        for all_consts.each |&c| {
-            assert_eq!(c.scale(2f).unscale(2f), c);
-        }
-    }
-
-    #[test]
-    fn test_conj() {
-        for all_consts.each |&c| {
-            assert_eq!(c.conj(), Cmplx::new(c.re, -c.im));
-            assert_eq!(c.conj().conj(), c);
-        }
-    }
-
-    #[test]
-    fn test_inv() {
-        assert_eq!(_1_1i.inv(), _05_05i.conj());
-        assert_eq!(_1_0i.inv(), _1_0i.inv());
-    }
-
-    #[test]
-    #[should_fail]
-    #[ignore]
-    fn test_inv_zero() {
-        // FIXME #5736: should this really fail, or just NaN?
-        _0_0i.inv();
-    }
-
-
-    mod arith {
-        use super::*;
-        use core::num::Zero;
-
-        #[test]
-        fn test_add() {
-            assert_eq!(_05_05i + _05_05i, _1_1i);
-            assert_eq!(_0_1i + _1_0i, _1_1i);
-            assert_eq!(_1_0i + _neg1_1i, _0_1i);
-
-            for all_consts.each |&c| {
-                assert_eq!(_0_0i + c, c);
-                assert_eq!(c + _0_0i, c);
-            }
-        }
-
-        #[test]
-        fn test_sub() {
-            assert_eq!(_05_05i - _05_05i, _0_0i);
-            assert_eq!(_0_1i - _1_0i, _neg1_1i);
-            assert_eq!(_0_1i - _neg1_1i, _1_0i);
-
-            for all_consts.each |&c| {
-                assert_eq!(c - _0_0i, c);
-                assert_eq!(c - c, _0_0i);
-            }
-        }
-
-        #[test]
-        fn test_mul() {
-            assert_eq!(_05_05i * _05_05i, _0_1i.unscale(2f));
-            assert_eq!(_1_1i * _0_1i, _neg1_1i);
-
-            // i^2 & i^4
-            assert_eq!(_0_1i * _0_1i, -_1_0i);
-            assert_eq!(_0_1i * _0_1i * _0_1i * _0_1i, _1_0i);
-
-            for all_consts.each |&c| {
-                assert_eq!(c * _1_0i, c);
-                assert_eq!(_1_0i * c, c);
-            }
-        }
-        #[test]
-        fn test_div() {
-            assert_eq!(_neg1_1i / _0_1i, _1_1i);
-            for all_consts.each |&c| {
-                if c != Zero::zero() {
-                    assert_eq!(c / c, _1_0i);
-                }
-            }
-        }
-        #[test]
-        fn test_neg() {
-            assert_eq!(-_1_0i + _0_1i, _neg1_1i);
-            assert_eq!((-_0_1i) * _0_1i, _1_0i);
-            for all_consts.each |&c| {
-                assert_eq!(-(-c), c);
-            }
-        }
-    }
-
-    #[test]
-    fn test_to_str() {
-        fn test(c : Complex, s: ~str) {
-            assert_eq!(c.to_str(), s);
-        }
-        test(_0_0i, ~"0+0i");
-        test(_1_0i, ~"1+0i");
-        test(_0_1i, ~"0+1i");
-        test(_1_1i, ~"1+1i");
-        test(_neg1_1i, ~"-1+1i");
-        test(-_neg1_1i, ~"1-1i");
-        test(_05_05i, ~"0.5+0.5i");
-    }
-}
diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs
new file mode 100644
index 00000000000..d5dc0dd4730
--- /dev/null
+++ b/src/libstd/num/f32.rs
@@ -0,0 +1,1250 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations and constants for `f32`
+
+use libc::c_int;
+use num::{Zero, One, strconv};
+use num::{FPCategory, FPNaN, FPInfinite , FPZero, FPSubnormal, FPNormal};
+use prelude::*;
+
+pub use cmath::c_float_targ_consts::*;
+
+// An inner module is required to get the #[inline(always)] attribute on the
+// functions.
+pub use self::delegated::*;
+
+macro_rules! delegate(
+    (
+        $(
+            fn $name:ident(
+                $(
+                    $arg:ident : $arg_ty:ty
+                ),*
+            ) -> $rv:ty = $bound_name:path
+        ),*
+    ) => (
+        mod delegated {
+            use cmath::c_float_utils;
+            use libc::{c_float, c_int};
+            use unstable::intrinsics;
+
+            $(
+                #[inline(always)]
+                pub fn $name($( $arg : $arg_ty ),*) -> $rv {
+                    unsafe {
+                        $bound_name($( $arg ),*)
+                    }
+                }
+            )*
+        }
+    )
+)
+
+delegate!(
+    // intrinsics
+    fn abs(n: f32) -> f32 = intrinsics::fabsf32,
+    fn cos(n: f32) -> f32 = intrinsics::cosf32,
+    fn exp(n: f32) -> f32 = intrinsics::expf32,
+    fn exp2(n: f32) -> f32 = intrinsics::exp2f32,
+    fn floor(x: f32) -> f32 = intrinsics::floorf32,
+    fn ln(n: f32) -> f32 = intrinsics::logf32,
+    fn log10(n: f32) -> f32 = intrinsics::log10f32,
+    fn log2(n: f32) -> f32 = intrinsics::log2f32,
+    fn mul_add(a: f32, b: f32, c: f32) -> f32 = intrinsics::fmaf32,
+    fn pow(n: f32, e: f32) -> f32 = intrinsics::powf32,
+    fn powi(n: f32, e: c_int) -> f32 = intrinsics::powif32,
+    fn sin(n: f32) -> f32 = intrinsics::sinf32,
+    fn sqrt(n: f32) -> f32 = intrinsics::sqrtf32,
+
+    // LLVM 3.3 required to use intrinsics for these four
+    fn ceil(n: c_float) -> c_float = c_float_utils::ceil,
+    fn trunc(n: c_float) -> c_float = c_float_utils::trunc,
+    /*
+    fn ceil(n: f32) -> f32 = intrinsics::ceilf32,
+    fn trunc(n: f32) -> f32 = intrinsics::truncf32,
+    fn rint(n: f32) -> f32 = intrinsics::rintf32,
+    fn nearbyint(n: f32) -> f32 = intrinsics::nearbyintf32,
+    */
+
+    // cmath
+    fn acos(n: c_float) -> c_float = c_float_utils::acos,
+    fn asin(n: c_float) -> c_float = c_float_utils::asin,
+    fn atan(n: c_float) -> c_float = c_float_utils::atan,
+    fn atan2(a: c_float, b: c_float) -> c_float = c_float_utils::atan2,
+    fn cbrt(n: c_float) -> c_float = c_float_utils::cbrt,
+    fn copysign(x: c_float, y: c_float) -> c_float = c_float_utils::copysign,
+    fn cosh(n: c_float) -> c_float = c_float_utils::cosh,
+    fn erf(n: c_float) -> c_float = c_float_utils::erf,
+    fn erfc(n: c_float) -> c_float = c_float_utils::erfc,
+    fn exp_m1(n: c_float) -> c_float = c_float_utils::exp_m1,
+    fn abs_sub(a: c_float, b: c_float) -> c_float = c_float_utils::abs_sub,
+    fn fmax(a: c_float, b: c_float) -> c_float = c_float_utils::fmax,
+    fn fmin(a: c_float, b: c_float) -> c_float = c_float_utils::fmin,
+    fn next_after(x: c_float, y: c_float) -> c_float = c_float_utils::next_after,
+    fn frexp(n: c_float, value: &mut c_int) -> c_float = c_float_utils::frexp,
+    fn hypot(x: c_float, y: c_float) -> c_float = c_float_utils::hypot,
+    fn ldexp(x: c_float, n: c_int) -> c_float = c_float_utils::ldexp,
+    fn lgamma(n: c_float, sign: &mut c_int) -> c_float = c_float_utils::lgamma,
+    fn log_radix(n: c_float) -> c_float = c_float_utils::log_radix,
+    fn ln_1p(n: c_float) -> c_float = c_float_utils::ln_1p,
+    fn ilog_radix(n: c_float) -> c_int = c_float_utils::ilog_radix,
+    fn modf(n: c_float, iptr: &mut c_float) -> c_float = c_float_utils::modf,
+    fn round(n: c_float) -> c_float = c_float_utils::round,
+    fn ldexp_radix(n: c_float, i: c_int) -> c_float = c_float_utils::ldexp_radix,
+    fn sinh(n: c_float) -> c_float = c_float_utils::sinh,
+    fn tan(n: c_float) -> c_float = c_float_utils::tan,
+    fn tanh(n: c_float) -> c_float = c_float_utils::tanh,
+    fn tgamma(n: c_float) -> c_float = c_float_utils::tgamma
+)
+
+// These are not defined inside consts:: for consistency with
+// the integer types
+
+pub static NaN: f32 = 0.0_f32/0.0_f32;
+
+pub static infinity: f32 = 1.0_f32/0.0_f32;
+
+pub static neg_infinity: f32 = -1.0_f32/0.0_f32;
+
+#[inline(always)]
+pub fn add(x: f32, y: f32) -> f32 { return x + y; }
+
+#[inline(always)]
+pub fn sub(x: f32, y: f32) -> f32 { return x - y; }
+
+#[inline(always)]
+pub fn mul(x: f32, y: f32) -> f32 { return x * y; }
+
+#[inline(always)]
+pub fn div(x: f32, y: f32) -> f32 { return x / y; }
+
+#[inline(always)]
+pub fn rem(x: f32, y: f32) -> f32 { return x % y; }
+
+#[inline(always)]
+pub fn lt(x: f32, y: f32) -> bool { return x < y; }
+
+#[inline(always)]
+pub fn le(x: f32, y: f32) -> bool { return x <= y; }
+
+#[inline(always)]
+pub fn eq(x: f32, y: f32) -> bool { return x == y; }
+
+#[inline(always)]
+pub fn ne(x: f32, y: f32) -> bool { return x != y; }
+
+#[inline(always)]
+pub fn ge(x: f32, y: f32) -> bool { return x >= y; }
+
+#[inline(always)]
+pub fn gt(x: f32, y: f32) -> bool { return x > y; }
+
+
+// FIXME (#1999): replace the predicates below with llvm intrinsics or
+// calls to the libmath macros in the rust runtime for performance.
+
+// FIXME (#1999): add is_normal, is_subnormal, and fpclassify.
+
+/* Module: consts */
+pub mod consts {
+    // FIXME (requires Issue #1433 to fix): replace with mathematical
+    // staticants from cmath.
+    /// Archimedes' staticant
+    pub static pi: f32 = 3.14159265358979323846264338327950288_f32;
+
+    /// pi/2.0
+    pub static frac_pi_2: f32 = 1.57079632679489661923132169163975144_f32;
+
+    /// pi/4.0
+    pub static frac_pi_4: f32 = 0.785398163397448309615660845819875721_f32;
+
+    /// 1.0/pi
+    pub static frac_1_pi: f32 = 0.318309886183790671537767526745028724_f32;
+
+    /// 2.0/pi
+    pub static frac_2_pi: f32 = 0.636619772367581343075535053490057448_f32;
+
+    /// 2.0/sqrt(pi)
+    pub static frac_2_sqrtpi: f32 = 1.12837916709551257389615890312154517_f32;
+
+    /// sqrt(2.0)
+    pub static sqrt2: f32 = 1.41421356237309504880168872420969808_f32;
+
+    /// 1.0/sqrt(2.0)
+    pub static frac_1_sqrt2: f32 = 0.707106781186547524400844362104849039_f32;
+
+    /// Euler's number
+    pub static e: f32 = 2.71828182845904523536028747135266250_f32;
+
+    /// log2(e)
+    pub static log2_e: f32 = 1.44269504088896340735992468100189214_f32;
+
+    /// log10(e)
+    pub static log10_e: f32 = 0.434294481903251827651128918916605082_f32;
+
+    /// ln(2.0)
+    pub static ln_2: f32 = 0.693147180559945309417232121458176568_f32;
+
+    /// ln(10.0)
+    pub static ln_10: f32 = 2.30258509299404568401799145468436421_f32;
+}
+
+impl Num for f32 {}
+
+#[cfg(not(test))]
+impl Eq for f32 {
+    #[inline(always)]
+    fn eq(&self, other: &f32) -> bool { (*self) == (*other) }
+    #[inline(always)]
+    fn ne(&self, other: &f32) -> bool { (*self) != (*other) }
+}
+
+#[cfg(not(test))]
+impl ApproxEq<f32> for f32 {
+    #[inline(always)]
+    fn approx_epsilon() -> f32 { 1.0e-6 }
+
+    #[inline(always)]
+    fn approx_eq(&self, other: &f32) -> bool {
+        self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<f32, f32>())
+    }
+
+    #[inline(always)]
+    fn approx_eq_eps(&self, other: &f32, approx_epsilon: &f32) -> bool {
+        (*self - *other).abs() < *approx_epsilon
+    }
+}
+
+#[cfg(not(test))]
+impl Ord for f32 {
+    #[inline(always)]
+    fn lt(&self, other: &f32) -> bool { (*self) < (*other) }
+    #[inline(always)]
+    fn le(&self, other: &f32) -> bool { (*self) <= (*other) }
+    #[inline(always)]
+    fn ge(&self, other: &f32) -> bool { (*self) >= (*other) }
+    #[inline(always)]
+    fn gt(&self, other: &f32) -> bool { (*self) > (*other) }
+}
+
+impl Orderable for f32 {
+    /// Returns `NaN` if either of the numbers are `NaN`.
+    #[inline(always)]
+    fn min(&self, other: &f32) -> f32 {
+        if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmin(*self, *other) }
+    }
+
+    /// Returns `NaN` if either of the numbers are `NaN`.
+    #[inline(always)]
+    fn max(&self, other: &f32) -> f32 {
+        if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmax(*self, *other) }
+    }
+
+    /// Returns the number constrained within the range `mn <= self <= mx`.
+    /// If any of the numbers are `NaN` then `NaN` is returned.
+    #[inline(always)]
+    fn clamp(&self, mn: &f32, mx: &f32) -> f32 {
+        cond!(
+            (self.is_NaN())   { *self }
+            (!(*self <= *mx)) { *mx   }
+            (!(*self >= *mn)) { *mn   }
+            _                 { *self }
+        )
+    }
+}
+
+impl Zero for f32 {
+    #[inline(always)]
+    fn zero() -> f32 { 0.0 }
+
+    /// Returns true if the number is equal to either `0.0` or `-0.0`
+    #[inline(always)]
+    fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 }
+}
+
+impl One for f32 {
+    #[inline(always)]
+    fn one() -> f32 { 1.0 }
+}
+
+#[cfg(not(test))]
+impl Add<f32,f32> for f32 {
+    #[inline(always)]
+    fn add(&self, other: &f32) -> f32 { *self + *other }
+}
+
+#[cfg(not(test))]
+impl Sub<f32,f32> for f32 {
+    #[inline(always)]
+    fn sub(&self, other: &f32) -> f32 { *self - *other }
+}
+
+#[cfg(not(test))]
+impl Mul<f32,f32> for f32 {
+    #[inline(always)]
+    fn mul(&self, other: &f32) -> f32 { *self * *other }
+}
+
+#[cfg(not(test))]
+impl Div<f32,f32> for f32 {
+    #[inline(always)]
+    fn div(&self, other: &f32) -> f32 { *self / *other }
+}
+
+#[cfg(not(test))]
+impl Rem<f32,f32> for f32 {
+    #[inline(always)]
+    fn rem(&self, other: &f32) -> f32 { *self % *other }
+}
+
+#[cfg(not(test))]
+impl Neg<f32> for f32 {
+    #[inline(always)]
+    fn neg(&self) -> f32 { -*self }
+}
+
+impl Signed for f32 {
+    /// Computes the absolute value. Returns `NaN` if the number is `NaN`.
+    #[inline(always)]
+    fn abs(&self) -> f32 { abs(*self) }
+
+    ///
+    /// The positive difference of two numbers. Returns `0.0` if the number is less than or
+    /// equal to `other`, otherwise the difference between`self` and `other` is returned.
+    ///
+    #[inline(always)]
+    fn abs_sub(&self, other: &f32) -> f32 { abs_sub(*self, *other) }
+
+    ///
+    /// # Returns
+    ///
+    /// - `1.0` if the number is positive, `+0.0` or `infinity`
+    /// - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
+    /// - `NaN` if the number is NaN
+    ///
+    #[inline(always)]
+    fn signum(&self) -> f32 {
+        if self.is_NaN() { NaN } else { copysign(1.0, *self) }
+    }
+
+    /// Returns `true` if the number is positive, including `+0.0` and `infinity`
+    #[inline(always)]
+    fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity }
+
+    /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity`
+    #[inline(always)]
+    fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
+}
+
+impl Round for f32 {
+    /// Round half-way cases toward `neg_infinity`
+    #[inline(always)]
+    fn floor(&self) -> f32 { floor(*self) }
+
+    /// Round half-way cases toward `infinity`
+    #[inline(always)]
+    fn ceil(&self) -> f32 { ceil(*self) }
+
+    /// Round half-way cases away from `0.0`
+    #[inline(always)]
+    fn round(&self) -> f32 { round(*self) }
+
+    /// The integer part of the number (rounds towards `0.0`)
+    #[inline(always)]
+    fn trunc(&self) -> f32 { trunc(*self) }
+
+    ///
+    /// The fractional part of the number, satisfying:
+    ///
+    /// ~~~
+    /// assert!(x == trunc(x) + fract(x))
+    /// ~~~
+    ///
+    #[inline(always)]
+    fn fract(&self) -> f32 { *self - self.trunc() }
+}
+
+impl Fractional for f32 {
+    /// The reciprocal (multiplicative inverse) of the number
+    #[inline(always)]
+    fn recip(&self) -> f32 { 1.0 / *self }
+}
+
+impl Algebraic for f32 {
+    #[inline(always)]
+    fn pow(&self, n: f32) -> f32 { pow(*self, n) }
+
+    #[inline(always)]
+    fn sqrt(&self) -> f32 { sqrt(*self) }
+
+    #[inline(always)]
+    fn rsqrt(&self) -> f32 { self.sqrt().recip() }
+
+    #[inline(always)]
+    fn cbrt(&self) -> f32 { cbrt(*self) }
+
+    #[inline(always)]
+    fn hypot(&self, other: f32) -> f32 { hypot(*self, other) }
+}
+
+impl Trigonometric for f32 {
+    #[inline(always)]
+    fn sin(&self) -> f32 { sin(*self) }
+
+    #[inline(always)]
+    fn cos(&self) -> f32 { cos(*self) }
+
+    #[inline(always)]
+    fn tan(&self) -> f32 { tan(*self) }
+
+    #[inline(always)]
+    fn asin(&self) -> f32 { asin(*self) }
+
+    #[inline(always)]
+    fn acos(&self) -> f32 { acos(*self) }
+
+    #[inline(always)]
+    fn atan(&self) -> f32 { atan(*self) }
+
+    #[inline(always)]
+    fn atan2(&self, other: f32) -> f32 { atan2(*self, other) }
+
+    /// Simultaneously computes the sine and cosine of the number
+    #[inline(always)]
+    fn sin_cos(&self) -> (f32, f32) {
+        (self.sin(), self.cos())
+    }
+}
+
+impl Exponential for f32 {
+    /// Returns the exponential of the number
+    #[inline(always)]
+    fn exp(&self) -> f32 { exp(*self) }
+
+    /// Returns 2 raised to the power of the number
+    #[inline(always)]
+    fn exp2(&self) -> f32 { exp2(*self) }
+
+    /// Returns the natural logarithm of the number
+    #[inline(always)]
+    fn ln(&self) -> f32 { ln(*self) }
+
+    /// Returns the logarithm of the number with respect to an arbitrary base
+    #[inline(always)]
+    fn log(&self, base: f32) -> f32 { self.ln() / base.ln() }
+
+    /// Returns the base 2 logarithm of the number
+    #[inline(always)]
+    fn log2(&self) -> f32 { log2(*self) }
+
+    /// Returns the base 10 logarithm of the number
+    #[inline(always)]
+    fn log10(&self) -> f32 { log10(*self) }
+}
+
+impl Hyperbolic for f32 {
+    #[inline(always)]
+    fn sinh(&self) -> f32 { sinh(*self) }
+
+    #[inline(always)]
+    fn cosh(&self) -> f32 { cosh(*self) }
+
+    #[inline(always)]
+    fn tanh(&self) -> f32 { tanh(*self) }
+
+    ///
+    /// Inverse hyperbolic sine
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic sine of `self` will be returned
+    /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity`
+    /// - `NaN` if `self` is `NaN`
+    ///
+    #[inline(always)]
+    fn asinh(&self) -> f32 {
+        match *self {
+            neg_infinity => neg_infinity,
+            x => (x + ((x * x) + 1.0).sqrt()).ln(),
+        }
+    }
+
+    ///
+    /// Inverse hyperbolic cosine
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic cosine of `self` will be returned
+    /// - `infinity` if `self` is `infinity`
+    /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`)
+    ///
+    #[inline(always)]
+    fn acosh(&self) -> f32 {
+        match *self {
+            x if x < 1.0 => Float::NaN(),
+            x => (x + ((x * x) - 1.0).sqrt()).ln(),
+        }
+    }
+
+    ///
+    /// Inverse hyperbolic tangent
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic tangent of `self` will be returned
+    /// - `self` if `self` is `0.0` or `-0.0`
+    /// - `infinity` if `self` is `1.0`
+    /// - `neg_infinity` if `self` is `-1.0`
+    /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0`
+    ///   (including `infinity` and `neg_infinity`)
+    ///
+    #[inline(always)]
+    fn atanh(&self) -> f32 {
+        0.5 * ((2.0 * *self) / (1.0 - *self)).ln_1p()
+    }
+}
+
+impl Real for f32 {
+    /// Archimedes' constant
+    #[inline(always)]
+    fn pi() -> f32 { 3.14159265358979323846264338327950288 }
+
+    /// 2.0 * pi
+    #[inline(always)]
+    fn two_pi() -> f32 { 6.28318530717958647692528676655900576 }
+
+    /// pi / 2.0
+    #[inline(always)]
+    fn frac_pi_2() -> f32 { 1.57079632679489661923132169163975144 }
+
+    /// pi / 3.0
+    #[inline(always)]
+    fn frac_pi_3() -> f32 { 1.04719755119659774615421446109316763 }
+
+    /// pi / 4.0
+    #[inline(always)]
+    fn frac_pi_4() -> f32 { 0.785398163397448309615660845819875721 }
+
+    /// pi / 6.0
+    #[inline(always)]
+    fn frac_pi_6() -> f32 { 0.52359877559829887307710723054658381 }
+
+    /// pi / 8.0
+    #[inline(always)]
+    fn frac_pi_8() -> f32 { 0.39269908169872415480783042290993786 }
+
+    /// 1 .0/ pi
+    #[inline(always)]
+    fn frac_1_pi() -> f32 { 0.318309886183790671537767526745028724 }
+
+    /// 2.0 / pi
+    #[inline(always)]
+    fn frac_2_pi() -> f32 { 0.636619772367581343075535053490057448 }
+
+    /// 2.0 / sqrt(pi)
+    #[inline(always)]
+    fn frac_2_sqrtpi() -> f32 { 1.12837916709551257389615890312154517 }
+
+    /// sqrt(2.0)
+    #[inline(always)]
+    fn sqrt2() -> f32 { 1.41421356237309504880168872420969808 }
+
+    /// 1.0 / sqrt(2.0)
+    #[inline(always)]
+    fn frac_1_sqrt2() -> f32 { 0.707106781186547524400844362104849039 }
+
+    /// Euler's number
+    #[inline(always)]
+    fn e() -> f32 { 2.71828182845904523536028747135266250 }
+
+    /// log2(e)
+    #[inline(always)]
+    fn log2_e() -> f32 { 1.44269504088896340735992468100189214 }
+
+    /// log10(e)
+    #[inline(always)]
+    fn log10_e() -> f32 { 0.434294481903251827651128918916605082 }
+
+    /// ln(2.0)
+    #[inline(always)]
+    fn ln_2() -> f32 { 0.693147180559945309417232121458176568 }
+
+    /// ln(10.0)
+    #[inline(always)]
+    fn ln_10() -> f32 { 2.30258509299404568401799145468436421 }
+
+    /// Converts to degrees, assuming the number is in radians
+    #[inline(always)]
+    fn to_degrees(&self) -> f32 { *self * (180.0 / Real::pi::<f32>()) }
+
+    /// Converts to radians, assuming the number is in degrees
+    #[inline(always)]
+    fn to_radians(&self) -> f32 { *self * (Real::pi::<f32>() / 180.0) }
+}
+
+impl Bounded for f32 {
+    #[inline(always)]
+    fn min_value() -> f32 { 1.17549435e-38 }
+
+    #[inline(always)]
+    fn max_value() -> f32 { 3.40282347e+38 }
+}
+
+impl Primitive for f32 {
+    #[inline(always)]
+    fn bits() -> uint { 32 }
+
+    #[inline(always)]
+    fn bytes() -> uint { Primitive::bits::<f32>() / 8 }
+}
+
+impl Float for f32 {
+    #[inline(always)]
+    fn NaN() -> f32 { 0.0 / 0.0 }
+
+    #[inline(always)]
+    fn infinity() -> f32 { 1.0 / 0.0 }
+
+    #[inline(always)]
+    fn neg_infinity() -> f32 { -1.0 / 0.0 }
+
+    #[inline(always)]
+    fn neg_zero() -> f32 { -0.0 }
+
+    /// Returns `true` if the number is NaN
+    #[inline(always)]
+    fn is_NaN(&self) -> bool { *self != *self }
+
+    /// Returns `true` if the number is infinite
+    #[inline(always)]
+    fn is_infinite(&self) -> bool {
+        *self == Float::infinity() || *self == Float::neg_infinity()
+    }
+
+    /// Returns `true` if the number is neither infinite or NaN
+    #[inline(always)]
+    fn is_finite(&self) -> bool {
+        !(self.is_NaN() || self.is_infinite())
+    }
+
+    /// Returns `true` if the number is neither zero, infinite, subnormal or NaN
+    #[inline(always)]
+    fn is_normal(&self) -> bool {
+        self.classify() == FPNormal
+    }
+
+    /// Returns the floating point category of the number. If only one property is going to
+    /// be tested, it is generally faster to use the specific predicate instead.
+    fn classify(&self) -> FPCategory {
+        static EXP_MASK: u32 = 0x7f800000;
+        static MAN_MASK: u32 = 0x007fffff;
+
+        match (
+            unsafe { ::cast::transmute::<f32,u32>(*self) } & MAN_MASK,
+            unsafe { ::cast::transmute::<f32,u32>(*self) } & EXP_MASK,
+        ) {
+            (0, 0)        => FPZero,
+            (_, 0)        => FPSubnormal,
+            (0, EXP_MASK) => FPInfinite,
+            (_, EXP_MASK) => FPNaN,
+            _             => FPNormal,
+        }
+    }
+
+    #[inline(always)]
+    fn mantissa_digits() -> uint { 24 }
+
+    #[inline(always)]
+    fn digits() -> uint { 6 }
+
+    #[inline(always)]
+    fn epsilon() -> f32 { 1.19209290e-07 }
+
+    #[inline(always)]
+    fn min_exp() -> int { -125 }
+
+    #[inline(always)]
+    fn max_exp() -> int { 128 }
+
+    #[inline(always)]
+    fn min_10_exp() -> int { -37 }
+
+    #[inline(always)]
+    fn max_10_exp() -> int { 38 }
+
+    /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp`
+    #[inline(always)]
+    fn ldexp(x: f32, exp: int) -> f32 {
+        ldexp(x, exp as c_int)
+    }
+
+    ///
+    /// Breaks the number into a normalized fraction and a base-2 exponent, satisfying:
+    ///
+    /// - `self = x * pow(2, exp)`
+    /// - `0.5 <= abs(x) < 1.0`
+    ///
+    #[inline(always)]
+    fn frexp(&self) -> (f32, int) {
+        let mut exp = 0;
+        let x = frexp(*self, &mut exp);
+        (x, exp as int)
+    }
+
+    ///
+    /// Returns the exponential of the number, minus `1`, in a way that is accurate
+    /// even if the number is close to zero
+    ///
+    #[inline(always)]
+    fn exp_m1(&self) -> f32 { exp_m1(*self) }
+
+    ///
+    /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more accurately
+    /// than if the operations were performed separately
+    ///
+    #[inline(always)]
+    fn ln_1p(&self) -> f32 { ln_1p(*self) }
+
+    ///
+    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
+    /// produces a more accurate result with better performance than a separate multiplication
+    /// operation followed by an add.
+    ///
+    #[inline(always)]
+    fn mul_add(&self, a: f32, b: f32) -> f32 {
+        mul_add(*self, a, b)
+    }
+
+    /// Returns the next representable floating-point value in the direction of `other`
+    #[inline(always)]
+    fn next_after(&self, other: f32) -> f32 {
+        next_after(*self, other)
+    }
+}
+
+//
+// Section: String Conversions
+//
+
+///
+/// Converts a float to a string
+///
+/// # Arguments
+///
+/// * num - The float value
+///
+#[inline(always)]
+pub fn to_str(num: f32) -> ~str {
+    let (r, _) = strconv::to_str_common(
+        &num, 10u, true, strconv::SignNeg, strconv::DigAll);
+    r
+}
+
+///
+/// Converts a float to a string in hexadecimal format
+///
+/// # Arguments
+///
+/// * num - The float value
+///
+#[inline(always)]
+pub fn to_str_hex(num: f32) -> ~str {
+    let (r, _) = strconv::to_str_common(
+        &num, 16u, true, strconv::SignNeg, strconv::DigAll);
+    r
+}
+
+///
+/// Converts a float to a string in a given radix
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * radix - The base to use
+///
+/// # Failure
+///
+/// Fails if called on a special value like `inf`, `-inf` or `NaN` due to
+/// possible misinterpretation of the result at higher bases. If those values
+/// are expected, use `to_str_radix_special()` instead.
+///
+#[inline(always)]
+pub fn to_str_radix(num: f32, rdx: uint) -> ~str {
+    let (r, special) = strconv::to_str_common(
+        &num, rdx, true, strconv::SignNeg, strconv::DigAll);
+    if special { fail!("number has a special value, \
+                      try to_str_radix_special() if those are expected") }
+    r
+}
+
+///
+/// Converts a float to a string in a given radix, and a flag indicating
+/// whether it's a special value
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * radix - The base to use
+///
+#[inline(always)]
+pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) {
+    strconv::to_str_common(&num, rdx, true,
+                           strconv::SignNeg, strconv::DigAll)
+}
+
+///
+/// Converts a float to a string with exactly the number of
+/// provided significant digits
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * digits - The number of significant digits
+///
+#[inline(always)]
+pub fn to_str_exact(num: f32, dig: uint) -> ~str {
+    let (r, _) = strconv::to_str_common(
+        &num, 10u, true, strconv::SignNeg, strconv::DigExact(dig));
+    r
+}
+
+///
+/// Converts a float to a string with a maximum number of
+/// significant digits
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * digits - The number of significant digits
+///
+#[inline(always)]
+pub fn to_str_digits(num: f32, dig: uint) -> ~str {
+    let (r, _) = strconv::to_str_common(
+        &num, 10u, true, strconv::SignNeg, strconv::DigMax(dig));
+    r
+}
+
+impl to_str::ToStr for f32 {
+    #[inline(always)]
+    fn to_str(&self) -> ~str { to_str_digits(*self, 8) }
+}
+
+impl num::ToStrRadix for f32 {
+    #[inline(always)]
+    fn to_str_radix(&self, rdx: uint) -> ~str {
+        to_str_radix(*self, rdx)
+    }
+}
+
+///
+/// Convert a string in base 10 to a float.
+/// Accepts a optional decimal exponent.
+///
+/// This function accepts strings such as
+///
+/// * '3.14'
+/// * '+3.14', equivalent to '3.14'
+/// * '-3.14'
+/// * '2.5E10', or equivalently, '2.5e10'
+/// * '2.5E-10'
+/// * '.' (understood as 0)
+/// * '5.'
+/// * '.5', or, equivalently,  '0.5'
+/// * '+inf', 'inf', '-inf', 'NaN'
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number.  Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `num`.
+///
+#[inline(always)]
+pub fn from_str(num: &str) -> Option<f32> {
+    strconv::from_str_common(num, 10u, true, true, true,
+                             strconv::ExpDec, false, false)
+}
+
+///
+/// Convert a string in base 16 to a float.
+/// Accepts a optional binary exponent.
+///
+/// This function accepts strings such as
+///
+/// * 'a4.fe'
+/// * '+a4.fe', equivalent to 'a4.fe'
+/// * '-a4.fe'
+/// * '2b.aP128', or equivalently, '2b.ap128'
+/// * '2b.aP-128'
+/// * '.' (understood as 0)
+/// * 'c.'
+/// * '.c', or, equivalently,  '0.c'
+/// * '+inf', 'inf', '-inf', 'NaN'
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number.  Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `[num]`.
+///
+#[inline(always)]
+pub fn from_str_hex(num: &str) -> Option<f32> {
+    strconv::from_str_common(num, 16u, true, true, true,
+                             strconv::ExpBin, false, false)
+}
+
+///
+/// Convert a string in an given base to a float.
+///
+/// Due to possible conflicts, this function does **not** accept
+/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
+/// does it recognize exponents of any kind.
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+/// * radix - The base to use. Must lie in the range [2 .. 36]
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number. Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `num`.
+///
+#[inline(always)]
+pub fn from_str_radix(num: &str, rdx: uint) -> Option<f32> {
+    strconv::from_str_common(num, rdx, true, true, false,
+                             strconv::ExpNone, false, false)
+}
+
+impl FromStr for f32 {
+    #[inline(always)]
+    fn from_str(val: &str) -> Option<f32> { from_str(val) }
+}
+
+impl num::FromStrRadix for f32 {
+    #[inline(always)]
+    fn from_str_radix(val: &str, rdx: uint) -> Option<f32> {
+        from_str_radix(val, rdx)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use f32::*;
+    use num::*;
+    use super::*;
+    use prelude::*;
+
+    #[test]
+    fn test_num() {
+        num::test_num(10f32, 2f32);
+    }
+
+    #[test]
+    fn test_min() {
+        assert_eq!(1f32.min(&2f32), 1f32);
+        assert_eq!(2f32.min(&1f32), 1f32);
+    }
+
+    #[test]
+    fn test_max() {
+        assert_eq!(1f32.max(&2f32), 2f32);
+        assert_eq!(2f32.max(&1f32), 2f32);
+    }
+
+    #[test]
+    fn test_clamp() {
+        assert_eq!(1f32.clamp(&2f32, &4f32), 2f32);
+        assert_eq!(8f32.clamp(&2f32, &4f32), 4f32);
+        assert_eq!(3f32.clamp(&2f32, &4f32), 3f32);
+        assert!(3f32.clamp(&Float::NaN::<f32>(), &4f32).is_NaN());
+        assert!(3f32.clamp(&2f32, &Float::NaN::<f32>()).is_NaN());
+        assert!(Float::NaN::<f32>().clamp(&2f32, &4f32).is_NaN());
+    }
+
+    #[test]
+    fn test_floor() {
+        assert_approx_eq!(1.0f32.floor(), 1.0f32);
+        assert_approx_eq!(1.3f32.floor(), 1.0f32);
+        assert_approx_eq!(1.5f32.floor(), 1.0f32);
+        assert_approx_eq!(1.7f32.floor(), 1.0f32);
+        assert_approx_eq!(0.0f32.floor(), 0.0f32);
+        assert_approx_eq!((-0.0f32).floor(), -0.0f32);
+        assert_approx_eq!((-1.0f32).floor(), -1.0f32);
+        assert_approx_eq!((-1.3f32).floor(), -2.0f32);
+        assert_approx_eq!((-1.5f32).floor(), -2.0f32);
+        assert_approx_eq!((-1.7f32).floor(), -2.0f32);
+    }
+
+    #[test]
+    fn test_ceil() {
+        assert_approx_eq!(1.0f32.ceil(), 1.0f32);
+        assert_approx_eq!(1.3f32.ceil(), 2.0f32);
+        assert_approx_eq!(1.5f32.ceil(), 2.0f32);
+        assert_approx_eq!(1.7f32.ceil(), 2.0f32);
+        assert_approx_eq!(0.0f32.ceil(), 0.0f32);
+        assert_approx_eq!((-0.0f32).ceil(), -0.0f32);
+        assert_approx_eq!((-1.0f32).ceil(), -1.0f32);
+        assert_approx_eq!((-1.3f32).ceil(), -1.0f32);
+        assert_approx_eq!((-1.5f32).ceil(), -1.0f32);
+        assert_approx_eq!((-1.7f32).ceil(), -1.0f32);
+    }
+
+    #[test]
+    fn test_round() {
+        assert_approx_eq!(1.0f32.round(), 1.0f32);
+        assert_approx_eq!(1.3f32.round(), 1.0f32);
+        assert_approx_eq!(1.5f32.round(), 2.0f32);
+        assert_approx_eq!(1.7f32.round(), 2.0f32);
+        assert_approx_eq!(0.0f32.round(), 0.0f32);
+        assert_approx_eq!((-0.0f32).round(), -0.0f32);
+        assert_approx_eq!((-1.0f32).round(), -1.0f32);
+        assert_approx_eq!((-1.3f32).round(), -1.0f32);
+        assert_approx_eq!((-1.5f32).round(), -2.0f32);
+        assert_approx_eq!((-1.7f32).round(), -2.0f32);
+    }
+
+    #[test]
+    fn test_trunc() {
+        assert_approx_eq!(1.0f32.trunc(), 1.0f32);
+        assert_approx_eq!(1.3f32.trunc(), 1.0f32);
+        assert_approx_eq!(1.5f32.trunc(), 1.0f32);
+        assert_approx_eq!(1.7f32.trunc(), 1.0f32);
+        assert_approx_eq!(0.0f32.trunc(), 0.0f32);
+        assert_approx_eq!((-0.0f32).trunc(), -0.0f32);
+        assert_approx_eq!((-1.0f32).trunc(), -1.0f32);
+        assert_approx_eq!((-1.3f32).trunc(), -1.0f32);
+        assert_approx_eq!((-1.5f32).trunc(), -1.0f32);
+        assert_approx_eq!((-1.7f32).trunc(), -1.0f32);
+    }
+
+    #[test]
+    fn test_fract() {
+        assert_approx_eq!(1.0f32.fract(), 0.0f32);
+        assert_approx_eq!(1.3f32.fract(), 0.3f32);
+        assert_approx_eq!(1.5f32.fract(), 0.5f32);
+        assert_approx_eq!(1.7f32.fract(), 0.7f32);
+        assert_approx_eq!(0.0f32.fract(), 0.0f32);
+        assert_approx_eq!((-0.0f32).fract(), -0.0f32);
+        assert_approx_eq!((-1.0f32).fract(), -0.0f32);
+        assert_approx_eq!((-1.3f32).fract(), -0.3f32);
+        assert_approx_eq!((-1.5f32).fract(), -0.5f32);
+        assert_approx_eq!((-1.7f32).fract(), -0.7f32);
+    }
+
+    #[test]
+    fn test_asinh() {
+        assert_eq!(0.0f32.asinh(), 0.0f32);
+        assert_eq!((-0.0f32).asinh(), -0.0f32);
+        assert_eq!(Float::infinity::<f32>().asinh(), Float::infinity::<f32>());
+        assert_eq!(Float::neg_infinity::<f32>().asinh(), Float::neg_infinity::<f32>());
+        assert!(Float::NaN::<f32>().asinh().is_NaN());
+        assert_approx_eq!(2.0f32.asinh(), 1.443635475178810342493276740273105f32);
+        assert_approx_eq!((-2.0f32).asinh(), -1.443635475178810342493276740273105f32);
+    }
+
+    #[test]
+    fn test_acosh() {
+        assert_eq!(1.0f32.acosh(), 0.0f32);
+        assert!(0.999f32.acosh().is_NaN());
+        assert_eq!(Float::infinity::<f32>().acosh(), Float::infinity::<f32>());
+        assert!(Float::neg_infinity::<f32>().acosh().is_NaN());
+        assert!(Float::NaN::<f32>().acosh().is_NaN());
+        assert_approx_eq!(2.0f32.acosh(), 1.31695789692481670862504634730796844f32);
+        assert_approx_eq!(3.0f32.acosh(), 1.76274717403908605046521864995958461f32);
+    }
+
+    #[test]
+    fn test_atanh() {
+        assert_eq!(0.0f32.atanh(), 0.0f32);
+        assert_eq!((-0.0f32).atanh(), -0.0f32);
+        assert_eq!(1.0f32.atanh(), Float::infinity::<f32>());
+        assert_eq!((-1.0f32).atanh(), Float::neg_infinity::<f32>());
+        assert!(2f64.atanh().atanh().is_NaN());
+        assert!((-2f64).atanh().atanh().is_NaN());
+        assert!(Float::infinity::<f64>().atanh().is_NaN());
+        assert!(Float::neg_infinity::<f64>().atanh().is_NaN());
+        assert!(Float::NaN::<f32>().atanh().is_NaN());
+        assert_approx_eq!(0.5f32.atanh(), 0.54930614433405484569762261846126285f32);
+        assert_approx_eq!((-0.5f32).atanh(), -0.54930614433405484569762261846126285f32);
+    }
+
+    #[test]
+    fn test_real_consts() {
+        assert_approx_eq!(Real::two_pi::<f32>(), 2f32 * Real::pi::<f32>());
+        assert_approx_eq!(Real::frac_pi_2::<f32>(), Real::pi::<f32>() / 2f32);
+        assert_approx_eq!(Real::frac_pi_3::<f32>(), Real::pi::<f32>() / 3f32);
+        assert_approx_eq!(Real::frac_pi_4::<f32>(), Real::pi::<f32>() / 4f32);
+        assert_approx_eq!(Real::frac_pi_6::<f32>(), Real::pi::<f32>() / 6f32);
+        assert_approx_eq!(Real::frac_pi_8::<f32>(), Real::pi::<f32>() / 8f32);
+        assert_approx_eq!(Real::frac_1_pi::<f32>(), 1f32 / Real::pi::<f32>());
+        assert_approx_eq!(Real::frac_2_pi::<f32>(), 2f32 / Real::pi::<f32>());
+        assert_approx_eq!(Real::frac_2_sqrtpi::<f32>(), 2f32 / Real::pi::<f32>().sqrt());
+        assert_approx_eq!(Real::sqrt2::<f32>(), 2f32.sqrt());
+        assert_approx_eq!(Real::frac_1_sqrt2::<f32>(), 1f32 / 2f32.sqrt());
+        assert_approx_eq!(Real::log2_e::<f32>(), Real::e::<f32>().log2());
+        assert_approx_eq!(Real::log10_e::<f32>(), Real::e::<f32>().log10());
+        assert_approx_eq!(Real::ln_2::<f32>(), 2f32.ln());
+        assert_approx_eq!(Real::ln_10::<f32>(), 10f32.ln());
+    }
+
+    #[test]
+    pub fn test_abs() {
+        assert_eq!(infinity.abs(), infinity);
+        assert_eq!(1f32.abs(), 1f32);
+        assert_eq!(0f32.abs(), 0f32);
+        assert_eq!((-0f32).abs(), 0f32);
+        assert_eq!((-1f32).abs(), 1f32);
+        assert_eq!(neg_infinity.abs(), infinity);
+        assert_eq!((1f32/neg_infinity).abs(), 0f32);
+        assert!(NaN.abs().is_NaN());
+    }
+
+    #[test]
+    fn test_abs_sub() {
+        assert_eq!((-1f32).abs_sub(&1f32), 0f32);
+        assert_eq!(1f32.abs_sub(&1f32), 0f32);
+        assert_eq!(1f32.abs_sub(&0f32), 1f32);
+        assert_eq!(1f32.abs_sub(&-1f32), 2f32);
+        assert_eq!(neg_infinity.abs_sub(&0f32), 0f32);
+        assert_eq!(infinity.abs_sub(&1f32), infinity);
+        assert_eq!(0f32.abs_sub(&neg_infinity), infinity);
+        assert_eq!(0f32.abs_sub(&infinity), 0f32);
+        assert!(NaN.abs_sub(&-1f32).is_NaN());
+        assert!(1f32.abs_sub(&NaN).is_NaN());
+    }
+
+    #[test]
+    fn test_signum() {
+        assert_eq!(infinity.signum(), 1f32);
+        assert_eq!(1f32.signum(), 1f32);
+        assert_eq!(0f32.signum(), 1f32);
+        assert_eq!((-0f32).signum(), -1f32);
+        assert_eq!((-1f32).signum(), -1f32);
+        assert_eq!(neg_infinity.signum(), -1f32);
+        assert_eq!((1f32/neg_infinity).signum(), -1f32);
+        assert!(NaN.signum().is_NaN());
+    }
+
+    #[test]
+    fn test_is_positive() {
+        assert!(infinity.is_positive());
+        assert!(1f32.is_positive());
+        assert!(0f32.is_positive());
+        assert!(!(-0f32).is_positive());
+        assert!(!(-1f32).is_positive());
+        assert!(!neg_infinity.is_positive());
+        assert!(!(1f32/neg_infinity).is_positive());
+        assert!(!NaN.is_positive());
+    }
+
+    #[test]
+    fn test_is_negative() {
+        assert!(!infinity.is_negative());
+        assert!(!1f32.is_negative());
+        assert!(!0f32.is_negative());
+        assert!((-0f32).is_negative());
+        assert!((-1f32).is_negative());
+        assert!(neg_infinity.is_negative());
+        assert!((1f32/neg_infinity).is_negative());
+        assert!(!NaN.is_negative());
+    }
+
+    #[test]
+    fn test_approx_eq() {
+        assert!(1.0f32.approx_eq(&1f32));
+        assert!(0.9999999f32.approx_eq(&1f32));
+        assert!(1.000001f32.approx_eq_eps(&1f32, &1.0e-5));
+        assert!(1.0000001f32.approx_eq_eps(&1f32, &1.0e-6));
+        assert!(!1.0000001f32.approx_eq_eps(&1f32, &1.0e-7));
+    }
+
+    #[test]
+    fn test_primitive() {
+        assert_eq!(Primitive::bits::<f32>(), sys::size_of::<f32>() * 8);
+        assert_eq!(Primitive::bytes::<f32>(), sys::size_of::<f32>());
+    }
+
+    #[test]
+    fn test_is_normal() {
+        assert!(!Float::NaN::<f32>().is_normal());
+        assert!(!Float::infinity::<f32>().is_normal());
+        assert!(!Float::neg_infinity::<f32>().is_normal());
+        assert!(!Zero::zero::<f32>().is_normal());
+        assert!(!Float::neg_zero::<f32>().is_normal());
+        assert!(1f32.is_normal());
+        assert!(1e-37f32.is_normal());
+        assert!(!1e-38f32.is_normal());
+    }
+
+    #[test]
+    fn test_classify() {
+        assert_eq!(Float::NaN::<f32>().classify(), FPNaN);
+        assert_eq!(Float::infinity::<f32>().classify(), FPInfinite);
+        assert_eq!(Float::neg_infinity::<f32>().classify(), FPInfinite);
+        assert_eq!(Zero::zero::<f32>().classify(), FPZero);
+        assert_eq!(Float::neg_zero::<f32>().classify(), FPZero);
+        assert_eq!(1f32.classify(), FPNormal);
+        assert_eq!(1e-37f32.classify(), FPNormal);
+        assert_eq!(1e-38f32.classify(), FPSubnormal);
+    }
+
+    #[test]
+    fn test_ldexp() {
+        // We have to use from_str until base-2 exponents
+        // are supported in floating-point literals
+        let f1: f32 = from_str_hex("1p-123").unwrap();
+        let f2: f32 = from_str_hex("1p-111").unwrap();
+        assert_eq!(Float::ldexp(1f32, -123), f1);
+        assert_eq!(Float::ldexp(1f32, -111), f2);
+
+        assert_eq!(Float::ldexp(0f32, -123), 0f32);
+        assert_eq!(Float::ldexp(-0f32, -123), -0f32);
+        assert_eq!(Float::ldexp(Float::infinity::<f32>(), -123),
+                   Float::infinity::<f32>());
+        assert_eq!(Float::ldexp(Float::neg_infinity::<f32>(), -123),
+                   Float::neg_infinity::<f32>());
+        assert!(Float::ldexp(Float::NaN::<f32>(), -123).is_NaN());
+    }
+
+    #[test]
+    fn test_frexp() {
+        // We have to use from_str until base-2 exponents
+        // are supported in floating-point literals
+        let f1: f32 = from_str_hex("1p-123").unwrap();
+        let f2: f32 = from_str_hex("1p-111").unwrap();
+        let (x1, exp1) = f1.frexp();
+        let (x2, exp2) = f2.frexp();
+        assert_eq!((x1, exp1), (0.5f32, -122));
+        assert_eq!((x2, exp2), (0.5f32, -110));
+        assert_eq!(Float::ldexp(x1, exp1), f1);
+        assert_eq!(Float::ldexp(x2, exp2), f2);
+
+        assert_eq!(0f32.frexp(), (0f32, 0));
+        assert_eq!((-0f32).frexp(), (-0f32, 0));
+        assert_eq!(match Float::infinity::<f32>().frexp() { (x, _) => x },
+                   Float::infinity::<f32>())
+        assert_eq!(match Float::neg_infinity::<f32>().frexp() { (x, _) => x },
+                   Float::neg_infinity::<f32>())
+        assert!(match Float::NaN::<f32>().frexp() { (x, _) => x.is_NaN() })
+    }
+}
diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs
new file mode 100644
index 00000000000..6e2496e2e45
--- /dev/null
+++ b/src/libstd/num/f64.rs
@@ -0,0 +1,1295 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations and constants for `f64`
+
+use libc::c_int;
+use num::{Zero, One, strconv};
+use num::{FPCategory, FPNaN, FPInfinite , FPZero, FPSubnormal, FPNormal};
+use prelude::*;
+
+pub use cmath::c_double_targ_consts::*;
+pub use cmp::{min, max};
+
+// An inner module is required to get the #[inline(always)] attribute on the
+// functions.
+pub use self::delegated::*;
+
+macro_rules! delegate(
+    (
+        $(
+            fn $name:ident(
+                $(
+                    $arg:ident : $arg_ty:ty
+                ),*
+            ) -> $rv:ty = $bound_name:path
+        ),*
+    ) => (
+        mod delegated {
+            use cmath::c_double_utils;
+            use libc::{c_double, c_int};
+            use unstable::intrinsics;
+
+            $(
+                #[inline(always)]
+                pub fn $name($( $arg : $arg_ty ),*) -> $rv {
+                    unsafe {
+                        $bound_name($( $arg ),*)
+                    }
+                }
+            )*
+        }
+    )
+)
+
+delegate!(
+    // intrinsics
+    fn abs(n: f64) -> f64 = intrinsics::fabsf64,
+    fn cos(n: f64) -> f64 = intrinsics::cosf64,
+    fn exp(n: f64) -> f64 = intrinsics::expf64,
+    fn exp2(n: f64) -> f64 = intrinsics::exp2f64,
+    fn floor(x: f64) -> f64 = intrinsics::floorf64,
+    fn ln(n: f64) -> f64 = intrinsics::logf64,
+    fn log10(n: f64) -> f64 = intrinsics::log10f64,
+    fn log2(n: f64) -> f64 = intrinsics::log2f64,
+    fn mul_add(a: f64, b: f64, c: f64) -> f64 = intrinsics::fmaf64,
+    fn pow(n: f64, e: f64) -> f64 = intrinsics::powf64,
+    fn powi(n: f64, e: c_int) -> f64 = intrinsics::powif64,
+    fn sin(n: f64) -> f64 = intrinsics::sinf64,
+    fn sqrt(n: f64) -> f64 = intrinsics::sqrtf64,
+
+    // LLVM 3.3 required to use intrinsics for these four
+    fn ceil(n: c_double) -> c_double = c_double_utils::ceil,
+    fn trunc(n: c_double) -> c_double = c_double_utils::trunc,
+    /*
+    fn ceil(n: f64) -> f64 = intrinsics::ceilf64,
+    fn trunc(n: f64) -> f64 = intrinsics::truncf64,
+    fn rint(n: c_double) -> c_double = intrinsics::rintf64,
+    fn nearbyint(n: c_double) -> c_double = intrinsics::nearbyintf64,
+    */
+
+    // cmath
+    fn acos(n: c_double) -> c_double = c_double_utils::acos,
+    fn asin(n: c_double) -> c_double = c_double_utils::asin,
+    fn atan(n: c_double) -> c_double = c_double_utils::atan,
+    fn atan2(a: c_double, b: c_double) -> c_double = c_double_utils::atan2,
+    fn cbrt(n: c_double) -> c_double = c_double_utils::cbrt,
+    fn copysign(x: c_double, y: c_double) -> c_double = c_double_utils::copysign,
+    fn cosh(n: c_double) -> c_double = c_double_utils::cosh,
+    fn erf(n: c_double) -> c_double = c_double_utils::erf,
+    fn erfc(n: c_double) -> c_double = c_double_utils::erfc,
+    fn exp_m1(n: c_double) -> c_double = c_double_utils::exp_m1,
+    fn abs_sub(a: c_double, b: c_double) -> c_double = c_double_utils::abs_sub,
+    fn fmax(a: c_double, b: c_double) -> c_double = c_double_utils::fmax,
+    fn fmin(a: c_double, b: c_double) -> c_double = c_double_utils::fmin,
+    fn next_after(x: c_double, y: c_double) -> c_double = c_double_utils::next_after,
+    fn frexp(n: c_double, value: &mut c_int) -> c_double = c_double_utils::frexp,
+    fn hypot(x: c_double, y: c_double) -> c_double = c_double_utils::hypot,
+    fn ldexp(x: c_double, n: c_int) -> c_double = c_double_utils::ldexp,
+    fn lgamma(n: c_double, sign: &mut c_int) -> c_double = c_double_utils::lgamma,
+    fn log_radix(n: c_double) -> c_double = c_double_utils::log_radix,
+    fn ln_1p(n: c_double) -> c_double = c_double_utils::ln_1p,
+    fn ilog_radix(n: c_double) -> c_int = c_double_utils::ilog_radix,
+    fn modf(n: c_double, iptr: &mut c_double) -> c_double = c_double_utils::modf,
+    fn round(n: c_double) -> c_double = c_double_utils::round,
+    fn ldexp_radix(n: c_double, i: c_int) -> c_double = c_double_utils::ldexp_radix,
+    fn sinh(n: c_double) -> c_double = c_double_utils::sinh,
+    fn tan(n: c_double) -> c_double = c_double_utils::tan,
+    fn tanh(n: c_double) -> c_double = c_double_utils::tanh,
+    fn tgamma(n: c_double) -> c_double = c_double_utils::tgamma,
+    fn j0(n: c_double) -> c_double = c_double_utils::j0,
+    fn j1(n: c_double) -> c_double = c_double_utils::j1,
+    fn jn(i: c_int, n: c_double) -> c_double = c_double_utils::jn,
+    fn y0(n: c_double) -> c_double = c_double_utils::y0,
+    fn y1(n: c_double) -> c_double = c_double_utils::y1,
+    fn yn(i: c_int, n: c_double) -> c_double = c_double_utils::yn
+)
+
+// FIXME (#1433): obtain these in a different way
+
+// These are not defined inside consts:: for consistency with
+// the integer types
+
+pub static radix: uint = 2u;
+
+pub static mantissa_digits: uint = 53u;
+pub static digits: uint = 15u;
+
+pub static epsilon: f64 = 2.2204460492503131e-16_f64;
+
+pub static min_value: f64 = 2.2250738585072014e-308_f64;
+pub static max_value: f64 = 1.7976931348623157e+308_f64;
+
+pub static min_exp: int = -1021;
+pub static max_exp: int = 1024;
+
+pub static min_10_exp: int = -307;
+pub static max_10_exp: int = 308;
+
+pub static NaN: f64 = 0.0_f64/0.0_f64;
+
+pub static infinity: f64 = 1.0_f64/0.0_f64;
+
+pub static neg_infinity: f64 = -1.0_f64/0.0_f64;
+
+#[inline(always)]
+pub fn add(x: f64, y: f64) -> f64 { return x + y; }
+
+#[inline(always)]
+pub fn sub(x: f64, y: f64) -> f64 { return x - y; }
+
+#[inline(always)]
+pub fn mul(x: f64, y: f64) -> f64 { return x * y; }
+
+#[inline(always)]
+pub fn div(x: f64, y: f64) -> f64 { return x / y; }
+
+#[inline(always)]
+pub fn rem(x: f64, y: f64) -> f64 { return x % y; }
+
+#[inline(always)]
+pub fn lt(x: f64, y: f64) -> bool { return x < y; }
+
+#[inline(always)]
+pub fn le(x: f64, y: f64) -> bool { return x <= y; }
+
+#[inline(always)]
+pub fn eq(x: f64, y: f64) -> bool { return x == y; }
+
+#[inline(always)]
+pub fn ne(x: f64, y: f64) -> bool { return x != y; }
+
+#[inline(always)]
+pub fn ge(x: f64, y: f64) -> bool { return x >= y; }
+
+#[inline(always)]
+pub fn gt(x: f64, y: f64) -> bool { return x > y; }
+
+
+// FIXME (#1999): add is_normal, is_subnormal, and fpclassify
+
+/* Module: consts */
+pub mod consts {
+    // FIXME (requires Issue #1433 to fix): replace with mathematical
+    // constants from cmath.
+    /// Archimedes' constant
+    pub static pi: f64 = 3.14159265358979323846264338327950288_f64;
+
+    /// pi/2.0
+    pub static frac_pi_2: f64 = 1.57079632679489661923132169163975144_f64;
+
+    /// pi/4.0
+    pub static frac_pi_4: f64 = 0.785398163397448309615660845819875721_f64;
+
+    /// 1.0/pi
+    pub static frac_1_pi: f64 = 0.318309886183790671537767526745028724_f64;
+
+    /// 2.0/pi
+    pub static frac_2_pi: f64 = 0.636619772367581343075535053490057448_f64;
+
+    /// 2.0/sqrt(pi)
+    pub static frac_2_sqrtpi: f64 = 1.12837916709551257389615890312154517_f64;
+
+    /// sqrt(2.0)
+    pub static sqrt2: f64 = 1.41421356237309504880168872420969808_f64;
+
+    /// 1.0/sqrt(2.0)
+    pub static frac_1_sqrt2: f64 = 0.707106781186547524400844362104849039_f64;
+
+    /// Euler's number
+    pub static e: f64 = 2.71828182845904523536028747135266250_f64;
+
+    /// log2(e)
+    pub static log2_e: f64 = 1.44269504088896340735992468100189214_f64;
+
+    /// log10(e)
+    pub static log10_e: f64 = 0.434294481903251827651128918916605082_f64;
+
+    /// ln(2.0)
+    pub static ln_2: f64 = 0.693147180559945309417232121458176568_f64;
+
+    /// ln(10.0)
+    pub static ln_10: f64 = 2.30258509299404568401799145468436421_f64;
+}
+
+impl Num for f64 {}
+
+#[cfg(not(test))]
+impl Eq for f64 {
+    #[inline(always)]
+    fn eq(&self, other: &f64) -> bool { (*self) == (*other) }
+    #[inline(always)]
+    fn ne(&self, other: &f64) -> bool { (*self) != (*other) }
+}
+
+#[cfg(not(test))]
+impl ApproxEq<f64> for f64 {
+    #[inline(always)]
+    fn approx_epsilon() -> f64 { 1.0e-6 }
+
+    #[inline(always)]
+    fn approx_eq(&self, other: &f64) -> bool {
+        self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<f64, f64>())
+    }
+
+    #[inline(always)]
+    fn approx_eq_eps(&self, other: &f64, approx_epsilon: &f64) -> bool {
+        (*self - *other).abs() < *approx_epsilon
+    }
+}
+
+#[cfg(not(test))]
+impl Ord for f64 {
+    #[inline(always)]
+    fn lt(&self, other: &f64) -> bool { (*self) < (*other) }
+    #[inline(always)]
+    fn le(&self, other: &f64) -> bool { (*self) <= (*other) }
+    #[inline(always)]
+    fn ge(&self, other: &f64) -> bool { (*self) >= (*other) }
+    #[inline(always)]
+    fn gt(&self, other: &f64) -> bool { (*self) > (*other) }
+}
+
+impl Orderable for f64 {
+    /// Returns `NaN` if either of the numbers are `NaN`.
+    #[inline(always)]
+    fn min(&self, other: &f64) -> f64 {
+        if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmin(*self, *other) }
+    }
+
+    /// Returns `NaN` if either of the numbers are `NaN`.
+    #[inline(always)]
+    fn max(&self, other: &f64) -> f64 {
+        if self.is_NaN() || other.is_NaN() { Float::NaN() } else { fmax(*self, *other) }
+    }
+
+    /// Returns the number constrained within the range `mn <= self <= mx`.
+    /// If any of the numbers are `NaN` then `NaN` is returned.
+    #[inline(always)]
+    fn clamp(&self, mn: &f64, mx: &f64) -> f64 {
+        cond!(
+            (self.is_NaN())   { *self }
+            (!(*self <= *mx)) { *mx   }
+            (!(*self >= *mn)) { *mn   }
+            _                 { *self }
+        )
+    }
+}
+
+impl Zero for f64 {
+    #[inline(always)]
+    fn zero() -> f64 { 0.0 }
+
+    /// Returns true if the number is equal to either `0.0` or `-0.0`
+    #[inline(always)]
+    fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 }
+}
+
+impl One for f64 {
+    #[inline(always)]
+    fn one() -> f64 { 1.0 }
+}
+
+#[cfg(not(test))]
+impl Add<f64,f64> for f64 {
+    fn add(&self, other: &f64) -> f64 { *self + *other }
+}
+#[cfg(not(test))]
+impl Sub<f64,f64> for f64 {
+    fn sub(&self, other: &f64) -> f64 { *self - *other }
+}
+#[cfg(not(test))]
+impl Mul<f64,f64> for f64 {
+    fn mul(&self, other: &f64) -> f64 { *self * *other }
+}
+#[cfg(not(test))]
+impl Div<f64,f64> for f64 {
+    fn div(&self, other: &f64) -> f64 { *self / *other }
+}
+#[cfg(not(test))]
+impl Rem<f64,f64> for f64 {
+    #[inline(always)]
+    fn rem(&self, other: &f64) -> f64 { *self % *other }
+}
+#[cfg(not(test))]
+impl Neg<f64> for f64 {
+    fn neg(&self) -> f64 { -*self }
+}
+
+impl Signed for f64 {
+    /// Computes the absolute value. Returns `NaN` if the number is `NaN`.
+    #[inline(always)]
+    fn abs(&self) -> f64 { abs(*self) }
+
+    ///
+    /// The positive difference of two numbers. Returns `0.0` if the number is less than or
+    /// equal to `other`, otherwise the difference between`self` and `other` is returned.
+    ///
+    #[inline(always)]
+    fn abs_sub(&self, other: &f64) -> f64 { abs_sub(*self, *other) }
+
+    ///
+    /// # Returns
+    ///
+    /// - `1.0` if the number is positive, `+0.0` or `infinity`
+    /// - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
+    /// - `NaN` if the number is NaN
+    ///
+    #[inline(always)]
+    fn signum(&self) -> f64 {
+        if self.is_NaN() { NaN } else { copysign(1.0, *self) }
+    }
+
+    /// Returns `true` if the number is positive, including `+0.0` and `infinity`
+    #[inline(always)]
+    fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity }
+
+    /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity`
+    #[inline(always)]
+    fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
+}
+
+impl Round for f64 {
+    /// Round half-way cases toward `neg_infinity`
+    #[inline(always)]
+    fn floor(&self) -> f64 { floor(*self) }
+
+    /// Round half-way cases toward `infinity`
+    #[inline(always)]
+    fn ceil(&self) -> f64 { ceil(*self) }
+
+    /// Round half-way cases away from `0.0`
+    #[inline(always)]
+    fn round(&self) -> f64 { round(*self) }
+
+    /// The integer part of the number (rounds towards `0.0`)
+    #[inline(always)]
+    fn trunc(&self) -> f64 { trunc(*self) }
+
+    ///
+    /// The fractional part of the number, satisfying:
+    ///
+    /// ~~~
+    /// assert!(x == trunc(x) + fract(x))
+    /// ~~~
+    ///
+    #[inline(always)]
+    fn fract(&self) -> f64 { *self - self.trunc() }
+}
+
+impl Fractional for f64 {
+    /// The reciprocal (multiplicative inverse) of the number
+    #[inline(always)]
+    fn recip(&self) -> f64 { 1.0 / *self }
+}
+
+impl Algebraic for f64 {
+    #[inline(always)]
+    fn pow(&self, n: f64) -> f64 { pow(*self, n) }
+
+    #[inline(always)]
+    fn sqrt(&self) -> f64 { sqrt(*self) }
+
+    #[inline(always)]
+    fn rsqrt(&self) -> f64 { self.sqrt().recip() }
+
+    #[inline(always)]
+    fn cbrt(&self) -> f64 { cbrt(*self) }
+
+    #[inline(always)]
+    fn hypot(&self, other: f64) -> f64 { hypot(*self, other) }
+}
+
+impl Trigonometric for f64 {
+    #[inline(always)]
+    fn sin(&self) -> f64 { sin(*self) }
+
+    #[inline(always)]
+    fn cos(&self) -> f64 { cos(*self) }
+
+    #[inline(always)]
+    fn tan(&self) -> f64 { tan(*self) }
+
+    #[inline(always)]
+    fn asin(&self) -> f64 { asin(*self) }
+
+    #[inline(always)]
+    fn acos(&self) -> f64 { acos(*self) }
+
+    #[inline(always)]
+    fn atan(&self) -> f64 { atan(*self) }
+
+    #[inline(always)]
+    fn atan2(&self, other: f64) -> f64 { atan2(*self, other) }
+
+    /// Simultaneously computes the sine and cosine of the number
+    #[inline(always)]
+    fn sin_cos(&self) -> (f64, f64) {
+        (self.sin(), self.cos())
+    }
+}
+
+impl Exponential for f64 {
+    /// Returns the exponential of the number
+    #[inline(always)]
+    fn exp(&self) -> f64 { exp(*self) }
+
+    /// Returns 2 raised to the power of the number
+    #[inline(always)]
+    fn exp2(&self) -> f64 { exp2(*self) }
+
+    /// Returns the natural logarithm of the number
+    #[inline(always)]
+    fn ln(&self) -> f64 { ln(*self) }
+
+    /// Returns the logarithm of the number with respect to an arbitrary base
+    #[inline(always)]
+    fn log(&self, base: f64) -> f64 { self.ln() / base.ln() }
+
+    /// Returns the base 2 logarithm of the number
+    #[inline(always)]
+    fn log2(&self) -> f64 { log2(*self) }
+
+    /// Returns the base 10 logarithm of the number
+    #[inline(always)]
+    fn log10(&self) -> f64 { log10(*self) }
+}
+
+impl Hyperbolic for f64 {
+    #[inline(always)]
+    fn sinh(&self) -> f64 { sinh(*self) }
+
+    #[inline(always)]
+    fn cosh(&self) -> f64 { cosh(*self) }
+
+    #[inline(always)]
+    fn tanh(&self) -> f64 { tanh(*self) }
+
+    ///
+    /// Inverse hyperbolic sine
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic sine of `self` will be returned
+    /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity`
+    /// - `NaN` if `self` is `NaN`
+    ///
+    #[inline(always)]
+    fn asinh(&self) -> f64 {
+        match *self {
+            neg_infinity => neg_infinity,
+            x => (x + ((x * x) + 1.0).sqrt()).ln(),
+        }
+    }
+
+    ///
+    /// Inverse hyperbolic cosine
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic cosine of `self` will be returned
+    /// - `infinity` if `self` is `infinity`
+    /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`)
+    ///
+    #[inline(always)]
+    fn acosh(&self) -> f64 {
+        match *self {
+            x if x < 1.0 => Float::NaN(),
+            x => (x + ((x * x) - 1.0).sqrt()).ln(),
+        }
+    }
+
+    ///
+    /// Inverse hyperbolic tangent
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic tangent of `self` will be returned
+    /// - `self` if `self` is `0.0` or `-0.0`
+    /// - `infinity` if `self` is `1.0`
+    /// - `neg_infinity` if `self` is `-1.0`
+    /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0`
+    ///   (including `infinity` and `neg_infinity`)
+    ///
+    #[inline(always)]
+    fn atanh(&self) -> f64 {
+        0.5 * ((2.0 * *self) / (1.0 - *self)).ln_1p()
+    }
+}
+
+impl Real for f64 {
+    /// Archimedes' constant
+    #[inline(always)]
+    fn pi() -> f64 { 3.14159265358979323846264338327950288 }
+
+    /// 2.0 * pi
+    #[inline(always)]
+    fn two_pi() -> f64 { 6.28318530717958647692528676655900576 }
+
+    /// pi / 2.0
+    #[inline(always)]
+    fn frac_pi_2() -> f64 { 1.57079632679489661923132169163975144 }
+
+    /// pi / 3.0
+    #[inline(always)]
+    fn frac_pi_3() -> f64 { 1.04719755119659774615421446109316763 }
+
+    /// pi / 4.0
+    #[inline(always)]
+    fn frac_pi_4() -> f64 { 0.785398163397448309615660845819875721 }
+
+    /// pi / 6.0
+    #[inline(always)]
+    fn frac_pi_6() -> f64 { 0.52359877559829887307710723054658381 }
+
+    /// pi / 8.0
+    #[inline(always)]
+    fn frac_pi_8() -> f64 { 0.39269908169872415480783042290993786 }
+
+    /// 1.0 / pi
+    #[inline(always)]
+    fn frac_1_pi() -> f64 { 0.318309886183790671537767526745028724 }
+
+    /// 2.0 / pi
+    #[inline(always)]
+    fn frac_2_pi() -> f64 { 0.636619772367581343075535053490057448 }
+
+    /// 2.0 / sqrt(pi)
+    #[inline(always)]
+    fn frac_2_sqrtpi() -> f64 { 1.12837916709551257389615890312154517 }
+
+    /// sqrt(2.0)
+    #[inline(always)]
+    fn sqrt2() -> f64 { 1.41421356237309504880168872420969808 }
+
+    /// 1.0 / sqrt(2.0)
+    #[inline(always)]
+    fn frac_1_sqrt2() -> f64 { 0.707106781186547524400844362104849039 }
+
+    /// Euler's number
+    #[inline(always)]
+    fn e() -> f64 { 2.71828182845904523536028747135266250 }
+
+    /// log2(e)
+    #[inline(always)]
+    fn log2_e() -> f64 { 1.44269504088896340735992468100189214 }
+
+    /// log10(e)
+    #[inline(always)]
+    fn log10_e() -> f64 { 0.434294481903251827651128918916605082 }
+
+    /// ln(2.0)
+    #[inline(always)]
+    fn ln_2() -> f64 { 0.693147180559945309417232121458176568 }
+
+    /// ln(10.0)
+    #[inline(always)]
+    fn ln_10() -> f64 { 2.30258509299404568401799145468436421 }
+
+    /// Converts to degrees, assuming the number is in radians
+    #[inline(always)]
+    fn to_degrees(&self) -> f64 { *self * (180.0 / Real::pi::<f64>()) }
+
+    /// Converts to radians, assuming the number is in degrees
+    #[inline(always)]
+    fn to_radians(&self) -> f64 { *self * (Real::pi::<f64>() / 180.0) }
+}
+
+impl RealExt for f64 {
+    #[inline(always)]
+    fn lgamma(&self) -> (int, f64) {
+        let mut sign = 0;
+        let result = lgamma(*self, &mut sign);
+        (sign as int, result)
+    }
+
+    #[inline(always)]
+    fn tgamma(&self) -> f64 { tgamma(*self) }
+
+    #[inline(always)]
+    fn j0(&self) -> f64 { j0(*self) }
+
+    #[inline(always)]
+    fn j1(&self) -> f64 { j1(*self) }
+
+    #[inline(always)]
+    fn jn(&self, n: int) -> f64 { jn(n as c_int, *self) }
+
+    #[inline(always)]
+    fn y0(&self) -> f64 { y0(*self) }
+
+    #[inline(always)]
+    fn y1(&self) -> f64 { y1(*self) }
+
+    #[inline(always)]
+    fn yn(&self, n: int) -> f64 { yn(n as c_int, *self) }
+}
+
+impl Bounded for f64 {
+    #[inline(always)]
+    fn min_value() -> f64 { 2.2250738585072014e-308 }
+
+    #[inline(always)]
+    fn max_value() -> f64 { 1.7976931348623157e+308 }
+}
+
+impl Primitive for f64 {
+    #[inline(always)]
+    fn bits() -> uint { 64 }
+
+    #[inline(always)]
+    fn bytes() -> uint { Primitive::bits::<f64>() / 8 }
+}
+
+impl Float for f64 {
+    #[inline(always)]
+    fn NaN() -> f64 { 0.0 / 0.0 }
+
+    #[inline(always)]
+    fn infinity() -> f64 { 1.0 / 0.0 }
+
+    #[inline(always)]
+    fn neg_infinity() -> f64 { -1.0 / 0.0 }
+
+    #[inline(always)]
+    fn neg_zero() -> f64 { -0.0 }
+
+    /// Returns `true` if the number is NaN
+    #[inline(always)]
+    fn is_NaN(&self) -> bool { *self != *self }
+
+    /// Returns `true` if the number is infinite
+    #[inline(always)]
+    fn is_infinite(&self) -> bool {
+        *self == Float::infinity() || *self == Float::neg_infinity()
+    }
+
+    /// Returns `true` if the number is neither infinite or NaN
+    #[inline(always)]
+    fn is_finite(&self) -> bool {
+        !(self.is_NaN() || self.is_infinite())
+    }
+
+    /// Returns `true` if the number is neither zero, infinite, subnormal or NaN
+    #[inline(always)]
+    fn is_normal(&self) -> bool {
+        self.classify() == FPNormal
+    }
+
+    /// Returns the floating point category of the number. If only one property is going to
+    /// be tested, it is generally faster to use the specific predicate instead.
+    fn classify(&self) -> FPCategory {
+        static EXP_MASK: u64 = 0x7ff0000000000000;
+        static MAN_MASK: u64 = 0x000fffffffffffff;
+
+        match (
+            unsafe { ::cast::transmute::<f64,u64>(*self) } & MAN_MASK,
+            unsafe { ::cast::transmute::<f64,u64>(*self) } & EXP_MASK,
+        ) {
+            (0, 0)        => FPZero,
+            (_, 0)        => FPSubnormal,
+            (0, EXP_MASK) => FPInfinite,
+            (_, EXP_MASK) => FPNaN,
+            _             => FPNormal,
+        }
+    }
+
+    #[inline(always)]
+    fn mantissa_digits() -> uint { 53 }
+
+    #[inline(always)]
+    fn digits() -> uint { 15 }
+
+    #[inline(always)]
+    fn epsilon() -> f64 { 2.2204460492503131e-16 }
+
+    #[inline(always)]
+    fn min_exp() -> int { -1021 }
+
+    #[inline(always)]
+    fn max_exp() -> int { 1024 }
+
+    #[inline(always)]
+    fn min_10_exp() -> int { -307 }
+
+    #[inline(always)]
+    fn max_10_exp() -> int { 308 }
+
+    /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp`
+    #[inline(always)]
+    fn ldexp(x: f64, exp: int) -> f64 {
+        ldexp(x, exp as c_int)
+    }
+
+    ///
+    /// Breaks the number into a normalized fraction and a base-2 exponent, satisfying:
+    ///
+    /// - `self = x * pow(2, exp)`
+    /// - `0.5 <= abs(x) < 1.0`
+    ///
+    #[inline(always)]
+    fn frexp(&self) -> (f64, int) {
+        let mut exp = 0;
+        let x = frexp(*self, &mut exp);
+        (x, exp as int)
+    }
+
+    ///
+    /// Returns the exponential of the number, minus `1`, in a way that is accurate
+    /// even if the number is close to zero
+    ///
+    #[inline(always)]
+    fn exp_m1(&self) -> f64 { exp_m1(*self) }
+
+    ///
+    /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more accurately
+    /// than if the operations were performed separately
+    ///
+    #[inline(always)]
+    fn ln_1p(&self) -> f64 { ln_1p(*self) }
+
+    ///
+    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
+    /// produces a more accurate result with better performance than a separate multiplication
+    /// operation followed by an add.
+    ///
+    #[inline(always)]
+    fn mul_add(&self, a: f64, b: f64) -> f64 {
+        mul_add(*self, a, b)
+    }
+
+    /// Returns the next representable floating-point value in the direction of `other`
+    #[inline(always)]
+    fn next_after(&self, other: f64) -> f64 {
+        next_after(*self, other)
+    }
+}
+
+//
+// Section: String Conversions
+//
+
+///
+/// Converts a float to a string
+///
+/// # Arguments
+///
+/// * num - The float value
+///
+#[inline(always)]
+pub fn to_str(num: f64) -> ~str {
+    let (r, _) = strconv::to_str_common(
+        &num, 10u, true, strconv::SignNeg, strconv::DigAll);
+    r
+}
+
+///
+/// Converts a float to a string in hexadecimal format
+///
+/// # Arguments
+///
+/// * num - The float value
+///
+#[inline(always)]
+pub fn to_str_hex(num: f64) -> ~str {
+    let (r, _) = strconv::to_str_common(
+        &num, 16u, true, strconv::SignNeg, strconv::DigAll);
+    r
+}
+
+///
+/// Converts a float to a string in a given radix
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * radix - The base to use
+///
+/// # Failure
+///
+/// Fails if called on a special value like `inf`, `-inf` or `NaN` due to
+/// possible misinterpretation of the result at higher bases. If those values
+/// are expected, use `to_str_radix_special()` instead.
+///
+#[inline(always)]
+pub fn to_str_radix(num: f64, rdx: uint) -> ~str {
+    let (r, special) = strconv::to_str_common(
+        &num, rdx, true, strconv::SignNeg, strconv::DigAll);
+    if special { fail!("number has a special value, \
+                      try to_str_radix_special() if those are expected") }
+    r
+}
+
+///
+/// Converts a float to a string in a given radix, and a flag indicating
+/// whether it's a special value
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * radix - The base to use
+///
+#[inline(always)]
+pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) {
+    strconv::to_str_common(&num, rdx, true,
+                           strconv::SignNeg, strconv::DigAll)
+}
+
+///
+/// Converts a float to a string with exactly the number of
+/// provided significant digits
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * digits - The number of significant digits
+///
+#[inline(always)]
+pub fn to_str_exact(num: f64, dig: uint) -> ~str {
+    let (r, _) = strconv::to_str_common(
+        &num, 10u, true, strconv::SignNeg, strconv::DigExact(dig));
+    r
+}
+
+///
+/// Converts a float to a string with a maximum number of
+/// significant digits
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * digits - The number of significant digits
+///
+#[inline(always)]
+pub fn to_str_digits(num: f64, dig: uint) -> ~str {
+    let (r, _) = strconv::to_str_common(
+        &num, 10u, true, strconv::SignNeg, strconv::DigMax(dig));
+    r
+}
+
+impl to_str::ToStr for f64 {
+    #[inline(always)]
+    fn to_str(&self) -> ~str { to_str_digits(*self, 8) }
+}
+
+impl num::ToStrRadix for f64 {
+    #[inline(always)]
+    fn to_str_radix(&self, rdx: uint) -> ~str {
+        to_str_radix(*self, rdx)
+    }
+}
+
+///
+/// Convert a string in base 10 to a float.
+/// Accepts a optional decimal exponent.
+///
+/// This function accepts strings such as
+///
+/// * '3.14'
+/// * '+3.14', equivalent to '3.14'
+/// * '-3.14'
+/// * '2.5E10', or equivalently, '2.5e10'
+/// * '2.5E-10'
+/// * '.' (understood as 0)
+/// * '5.'
+/// * '.5', or, equivalently,  '0.5'
+/// * '+inf', 'inf', '-inf', 'NaN'
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number.  Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `num`.
+///
+#[inline(always)]
+pub fn from_str(num: &str) -> Option<f64> {
+    strconv::from_str_common(num, 10u, true, true, true,
+                             strconv::ExpDec, false, false)
+}
+
+///
+/// Convert a string in base 16 to a float.
+/// Accepts a optional binary exponent.
+///
+/// This function accepts strings such as
+///
+/// * 'a4.fe'
+/// * '+a4.fe', equivalent to 'a4.fe'
+/// * '-a4.fe'
+/// * '2b.aP128', or equivalently, '2b.ap128'
+/// * '2b.aP-128'
+/// * '.' (understood as 0)
+/// * 'c.'
+/// * '.c', or, equivalently,  '0.c'
+/// * '+inf', 'inf', '-inf', 'NaN'
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number.  Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `[num]`.
+///
+#[inline(always)]
+pub fn from_str_hex(num: &str) -> Option<f64> {
+    strconv::from_str_common(num, 16u, true, true, true,
+                             strconv::ExpBin, false, false)
+}
+
+///
+/// Convert a string in an given base to a float.
+///
+/// Due to possible conflicts, this function does **not** accept
+/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
+/// does it recognize exponents of any kind.
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+/// * radix - The base to use. Must lie in the range [2 .. 36]
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number. Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `num`.
+///
+#[inline(always)]
+pub fn from_str_radix(num: &str, rdx: uint) -> Option<f64> {
+    strconv::from_str_common(num, rdx, true, true, false,
+                             strconv::ExpNone, false, false)
+}
+
+impl FromStr for f64 {
+    #[inline(always)]
+    fn from_str(val: &str) -> Option<f64> { from_str(val) }
+}
+
+impl num::FromStrRadix for f64 {
+    #[inline(always)]
+    fn from_str_radix(val: &str, rdx: uint) -> Option<f64> {
+        from_str_radix(val, rdx)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use f64::*;
+    use num::*;
+    use super::*;
+    use prelude::*;
+
+    #[test]
+    fn test_num() {
+        num::test_num(10f64, 2f64);
+    }
+
+    #[test]
+    fn test_min() {
+        assert_eq!(1f64.min(&2f64), 1f64);
+        assert_eq!(2f64.min(&1f64), 1f64);
+        assert!(1f64.min(&Float::NaN::<f64>()).is_NaN());
+        assert!(Float::NaN::<f64>().min(&1f64).is_NaN());
+    }
+
+    #[test]
+    fn test_max() {
+        assert_eq!(1f64.max(&2f64), 2f64);
+        assert_eq!(2f64.max(&1f64), 2f64);
+        assert!(1f64.max(&Float::NaN::<f64>()).is_NaN());
+        assert!(Float::NaN::<f64>().max(&1f64).is_NaN());
+    }
+
+    #[test]
+    fn test_clamp() {
+        assert_eq!(1f64.clamp(&2f64, &4f64), 2f64);
+        assert_eq!(8f64.clamp(&2f64, &4f64), 4f64);
+        assert_eq!(3f64.clamp(&2f64, &4f64), 3f64);
+        assert!(3f64.clamp(&Float::NaN::<f64>(), &4f64).is_NaN());
+        assert!(3f64.clamp(&2f64, &Float::NaN::<f64>()).is_NaN());
+        assert!(Float::NaN::<f64>().clamp(&2f64, &4f64).is_NaN());
+    }
+
+    #[test]
+    fn test_floor() {
+        assert_approx_eq!(1.0f64.floor(), 1.0f64);
+        assert_approx_eq!(1.3f64.floor(), 1.0f64);
+        assert_approx_eq!(1.5f64.floor(), 1.0f64);
+        assert_approx_eq!(1.7f64.floor(), 1.0f64);
+        assert_approx_eq!(0.0f64.floor(), 0.0f64);
+        assert_approx_eq!((-0.0f64).floor(), -0.0f64);
+        assert_approx_eq!((-1.0f64).floor(), -1.0f64);
+        assert_approx_eq!((-1.3f64).floor(), -2.0f64);
+        assert_approx_eq!((-1.5f64).floor(), -2.0f64);
+        assert_approx_eq!((-1.7f64).floor(), -2.0f64);
+    }
+
+    #[test]
+    fn test_ceil() {
+        assert_approx_eq!(1.0f64.ceil(), 1.0f64);
+        assert_approx_eq!(1.3f64.ceil(), 2.0f64);
+        assert_approx_eq!(1.5f64.ceil(), 2.0f64);
+        assert_approx_eq!(1.7f64.ceil(), 2.0f64);
+        assert_approx_eq!(0.0f64.ceil(), 0.0f64);
+        assert_approx_eq!((-0.0f64).ceil(), -0.0f64);
+        assert_approx_eq!((-1.0f64).ceil(), -1.0f64);
+        assert_approx_eq!((-1.3f64).ceil(), -1.0f64);
+        assert_approx_eq!((-1.5f64).ceil(), -1.0f64);
+        assert_approx_eq!((-1.7f64).ceil(), -1.0f64);
+    }
+
+    #[test]
+    fn test_round() {
+        assert_approx_eq!(1.0f64.round(), 1.0f64);
+        assert_approx_eq!(1.3f64.round(), 1.0f64);
+        assert_approx_eq!(1.5f64.round(), 2.0f64);
+        assert_approx_eq!(1.7f64.round(), 2.0f64);
+        assert_approx_eq!(0.0f64.round(), 0.0f64);
+        assert_approx_eq!((-0.0f64).round(), -0.0f64);
+        assert_approx_eq!((-1.0f64).round(), -1.0f64);
+        assert_approx_eq!((-1.3f64).round(), -1.0f64);
+        assert_approx_eq!((-1.5f64).round(), -2.0f64);
+        assert_approx_eq!((-1.7f64).round(), -2.0f64);
+    }
+
+    #[test]
+    fn test_trunc() {
+        assert_approx_eq!(1.0f64.trunc(), 1.0f64);
+        assert_approx_eq!(1.3f64.trunc(), 1.0f64);
+        assert_approx_eq!(1.5f64.trunc(), 1.0f64);
+        assert_approx_eq!(1.7f64.trunc(), 1.0f64);
+        assert_approx_eq!(0.0f64.trunc(), 0.0f64);
+        assert_approx_eq!((-0.0f64).trunc(), -0.0f64);
+        assert_approx_eq!((-1.0f64).trunc(), -1.0f64);
+        assert_approx_eq!((-1.3f64).trunc(), -1.0f64);
+        assert_approx_eq!((-1.5f64).trunc(), -1.0f64);
+        assert_approx_eq!((-1.7f64).trunc(), -1.0f64);
+    }
+
+    #[test]
+    fn test_fract() {
+        assert_approx_eq!(1.0f64.fract(), 0.0f64);
+        assert_approx_eq!(1.3f64.fract(), 0.3f64);
+        assert_approx_eq!(1.5f64.fract(), 0.5f64);
+        assert_approx_eq!(1.7f64.fract(), 0.7f64);
+        assert_approx_eq!(0.0f64.fract(), 0.0f64);
+        assert_approx_eq!((-0.0f64).fract(), -0.0f64);
+        assert_approx_eq!((-1.0f64).fract(), -0.0f64);
+        assert_approx_eq!((-1.3f64).fract(), -0.3f64);
+        assert_approx_eq!((-1.5f64).fract(), -0.5f64);
+        assert_approx_eq!((-1.7f64).fract(), -0.7f64);
+    }
+
+    #[test]
+    fn test_asinh() {
+        assert_eq!(0.0f64.asinh(), 0.0f64);
+        assert_eq!((-0.0f64).asinh(), -0.0f64);
+        assert_eq!(Float::infinity::<f64>().asinh(), Float::infinity::<f64>());
+        assert_eq!(Float::neg_infinity::<f64>().asinh(), Float::neg_infinity::<f64>());
+        assert!(Float::NaN::<f64>().asinh().is_NaN());
+        assert_approx_eq!(2.0f64.asinh(), 1.443635475178810342493276740273105f64);
+        assert_approx_eq!((-2.0f64).asinh(), -1.443635475178810342493276740273105f64);
+    }
+
+    #[test]
+    fn test_acosh() {
+        assert_eq!(1.0f64.acosh(), 0.0f64);
+        assert!(0.999f64.acosh().is_NaN());
+        assert_eq!(Float::infinity::<f64>().acosh(), Float::infinity::<f64>());
+        assert!(Float::neg_infinity::<f64>().acosh().is_NaN());
+        assert!(Float::NaN::<f64>().acosh().is_NaN());
+        assert_approx_eq!(2.0f64.acosh(), 1.31695789692481670862504634730796844f64);
+        assert_approx_eq!(3.0f64.acosh(), 1.76274717403908605046521864995958461f64);
+    }
+
+    #[test]
+    fn test_atanh() {
+        assert_eq!(0.0f64.atanh(), 0.0f64);
+        assert_eq!((-0.0f64).atanh(), -0.0f64);
+        assert_eq!(1.0f64.atanh(), Float::infinity::<f64>());
+        assert_eq!((-1.0f64).atanh(), Float::neg_infinity::<f64>());
+        assert!(2f64.atanh().atanh().is_NaN());
+        assert!((-2f64).atanh().atanh().is_NaN());
+        assert!(Float::infinity::<f64>().atanh().is_NaN());
+        assert!(Float::neg_infinity::<f64>().atanh().is_NaN());
+        assert!(Float::NaN::<f64>().atanh().is_NaN());
+        assert_approx_eq!(0.5f64.atanh(), 0.54930614433405484569762261846126285f64);
+        assert_approx_eq!((-0.5f64).atanh(), -0.54930614433405484569762261846126285f64);
+    }
+
+    #[test]
+    fn test_real_consts() {
+        assert_approx_eq!(Real::two_pi::<f64>(), 2.0 * Real::pi::<f64>());
+        assert_approx_eq!(Real::frac_pi_2::<f64>(), Real::pi::<f64>() / 2f64);
+        assert_approx_eq!(Real::frac_pi_3::<f64>(), Real::pi::<f64>() / 3f64);
+        assert_approx_eq!(Real::frac_pi_4::<f64>(), Real::pi::<f64>() / 4f64);
+        assert_approx_eq!(Real::frac_pi_6::<f64>(), Real::pi::<f64>() / 6f64);
+        assert_approx_eq!(Real::frac_pi_8::<f64>(), Real::pi::<f64>() / 8f64);
+        assert_approx_eq!(Real::frac_1_pi::<f64>(), 1f64 / Real::pi::<f64>());
+        assert_approx_eq!(Real::frac_2_pi::<f64>(), 2f64 / Real::pi::<f64>());
+        assert_approx_eq!(Real::frac_2_sqrtpi::<f64>(), 2f64 / Real::pi::<f64>().sqrt());
+        assert_approx_eq!(Real::sqrt2::<f64>(), 2f64.sqrt());
+        assert_approx_eq!(Real::frac_1_sqrt2::<f64>(), 1f64 / 2f64.sqrt());
+        assert_approx_eq!(Real::log2_e::<f64>(), Real::e::<f64>().log2());
+        assert_approx_eq!(Real::log10_e::<f64>(), Real::e::<f64>().log10());
+        assert_approx_eq!(Real::ln_2::<f64>(), 2f64.ln());
+        assert_approx_eq!(Real::ln_10::<f64>(), 10f64.ln());
+    }
+
+    #[test]
+    pub fn test_abs() {
+        assert_eq!(infinity.abs(), infinity);
+        assert_eq!(1f64.abs(), 1f64);
+        assert_eq!(0f64.abs(), 0f64);
+        assert_eq!((-0f64).abs(), 0f64);
+        assert_eq!((-1f64).abs(), 1f64);
+        assert_eq!(neg_infinity.abs(), infinity);
+        assert_eq!((1f64/neg_infinity).abs(), 0f64);
+        assert!(NaN.abs().is_NaN());
+    }
+
+    #[test]
+    fn test_abs_sub() {
+        assert_eq!((-1f64).abs_sub(&1f64), 0f64);
+        assert_eq!(1f64.abs_sub(&1f64), 0f64);
+        assert_eq!(1f64.abs_sub(&0f64), 1f64);
+        assert_eq!(1f64.abs_sub(&-1f64), 2f64);
+        assert_eq!(neg_infinity.abs_sub(&0f64), 0f64);
+        assert_eq!(infinity.abs_sub(&1f64), infinity);
+        assert_eq!(0f64.abs_sub(&neg_infinity), infinity);
+        assert_eq!(0f64.abs_sub(&infinity), 0f64);
+        assert!(NaN.abs_sub(&-1f64).is_NaN());
+        assert!(1f64.abs_sub(&NaN).is_NaN());
+    }
+
+    #[test]
+    fn test_signum() {
+        assert_eq!(infinity.signum(), 1f64);
+        assert_eq!(1f64.signum(), 1f64);
+        assert_eq!(0f64.signum(), 1f64);
+        assert_eq!((-0f64).signum(), -1f64);
+        assert_eq!((-1f64).signum(), -1f64);
+        assert_eq!(neg_infinity.signum(), -1f64);
+        assert_eq!((1f64/neg_infinity).signum(), -1f64);
+        assert!(NaN.signum().is_NaN());
+    }
+
+    #[test]
+    fn test_is_positive() {
+        assert!(infinity.is_positive());
+        assert!(1f64.is_positive());
+        assert!(0f64.is_positive());
+        assert!(!(-0f64).is_positive());
+        assert!(!(-1f64).is_positive());
+        assert!(!neg_infinity.is_positive());
+        assert!(!(1f64/neg_infinity).is_positive());
+        assert!(!NaN.is_positive());
+    }
+
+    #[test]
+    fn test_is_negative() {
+        assert!(!infinity.is_negative());
+        assert!(!1f64.is_negative());
+        assert!(!0f64.is_negative());
+        assert!((-0f64).is_negative());
+        assert!((-1f64).is_negative());
+        assert!(neg_infinity.is_negative());
+        assert!((1f64/neg_infinity).is_negative());
+        assert!(!NaN.is_negative());
+    }
+
+    #[test]
+    fn test_approx_eq() {
+        assert!(1.0f64.approx_eq(&1f64));
+        assert!(0.9999999f64.approx_eq(&1f64));
+        assert!(1.000001f64.approx_eq_eps(&1f64, &1.0e-5));
+        assert!(1.0000001f64.approx_eq_eps(&1f64, &1.0e-6));
+        assert!(!1.0000001f64.approx_eq_eps(&1f64, &1.0e-7));
+    }
+
+    #[test]
+    fn test_primitive() {
+        assert_eq!(Primitive::bits::<f64>(), sys::size_of::<f64>() * 8);
+        assert_eq!(Primitive::bytes::<f64>(), sys::size_of::<f64>());
+    }
+
+    #[test]
+    fn test_is_normal() {
+        assert!(!Float::NaN::<f64>().is_normal());
+        assert!(!Float::infinity::<f64>().is_normal());
+        assert!(!Float::neg_infinity::<f64>().is_normal());
+        assert!(!Zero::zero::<f64>().is_normal());
+        assert!(!Float::neg_zero::<f64>().is_normal());
+        assert!(1f64.is_normal());
+        assert!(1e-307f64.is_normal());
+        assert!(!1e-308f64.is_normal());
+    }
+
+    #[test]
+    fn test_classify() {
+        assert_eq!(Float::NaN::<f64>().classify(), FPNaN);
+        assert_eq!(Float::infinity::<f64>().classify(), FPInfinite);
+        assert_eq!(Float::neg_infinity::<f64>().classify(), FPInfinite);
+        assert_eq!(Zero::zero::<f64>().classify(), FPZero);
+        assert_eq!(Float::neg_zero::<f64>().classify(), FPZero);
+        assert_eq!(1e-307f64.classify(), FPNormal);
+        assert_eq!(1e-308f64.classify(), FPSubnormal);
+    }
+
+    #[test]
+    fn test_ldexp() {
+        // We have to use from_str until base-2 exponents
+        // are supported in floating-point literals
+        let f1: f64 = from_str_hex("1p-123").unwrap();
+        let f2: f64 = from_str_hex("1p-111").unwrap();
+        assert_eq!(Float::ldexp(1f64, -123), f1);
+        assert_eq!(Float::ldexp(1f64, -111), f2);
+
+        assert_eq!(Float::ldexp(0f64, -123), 0f64);
+        assert_eq!(Float::ldexp(-0f64, -123), -0f64);
+        assert_eq!(Float::ldexp(Float::infinity::<f64>(), -123),
+                   Float::infinity::<f64>());
+        assert_eq!(Float::ldexp(Float::neg_infinity::<f64>(), -123),
+                   Float::neg_infinity::<f64>());
+        assert!(Float::ldexp(Float::NaN::<f64>(), -123).is_NaN());
+    }
+
+    #[test]
+    fn test_frexp() {
+        // We have to use from_str until base-2 exponents
+        // are supported in floating-point literals
+        let f1: f64 = from_str_hex("1p-123").unwrap();
+        let f2: f64 = from_str_hex("1p-111").unwrap();
+        let (x1, exp1) = f1.frexp();
+        let (x2, exp2) = f2.frexp();
+        assert_eq!((x1, exp1), (0.5f64, -122));
+        assert_eq!((x2, exp2), (0.5f64, -110));
+        assert_eq!(Float::ldexp(x1, exp1), f1);
+        assert_eq!(Float::ldexp(x2, exp2), f2);
+
+        assert_eq!(0f64.frexp(), (0f64, 0));
+        assert_eq!((-0f64).frexp(), (-0f64, 0));
+        assert_eq!(match Float::infinity::<f64>().frexp() { (x, _) => x },
+                   Float::infinity::<f64>())
+        assert_eq!(match Float::neg_infinity::<f64>().frexp() { (x, _) => x },
+                   Float::neg_infinity::<f64>())
+        assert!(match Float::NaN::<f64>().frexp() { (x, _) => x.is_NaN() })
+    }
+}
diff --git a/src/libstd/num/float.rs b/src/libstd/num/float.rs
new file mode 100644
index 00000000000..681aafaab88
--- /dev/null
+++ b/src/libstd/num/float.rs
@@ -0,0 +1,1387 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations and constants for `float`
+
+// Even though this module exports everything defined in it,
+// because it contains re-exports, we also have to explicitly
+// export locally defined things. That's a bit annoying.
+
+
+// export when m_float == c_double
+
+
+// PORT this must match in width according to architecture
+
+use libc::c_int;
+use num::{Zero, One, strconv};
+use num::FPCategory;
+use prelude::*;
+
+pub use f64::{add, sub, mul, div, rem, lt, le, eq, ne, ge, gt};
+pub use f64::{acos, asin, atan2, cbrt, ceil, copysign, cosh, floor};
+pub use f64::{erf, erfc, exp, exp_m1, exp2, abs_sub};
+pub use f64::{mul_add, fmax, fmin, next_after, frexp, hypot, ldexp};
+pub use f64::{lgamma, ln, log_radix, ln_1p, log10, log2, ilog_radix};
+pub use f64::{modf, pow, powi, round, sinh, tanh, tgamma, trunc};
+pub use f64::{j0, j1, jn, y0, y1, yn};
+
+pub static NaN: float = 0.0/0.0;
+
+pub static infinity: float = 1.0/0.0;
+
+pub static neg_infinity: float = -1.0/0.0;
+
+/* Module: consts */
+pub mod consts {
+    // FIXME (requires Issue #1433 to fix): replace with mathematical
+    // staticants from cmath.
+    /// Archimedes' staticant
+    pub static pi: float = 3.14159265358979323846264338327950288;
+
+    /// pi/2.0
+    pub static frac_pi_2: float = 1.57079632679489661923132169163975144;
+
+    /// pi/4.0
+    pub static frac_pi_4: float = 0.785398163397448309615660845819875721;
+
+    /// 1.0/pi
+    pub static frac_1_pi: float = 0.318309886183790671537767526745028724;
+
+    /// 2.0/pi
+    pub static frac_2_pi: float = 0.636619772367581343075535053490057448;
+
+    /// 2.0/sqrt(pi)
+    pub static frac_2_sqrtpi: float = 1.12837916709551257389615890312154517;
+
+    /// sqrt(2.0)
+    pub static sqrt2: float = 1.41421356237309504880168872420969808;
+
+    /// 1.0/sqrt(2.0)
+    pub static frac_1_sqrt2: float = 0.707106781186547524400844362104849039;
+
+    /// Euler's number
+    pub static e: float = 2.71828182845904523536028747135266250;
+
+    /// log2(e)
+    pub static log2_e: float = 1.44269504088896340735992468100189214;
+
+    /// log10(e)
+    pub static log10_e: float = 0.434294481903251827651128918916605082;
+
+    /// ln(2.0)
+    pub static ln_2: float = 0.693147180559945309417232121458176568;
+
+    /// ln(10.0)
+    pub static ln_10: float = 2.30258509299404568401799145468436421;
+}
+
+//
+// Section: String Conversions
+//
+
+///
+/// Converts a float to a string
+///
+/// # Arguments
+///
+/// * num - The float value
+///
+#[inline(always)]
+pub fn to_str(num: float) -> ~str {
+    let (r, _) = strconv::to_str_common(
+        &num, 10u, true, strconv::SignNeg, strconv::DigAll);
+    r
+}
+
+///
+/// Converts a float to a string in hexadecimal format
+///
+/// # Arguments
+///
+/// * num - The float value
+///
+#[inline(always)]
+pub fn to_str_hex(num: float) -> ~str {
+    let (r, _) = strconv::to_str_common(
+        &num, 16u, true, strconv::SignNeg, strconv::DigAll);
+    r
+}
+
+///
+/// Converts a float to a string in a given radix
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * radix - The base to use
+///
+/// # Failure
+///
+/// Fails if called on a special value like `inf`, `-inf` or `NaN` due to
+/// possible misinterpretation of the result at higher bases. If those values
+/// are expected, use `to_str_radix_special()` instead.
+///
+#[inline(always)]
+pub fn to_str_radix(num: float, radix: uint) -> ~str {
+    let (r, special) = strconv::to_str_common(
+        &num, radix, true, strconv::SignNeg, strconv::DigAll);
+    if special { fail!("number has a special value, \
+                         try to_str_radix_special() if those are expected") }
+    r
+}
+
+///
+/// Converts a float to a string in a given radix, and a flag indicating
+/// whether it's a special value
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * radix - The base to use
+///
+#[inline(always)]
+pub fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) {
+    strconv::to_str_common(&num, radix, true,
+                           strconv::SignNeg, strconv::DigAll)
+}
+
+///
+/// Converts a float to a string with exactly the number of
+/// provided significant digits
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * digits - The number of significant digits
+///
+#[inline(always)]
+pub fn to_str_exact(num: float, digits: uint) -> ~str {
+    let (r, _) = strconv::to_str_common(
+        &num, 10u, true, strconv::SignNeg, strconv::DigExact(digits));
+    r
+}
+
+///
+/// Converts a float to a string with a maximum number of
+/// significant digits
+///
+/// # Arguments
+///
+/// * num - The float value
+/// * digits - The number of significant digits
+///
+#[inline(always)]
+pub fn to_str_digits(num: float, digits: uint) -> ~str {
+    let (r, _) = strconv::to_str_common(
+        &num, 10u, true, strconv::SignNeg, strconv::DigMax(digits));
+    r
+}
+
+impl to_str::ToStr for float {
+    #[inline(always)]
+    fn to_str(&self) -> ~str { to_str_digits(*self, 8) }
+}
+
+impl num::ToStrRadix for float {
+    #[inline(always)]
+    fn to_str_radix(&self, radix: uint) -> ~str {
+        to_str_radix(*self, radix)
+    }
+}
+
+///
+/// Convert a string in base 10 to a float.
+/// Accepts a optional decimal exponent.
+///
+/// This function accepts strings such as
+///
+/// * '3.14'
+/// * '+3.14', equivalent to '3.14'
+/// * '-3.14'
+/// * '2.5E10', or equivalently, '2.5e10'
+/// * '2.5E-10'
+/// * '.' (understood as 0)
+/// * '5.'
+/// * '.5', or, equivalently,  '0.5'
+/// * '+inf', 'inf', '-inf', 'NaN'
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number.  Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `num`.
+///
+#[inline(always)]
+pub fn from_str(num: &str) -> Option<float> {
+    strconv::from_str_common(num, 10u, true, true, true,
+                             strconv::ExpDec, false, false)
+}
+
+///
+/// Convert a string in base 16 to a float.
+/// Accepts a optional binary exponent.
+///
+/// This function accepts strings such as
+///
+/// * 'a4.fe'
+/// * '+a4.fe', equivalent to 'a4.fe'
+/// * '-a4.fe'
+/// * '2b.aP128', or equivalently, '2b.ap128'
+/// * '2b.aP-128'
+/// * '.' (understood as 0)
+/// * 'c.'
+/// * '.c', or, equivalently,  '0.c'
+/// * '+inf', 'inf', '-inf', 'NaN'
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number.  Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `[num]`.
+///
+#[inline(always)]
+pub fn from_str_hex(num: &str) -> Option<float> {
+    strconv::from_str_common(num, 16u, true, true, true,
+                             strconv::ExpBin, false, false)
+}
+
+///
+/// Convert a string in an given base to a float.
+///
+/// Due to possible conflicts, this function does **not** accept
+/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
+/// does it recognize exponents of any kind.
+///
+/// Leading and trailing whitespace represent an error.
+///
+/// # Arguments
+///
+/// * num - A string
+/// * radix - The base to use. Must lie in the range [2 .. 36]
+///
+/// # Return value
+///
+/// `none` if the string did not represent a valid number. Otherwise,
+/// `Some(n)` where `n` is the floating-point number represented by `num`.
+///
+#[inline(always)]
+pub fn from_str_radix(num: &str, radix: uint) -> Option<float> {
+    strconv::from_str_common(num, radix, true, true, false,
+                             strconv::ExpNone, false, false)
+}
+
+impl FromStr for float {
+    #[inline(always)]
+    fn from_str(val: &str) -> Option<float> { from_str(val) }
+}
+
+impl num::FromStrRadix for float {
+    #[inline(always)]
+    fn from_str_radix(val: &str, radix: uint) -> Option<float> {
+        from_str_radix(val, radix)
+    }
+}
+
+//
+// Section: Arithmetics
+//
+
+///
+/// Compute the exponentiation of an integer by another integer as a float
+///
+/// # Arguments
+///
+/// * x - The base
+/// * pow - The exponent
+///
+/// # Return value
+///
+/// `NaN` if both `x` and `pow` are `0u`, otherwise `x^pow`
+///
+pub fn pow_with_uint(base: uint, pow: uint) -> float {
+    if base == 0u {
+        if pow == 0u {
+            return NaN as float;
+        }
+        return 0.;
+    }
+    let mut my_pow     = pow;
+    let mut total      = 1f;
+    let mut multiplier = base as float;
+    while (my_pow > 0u) {
+        if my_pow % 2u == 1u {
+            total = total * multiplier;
+        }
+        my_pow     /= 2u;
+        multiplier *= multiplier;
+    }
+    return total;
+}
+
+#[inline(always)]
+pub fn abs(x: float) -> float {
+    f64::abs(x as f64) as float
+}
+#[inline(always)]
+pub fn sqrt(x: float) -> float {
+    f64::sqrt(x as f64) as float
+}
+#[inline(always)]
+pub fn atan(x: float) -> float {
+    f64::atan(x as f64) as float
+}
+#[inline(always)]
+pub fn sin(x: float) -> float {
+    f64::sin(x as f64) as float
+}
+#[inline(always)]
+pub fn cos(x: float) -> float {
+    f64::cos(x as f64) as float
+}
+#[inline(always)]
+pub fn tan(x: float) -> float {
+    f64::tan(x as f64) as float
+}
+
+impl Num for float {}
+
+#[cfg(not(test))]
+impl Eq for float {
+    #[inline(always)]
+    fn eq(&self, other: &float) -> bool { (*self) == (*other) }
+    #[inline(always)]
+    fn ne(&self, other: &float) -> bool { (*self) != (*other) }
+}
+
+#[cfg(not(test))]
+impl ApproxEq<float> for float {
+    #[inline(always)]
+    fn approx_epsilon() -> float { 1.0e-6 }
+
+    #[inline(always)]
+    fn approx_eq(&self, other: &float) -> bool {
+        self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<float, float>())
+    }
+
+    #[inline(always)]
+    fn approx_eq_eps(&self, other: &float, approx_epsilon: &float) -> bool {
+        (*self - *other).abs() < *approx_epsilon
+    }
+}
+
+#[cfg(not(test))]
+impl Ord for float {
+    #[inline(always)]
+    fn lt(&self, other: &float) -> bool { (*self) < (*other) }
+    #[inline(always)]
+    fn le(&self, other: &float) -> bool { (*self) <= (*other) }
+    #[inline(always)]
+    fn ge(&self, other: &float) -> bool { (*self) >= (*other) }
+    #[inline(always)]
+    fn gt(&self, other: &float) -> bool { (*self) > (*other) }
+}
+
+impl Orderable for float {
+    /// Returns `NaN` if either of the numbers are `NaN`.
+    #[inline(always)]
+    fn min(&self, other: &float) -> float {
+        (*self as f64).min(&(*other as f64)) as float
+    }
+
+    /// Returns `NaN` if either of the numbers are `NaN`.
+    #[inline(always)]
+    fn max(&self, other: &float) -> float {
+        (*self as f64).max(&(*other as f64)) as float
+    }
+
+    /// Returns the number constrained within the range `mn <= self <= mx`.
+    /// If any of the numbers are `NaN` then `NaN` is returned.
+    #[inline(always)]
+    fn clamp(&self, mn: &float, mx: &float) -> float {
+        (*self as f64).clamp(&(*mn as f64), &(*mx as f64)) as float
+    }
+}
+
+impl Zero for float {
+    #[inline(always)]
+    fn zero() -> float { 0.0 }
+
+    /// Returns true if the number is equal to either `0.0` or `-0.0`
+    #[inline(always)]
+    fn is_zero(&self) -> bool { *self == 0.0 || *self == -0.0 }
+}
+
+impl One for float {
+    #[inline(always)]
+    fn one() -> float { 1.0 }
+}
+
+impl Round for float {
+    /// Round half-way cases toward `neg_infinity`
+    #[inline(always)]
+    fn floor(&self) -> float { floor(*self as f64) as float }
+
+    /// Round half-way cases toward `infinity`
+    #[inline(always)]
+    fn ceil(&self) -> float { ceil(*self as f64) as float }
+
+    /// Round half-way cases away from `0.0`
+    #[inline(always)]
+    fn round(&self) -> float { round(*self as f64) as float }
+
+    /// The integer part of the number (rounds towards `0.0`)
+    #[inline(always)]
+    fn trunc(&self) -> float { trunc(*self as f64) as float }
+
+    ///
+    /// The fractional part of the number, satisfying:
+    ///
+    /// ~~~
+    /// assert!(x == trunc(x) + fract(x))
+    /// ~~~
+    ///
+    #[inline(always)]
+    fn fract(&self) -> float { *self - self.trunc() }
+}
+
+impl Fractional for float {
+    /// The reciprocal (multiplicative inverse) of the number
+    #[inline(always)]
+    fn recip(&self) -> float { 1.0 / *self }
+}
+
+impl Algebraic for float {
+    #[inline(always)]
+    fn pow(&self, n: float) -> float {
+        (*self as f64).pow(n as f64) as float
+    }
+
+    #[inline(always)]
+    fn sqrt(&self) -> float {
+        (*self as f64).sqrt() as float
+    }
+
+    #[inline(always)]
+    fn rsqrt(&self) -> float {
+        (*self as f64).rsqrt() as float
+    }
+
+    #[inline(always)]
+    fn cbrt(&self) -> float {
+        (*self as f64).cbrt() as float
+    }
+
+    #[inline(always)]
+    fn hypot(&self, other: float) -> float {
+        (*self as f64).hypot(other as f64) as float
+    }
+}
+
+impl Trigonometric for float {
+    #[inline(always)]
+    fn sin(&self) -> float {
+        (*self as f64).sin() as float
+    }
+
+    #[inline(always)]
+    fn cos(&self) -> float {
+        (*self as f64).cos() as float
+    }
+
+    #[inline(always)]
+    fn tan(&self) -> float {
+        (*self as f64).tan() as float
+    }
+
+    #[inline(always)]
+    fn asin(&self) -> float {
+        (*self as f64).asin() as float
+    }
+
+    #[inline(always)]
+    fn acos(&self) -> float {
+        (*self as f64).acos() as float
+    }
+
+    #[inline(always)]
+    fn atan(&self) -> float {
+        (*self as f64).atan() as float
+    }
+
+    #[inline(always)]
+    fn atan2(&self, other: float) -> float {
+        (*self as f64).atan2(other as f64) as float
+    }
+
+    /// Simultaneously computes the sine and cosine of the number
+    #[inline(always)]
+    fn sin_cos(&self) -> (float, float) {
+        match (*self as f64).sin_cos() {
+            (s, c) => (s as float, c as float)
+        }
+    }
+}
+
+impl Exponential for float {
+    /// Returns the exponential of the number
+    #[inline(always)]
+    fn exp(&self) -> float {
+        (*self as f64).exp() as float
+    }
+
+    /// Returns 2 raised to the power of the number
+    #[inline(always)]
+    fn exp2(&self) -> float {
+        (*self as f64).exp2() as float
+    }
+
+    /// Returns the natural logarithm of the number
+    #[inline(always)]
+    fn ln(&self) -> float {
+        (*self as f64).ln() as float
+    }
+
+    /// Returns the logarithm of the number with respect to an arbitrary base
+    #[inline(always)]
+    fn log(&self, base: float) -> float {
+        (*self as f64).log(base as f64) as float
+    }
+
+    /// Returns the base 2 logarithm of the number
+    #[inline(always)]
+    fn log2(&self) -> float {
+        (*self as f64).log2() as float
+    }
+
+    /// Returns the base 10 logarithm of the number
+    #[inline(always)]
+    fn log10(&self) -> float {
+        (*self as f64).log10() as float
+    }
+}
+
+impl Hyperbolic for float {
+    #[inline(always)]
+    fn sinh(&self) -> float {
+        (*self as f64).sinh() as float
+    }
+
+    #[inline(always)]
+    fn cosh(&self) -> float {
+        (*self as f64).cosh() as float
+    }
+
+    #[inline(always)]
+    fn tanh(&self) -> float {
+        (*self as f64).tanh() as float
+    }
+
+    ///
+    /// Inverse hyperbolic sine
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic sine of `self` will be returned
+    /// - `self` if `self` is `0.0`, `-0.0`, `infinity`, or `neg_infinity`
+    /// - `NaN` if `self` is `NaN`
+    ///
+    #[inline(always)]
+    fn asinh(&self) -> float {
+        (*self as f64).asinh() as float
+    }
+
+    ///
+    /// Inverse hyperbolic cosine
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic cosine of `self` will be returned
+    /// - `infinity` if `self` is `infinity`
+    /// - `NaN` if `self` is `NaN` or `self < 1.0` (including `neg_infinity`)
+    ///
+    #[inline(always)]
+    fn acosh(&self) -> float {
+        (*self as f64).acosh() as float
+    }
+
+    ///
+    /// Inverse hyperbolic tangent
+    ///
+    /// # Returns
+    ///
+    /// - on success, the inverse hyperbolic tangent of `self` will be returned
+    /// - `self` if `self` is `0.0` or `-0.0`
+    /// - `infinity` if `self` is `1.0`
+    /// - `neg_infinity` if `self` is `-1.0`
+    /// - `NaN` if the `self` is `NaN` or outside the domain of `-1.0 <= self <= 1.0`
+    ///   (including `infinity` and `neg_infinity`)
+    ///
+    #[inline(always)]
+    fn atanh(&self) -> float {
+        (*self as f64).atanh() as float
+    }
+}
+
+impl Real for float {
+    /// Archimedes' constant
+    #[inline(always)]
+    fn pi() -> float { 3.14159265358979323846264338327950288 }
+
+    /// 2.0 * pi
+    #[inline(always)]
+    fn two_pi() -> float { 6.28318530717958647692528676655900576 }
+
+    /// pi / 2.0
+    #[inline(always)]
+    fn frac_pi_2() -> float { 1.57079632679489661923132169163975144 }
+
+    /// pi / 3.0
+    #[inline(always)]
+    fn frac_pi_3() -> float { 1.04719755119659774615421446109316763 }
+
+    /// pi / 4.0
+    #[inline(always)]
+    fn frac_pi_4() -> float { 0.785398163397448309615660845819875721 }
+
+    /// pi / 6.0
+    #[inline(always)]
+    fn frac_pi_6() -> float { 0.52359877559829887307710723054658381 }
+
+    /// pi / 8.0
+    #[inline(always)]
+    fn frac_pi_8() -> float { 0.39269908169872415480783042290993786 }
+
+    /// 1.0 / pi
+    #[inline(always)]
+    fn frac_1_pi() -> float { 0.318309886183790671537767526745028724 }
+
+    /// 2.0 / pi
+    #[inline(always)]
+    fn frac_2_pi() -> float { 0.636619772367581343075535053490057448 }
+
+    /// 2 .0/ sqrt(pi)
+    #[inline(always)]
+    fn frac_2_sqrtpi() -> float { 1.12837916709551257389615890312154517 }
+
+    /// sqrt(2.0)
+    #[inline(always)]
+    fn sqrt2() -> float { 1.41421356237309504880168872420969808 }
+
+    /// 1.0 / sqrt(2.0)
+    #[inline(always)]
+    fn frac_1_sqrt2() -> float { 0.707106781186547524400844362104849039 }
+
+    /// Euler's number
+    #[inline(always)]
+    fn e() -> float { 2.71828182845904523536028747135266250 }
+
+    /// log2(e)
+    #[inline(always)]
+    fn log2_e() -> float { 1.44269504088896340735992468100189214 }
+
+    /// log10(e)
+    #[inline(always)]
+    fn log10_e() -> float { 0.434294481903251827651128918916605082 }
+
+    /// ln(2.0)
+    #[inline(always)]
+    fn ln_2() -> float { 0.693147180559945309417232121458176568 }
+
+    /// ln(10.0)
+    #[inline(always)]
+    fn ln_10() -> float { 2.30258509299404568401799145468436421 }
+
+    /// Converts to degrees, assuming the number is in radians
+    #[inline(always)]
+    fn to_degrees(&self) -> float { (*self as f64).to_degrees() as float }
+
+    /// Converts to radians, assuming the number is in degrees
+    #[inline(always)]
+    fn to_radians(&self) -> float { (*self as f64).to_radians() as float }
+}
+
+impl RealExt for float {
+    #[inline(always)]
+    fn lgamma(&self) -> (int, float) {
+        let mut sign = 0;
+        let result = lgamma(*self as f64, &mut sign);
+        (sign as int, result as float)
+    }
+
+    #[inline(always)]
+    fn tgamma(&self) -> float { tgamma(*self as f64) as float }
+
+    #[inline(always)]
+    fn j0(&self) -> float { j0(*self as f64) as float }
+
+    #[inline(always)]
+    fn j1(&self) -> float { j1(*self as f64) as float }
+
+    #[inline(always)]
+    fn jn(&self, n: int) -> float { jn(n as c_int, *self as f64) as float }
+
+    #[inline(always)]
+    fn y0(&self) -> float { y0(*self as f64) as float }
+
+    #[inline(always)]
+    fn y1(&self) -> float { y1(*self as f64) as float }
+
+    #[inline(always)]
+    fn yn(&self, n: int) -> float { yn(n as c_int, *self as f64) as float }
+}
+
+#[cfg(not(test))]
+impl Add<float,float> for float {
+    #[inline(always)]
+    fn add(&self, other: &float) -> float { *self + *other }
+}
+
+#[cfg(not(test))]
+impl Sub<float,float> for float {
+    #[inline(always)]
+    fn sub(&self, other: &float) -> float { *self - *other }
+}
+
+#[cfg(not(test))]
+impl Mul<float,float> for float {
+    #[inline(always)]
+    fn mul(&self, other: &float) -> float { *self * *other }
+}
+
+#[cfg(not(test))]
+impl Div<float,float> for float {
+    #[inline(always)]
+    fn div(&self, other: &float) -> float { *self / *other }
+}
+
+#[cfg(not(test))]
+impl Rem<float,float> for float {
+    #[inline(always)]
+    fn rem(&self, other: &float) -> float { *self % *other }
+}
+#[cfg(not(test))]
+impl Neg<float> for float {
+    #[inline(always)]
+    fn neg(&self) -> float { -*self }
+}
+
+impl Signed for float {
+    /// Computes the absolute value. Returns `NaN` if the number is `NaN`.
+    #[inline(always)]
+    fn abs(&self) -> float { abs(*self) }
+
+    ///
+    /// The positive difference of two numbers. Returns `0.0` if the number is less than or
+    /// equal to `other`, otherwise the difference between`self` and `other` is returned.
+    ///
+    #[inline(always)]
+    fn abs_sub(&self, other: &float) -> float {
+        (*self as f64).abs_sub(&(*other as f64)) as float
+    }
+
+    ///
+    /// # Returns
+    ///
+    /// - `1.0` if the number is positive, `+0.0` or `infinity`
+    /// - `-1.0` if the number is negative, `-0.0` or `neg_infinity`
+    /// - `NaN` if the number is NaN
+    ///
+    #[inline(always)]
+    fn signum(&self) -> float {
+        if self.is_NaN() { NaN } else { f64::copysign(1.0, *self as f64) as float }
+    }
+
+    /// Returns `true` if the number is positive, including `+0.0` and `infinity`
+    #[inline(always)]
+    fn is_positive(&self) -> bool { *self > 0.0 || (1.0 / *self) == infinity }
+
+    /// Returns `true` if the number is negative, including `-0.0` and `neg_infinity`
+    #[inline(always)]
+    fn is_negative(&self) -> bool { *self < 0.0 || (1.0 / *self) == neg_infinity }
+}
+
+impl Bounded for float {
+    #[inline(always)]
+    fn min_value() -> float { Bounded::min_value::<f64>() as float }
+
+    #[inline(always)]
+    fn max_value() -> float { Bounded::max_value::<f64>() as float }
+}
+
+impl Primitive for float {
+    #[inline(always)]
+    fn bits() -> uint { Primitive::bits::<f64>() }
+
+    #[inline(always)]
+    fn bytes() -> uint { Primitive::bytes::<f64>() }
+}
+
+impl Float for float {
+    #[inline(always)]
+    fn NaN() -> float { Float::NaN::<f64>() as float }
+
+    #[inline(always)]
+    fn infinity() -> float { Float::infinity::<f64>() as float }
+
+    #[inline(always)]
+    fn neg_infinity() -> float { Float::neg_infinity::<f64>() as float }
+
+    #[inline(always)]
+    fn neg_zero() -> float { Float::neg_zero::<f64>() as float }
+
+    /// Returns `true` if the number is NaN
+    #[inline(always)]
+    fn is_NaN(&self) -> bool { (*self as f64).is_NaN() }
+
+    /// Returns `true` if the number is infinite
+    #[inline(always)]
+    fn is_infinite(&self) -> bool { (*self as f64).is_infinite() }
+
+    /// Returns `true` if the number is neither infinite or NaN
+    #[inline(always)]
+    fn is_finite(&self) -> bool { (*self as f64).is_finite() }
+
+    /// Returns `true` if the number is neither zero, infinite, subnormal or NaN
+    #[inline(always)]
+    fn is_normal(&self) -> bool { (*self as f64).is_normal() }
+
+    /// Returns the floating point category of the number. If only one property is going to
+    /// be tested, it is generally faster to use the specific predicate instead.
+    #[inline(always)]
+    fn classify(&self) -> FPCategory { (*self as f64).classify() }
+
+    #[inline(always)]
+    fn mantissa_digits() -> uint { Float::mantissa_digits::<f64>() }
+
+    #[inline(always)]
+    fn digits() -> uint { Float::digits::<f64>() }
+
+    #[inline(always)]
+    fn epsilon() -> float { Float::epsilon::<f64>() as float }
+
+    #[inline(always)]
+    fn min_exp() -> int { Float::min_exp::<f64>() }
+
+    #[inline(always)]
+    fn max_exp() -> int { Float::max_exp::<f64>() }
+
+    #[inline(always)]
+    fn min_10_exp() -> int { Float::min_10_exp::<f64>() }
+
+    #[inline(always)]
+    fn max_10_exp() -> int { Float::max_10_exp::<f64>() }
+
+    /// Constructs a floating point number by multiplying `x` by 2 raised to the power of `exp`
+    #[inline(always)]
+    fn ldexp(x: float, exp: int) -> float {
+        Float::ldexp(x as f64, exp) as float
+    }
+
+    ///
+    /// Breaks the number into a normalized fraction and a base-2 exponent, satisfying:
+    ///
+    /// - `self = x * pow(2, exp)`
+    /// - `0.5 <= abs(x) < 1.0`
+    ///
+    #[inline(always)]
+    fn frexp(&self) -> (float, int) {
+        match (*self as f64).frexp() {
+            (x, exp) => (x as float, exp)
+        }
+    }
+
+    ///
+    /// Returns the exponential of the number, minus `1`, in a way that is accurate
+    /// even if the number is close to zero
+    ///
+    #[inline(always)]
+    fn exp_m1(&self) -> float {
+        (*self as f64).exp_m1() as float
+    }
+
+    ///
+    /// Returns the natural logarithm of the number plus `1` (`ln(1+n)`) more accurately
+    /// than if the operations were performed separately
+    ///
+    #[inline(always)]
+    fn ln_1p(&self) -> float {
+        (*self as f64).ln_1p() as float
+    }
+
+    ///
+    /// Fused multiply-add. Computes `(self * a) + b` with only one rounding error. This
+    /// produces a more accurate result with better performance than a separate multiplication
+    /// operation followed by an add.
+    ///
+    #[inline(always)]
+    fn mul_add(&self, a: float, b: float) -> float {
+        mul_add(*self as f64, a as f64, b as f64) as float
+    }
+
+    /// Returns the next representable floating-point value in the direction of `other`
+    #[inline(always)]
+    fn next_after(&self, other: float) -> float {
+        next_after(*self as f64, other as f64) as float
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use num::*;
+    use super::*;
+    use prelude::*;
+
+    #[test]
+    fn test_num() {
+        num::test_num(10f, 2f);
+    }
+
+    #[test]
+    fn test_min() {
+        assert_eq!(1f.min(&2f), 1f);
+        assert_eq!(2f.min(&1f), 1f);
+    }
+
+    #[test]
+    fn test_max() {
+        assert_eq!(1f.max(&2f), 2f);
+        assert_eq!(2f.max(&1f), 2f);
+    }
+
+    #[test]
+    fn test_clamp() {
+        assert_eq!(1f.clamp(&2f, &4f), 2f);
+        assert_eq!(8f.clamp(&2f, &4f), 4f);
+        assert_eq!(3f.clamp(&2f, &4f), 3f);
+        assert!(3f.clamp(&Float::NaN::<float>(), &4f).is_NaN());
+        assert!(3f.clamp(&2f, &Float::NaN::<float>()).is_NaN());
+        assert!(Float::NaN::<float>().clamp(&2f, &4f).is_NaN());
+    }
+
+    #[test]
+    fn test_floor() {
+        assert_approx_eq!(1.0f.floor(), 1.0f);
+        assert_approx_eq!(1.3f.floor(), 1.0f);
+        assert_approx_eq!(1.5f.floor(), 1.0f);
+        assert_approx_eq!(1.7f.floor(), 1.0f);
+        assert_approx_eq!(0.0f.floor(), 0.0f);
+        assert_approx_eq!((-0.0f).floor(), -0.0f);
+        assert_approx_eq!((-1.0f).floor(), -1.0f);
+        assert_approx_eq!((-1.3f).floor(), -2.0f);
+        assert_approx_eq!((-1.5f).floor(), -2.0f);
+        assert_approx_eq!((-1.7f).floor(), -2.0f);
+    }
+
+    #[test]
+    fn test_ceil() {
+        assert_approx_eq!(1.0f.ceil(), 1.0f);
+        assert_approx_eq!(1.3f.ceil(), 2.0f);
+        assert_approx_eq!(1.5f.ceil(), 2.0f);
+        assert_approx_eq!(1.7f.ceil(), 2.0f);
+        assert_approx_eq!(0.0f.ceil(), 0.0f);
+        assert_approx_eq!((-0.0f).ceil(), -0.0f);
+        assert_approx_eq!((-1.0f).ceil(), -1.0f);
+        assert_approx_eq!((-1.3f).ceil(), -1.0f);
+        assert_approx_eq!((-1.5f).ceil(), -1.0f);
+        assert_approx_eq!((-1.7f).ceil(), -1.0f);
+    }
+
+    #[test]
+    fn test_round() {
+        assert_approx_eq!(1.0f.round(), 1.0f);
+        assert_approx_eq!(1.3f.round(), 1.0f);
+        assert_approx_eq!(1.5f.round(), 2.0f);
+        assert_approx_eq!(1.7f.round(), 2.0f);
+        assert_approx_eq!(0.0f.round(), 0.0f);
+        assert_approx_eq!((-0.0f).round(), -0.0f);
+        assert_approx_eq!((-1.0f).round(), -1.0f);
+        assert_approx_eq!((-1.3f).round(), -1.0f);
+        assert_approx_eq!((-1.5f).round(), -2.0f);
+        assert_approx_eq!((-1.7f).round(), -2.0f);
+    }
+
+    #[test]
+    fn test_trunc() {
+        assert_approx_eq!(1.0f.trunc(), 1.0f);
+        assert_approx_eq!(1.3f.trunc(), 1.0f);
+        assert_approx_eq!(1.5f.trunc(), 1.0f);
+        assert_approx_eq!(1.7f.trunc(), 1.0f);
+        assert_approx_eq!(0.0f.trunc(), 0.0f);
+        assert_approx_eq!((-0.0f).trunc(), -0.0f);
+        assert_approx_eq!((-1.0f).trunc(), -1.0f);
+        assert_approx_eq!((-1.3f).trunc(), -1.0f);
+        assert_approx_eq!((-1.5f).trunc(), -1.0f);
+        assert_approx_eq!((-1.7f).trunc(), -1.0f);
+    }
+
+    #[test]
+    fn test_fract() {
+        assert_approx_eq!(1.0f.fract(), 0.0f);
+        assert_approx_eq!(1.3f.fract(), 0.3f);
+        assert_approx_eq!(1.5f.fract(), 0.5f);
+        assert_approx_eq!(1.7f.fract(), 0.7f);
+        assert_approx_eq!(0.0f.fract(), 0.0f);
+        assert_approx_eq!((-0.0f).fract(), -0.0f);
+        assert_approx_eq!((-1.0f).fract(), -0.0f);
+        assert_approx_eq!((-1.3f).fract(), -0.3f);
+        assert_approx_eq!((-1.5f).fract(), -0.5f);
+        assert_approx_eq!((-1.7f).fract(), -0.7f);
+    }
+
+    #[test]
+    fn test_asinh() {
+        assert_eq!(0.0f.asinh(), 0.0f);
+        assert_eq!((-0.0f).asinh(), -0.0f);
+        assert_eq!(Float::infinity::<float>().asinh(), Float::infinity::<float>());
+        assert_eq!(Float::neg_infinity::<float>().asinh(), Float::neg_infinity::<float>());
+        assert!(Float::NaN::<float>().asinh().is_NaN());
+        assert_approx_eq!(2.0f.asinh(), 1.443635475178810342493276740273105f);
+        assert_approx_eq!((-2.0f).asinh(), -1.443635475178810342493276740273105f);
+    }
+
+    #[test]
+    fn test_acosh() {
+        assert_eq!(1.0f.acosh(), 0.0f);
+        assert!(0.999f.acosh().is_NaN());
+        assert_eq!(Float::infinity::<float>().acosh(), Float::infinity::<float>());
+        assert!(Float::neg_infinity::<float>().acosh().is_NaN());
+        assert!(Float::NaN::<float>().acosh().is_NaN());
+        assert_approx_eq!(2.0f.acosh(), 1.31695789692481670862504634730796844f);
+        assert_approx_eq!(3.0f.acosh(), 1.76274717403908605046521864995958461f);
+    }
+
+    #[test]
+    fn test_atanh() {
+        assert_eq!(0.0f.atanh(), 0.0f);
+        assert_eq!((-0.0f).atanh(), -0.0f);
+        assert_eq!(1.0f.atanh(), Float::infinity::<float>());
+        assert_eq!((-1.0f).atanh(), Float::neg_infinity::<float>());
+        assert!(2f64.atanh().atanh().is_NaN());
+        assert!((-2f64).atanh().atanh().is_NaN());
+        assert!(Float::infinity::<f64>().atanh().is_NaN());
+        assert!(Float::neg_infinity::<f64>().atanh().is_NaN());
+        assert!(Float::NaN::<float>().atanh().is_NaN());
+        assert_approx_eq!(0.5f.atanh(), 0.54930614433405484569762261846126285f);
+        assert_approx_eq!((-0.5f).atanh(), -0.54930614433405484569762261846126285f);
+    }
+
+    #[test]
+    fn test_real_consts() {
+        assert_approx_eq!(Real::two_pi::<float>(), 2f * Real::pi::<float>());
+        assert_approx_eq!(Real::frac_pi_2::<float>(), Real::pi::<float>() / 2f);
+        assert_approx_eq!(Real::frac_pi_3::<float>(), Real::pi::<float>() / 3f);
+        assert_approx_eq!(Real::frac_pi_4::<float>(), Real::pi::<float>() / 4f);
+        assert_approx_eq!(Real::frac_pi_6::<float>(), Real::pi::<float>() / 6f);
+        assert_approx_eq!(Real::frac_pi_8::<float>(), Real::pi::<float>() / 8f);
+        assert_approx_eq!(Real::frac_1_pi::<float>(), 1f / Real::pi::<float>());
+        assert_approx_eq!(Real::frac_2_pi::<float>(), 2f / Real::pi::<float>());
+        assert_approx_eq!(Real::frac_2_sqrtpi::<float>(), 2f / Real::pi::<float>().sqrt());
+        assert_approx_eq!(Real::sqrt2::<float>(), 2f.sqrt());
+        assert_approx_eq!(Real::frac_1_sqrt2::<float>(), 1f / 2f.sqrt());
+        assert_approx_eq!(Real::log2_e::<float>(), Real::e::<float>().log2());
+        assert_approx_eq!(Real::log10_e::<float>(), Real::e::<float>().log10());
+        assert_approx_eq!(Real::ln_2::<float>(), 2f.ln());
+        assert_approx_eq!(Real::ln_10::<float>(), 10f.ln());
+    }
+
+    #[test]
+    fn test_abs() {
+        assert_eq!(infinity.abs(), infinity);
+        assert_eq!(1f.abs(), 1f);
+        assert_eq!(0f.abs(), 0f);
+        assert_eq!((-0f).abs(), 0f);
+        assert_eq!((-1f).abs(), 1f);
+        assert_eq!(neg_infinity.abs(), infinity);
+        assert_eq!((1f/neg_infinity).abs(), 0f);
+        assert!(NaN.abs().is_NaN());
+    }
+
+    #[test]
+    fn test_abs_sub() {
+        assert_eq!((-1f).abs_sub(&1f), 0f);
+        assert_eq!(1f.abs_sub(&1f), 0f);
+        assert_eq!(1f.abs_sub(&0f), 1f);
+        assert_eq!(1f.abs_sub(&-1f), 2f);
+        assert_eq!(neg_infinity.abs_sub(&0f), 0f);
+        assert_eq!(infinity.abs_sub(&1f), infinity);
+        assert_eq!(0f.abs_sub(&neg_infinity), infinity);
+        assert_eq!(0f.abs_sub(&infinity), 0f);
+        assert!(NaN.abs_sub(&-1f).is_NaN());
+        assert!(1f.abs_sub(&NaN).is_NaN());
+    }
+
+    #[test]
+    fn test_signum() {
+        assert_eq!(infinity.signum(), 1f);
+        assert_eq!(1f.signum(), 1f);
+        assert_eq!(0f.signum(), 1f);
+        assert_eq!((-0f).signum(), -1f);
+        assert_eq!((-1f).signum(), -1f);
+        assert_eq!(neg_infinity.signum(), -1f);
+        assert_eq!((1f/neg_infinity).signum(), -1f);
+        assert!(NaN.signum().is_NaN());
+    }
+
+    #[test]
+    fn test_is_positive() {
+        assert!(infinity.is_positive());
+        assert!(1f.is_positive());
+        assert!(0f.is_positive());
+        assert!(!(-0f).is_positive());
+        assert!(!(-1f).is_positive());
+        assert!(!neg_infinity.is_positive());
+        assert!(!(1f/neg_infinity).is_positive());
+        assert!(!NaN.is_positive());
+    }
+
+    #[test]
+    fn test_is_negative() {
+        assert!(!infinity.is_negative());
+        assert!(!1f.is_negative());
+        assert!(!0f.is_negative());
+        assert!((-0f).is_negative());
+        assert!((-1f).is_negative());
+        assert!(neg_infinity.is_negative());
+        assert!((1f/neg_infinity).is_negative());
+        assert!(!NaN.is_negative());
+    }
+
+    #[test]
+    fn test_approx_eq() {
+        assert!(1.0f.approx_eq(&1f));
+        assert!(0.9999999f.approx_eq(&1f));
+        assert!(1.000001f.approx_eq_eps(&1f, &1.0e-5));
+        assert!(1.0000001f.approx_eq_eps(&1f, &1.0e-6));
+        assert!(!1.0000001f.approx_eq_eps(&1f, &1.0e-7));
+    }
+
+    #[test]
+    fn test_primitive() {
+        assert_eq!(Primitive::bits::<float>(), sys::size_of::<float>() * 8);
+        assert_eq!(Primitive::bytes::<float>(), sys::size_of::<float>());
+    }
+
+    #[test]
+    fn test_is_normal() {
+        assert!(!Float::NaN::<float>().is_normal());
+        assert!(!Float::infinity::<float>().is_normal());
+        assert!(!Float::neg_infinity::<float>().is_normal());
+        assert!(!Zero::zero::<float>().is_normal());
+        assert!(!Float::neg_zero::<float>().is_normal());
+        assert!(1f.is_normal());
+        assert!(1e-307f.is_normal());
+        assert!(!1e-308f.is_normal());
+    }
+
+    #[test]
+    fn test_classify() {
+        assert_eq!(Float::NaN::<float>().classify(), FPNaN);
+        assert_eq!(Float::infinity::<float>().classify(), FPInfinite);
+        assert_eq!(Float::neg_infinity::<float>().classify(), FPInfinite);
+        assert_eq!(Zero::zero::<float>().classify(), FPZero);
+        assert_eq!(Float::neg_zero::<float>().classify(), FPZero);
+        assert_eq!(1f.classify(), FPNormal);
+        assert_eq!(1e-307f.classify(), FPNormal);
+        assert_eq!(1e-308f.classify(), FPSubnormal);
+    }
+
+    #[test]
+    fn test_ldexp() {
+        // We have to use from_str until base-2 exponents
+        // are supported in floating-point literals
+        let f1: float = from_str_hex("1p-123").unwrap();
+        let f2: float = from_str_hex("1p-111").unwrap();
+        assert_eq!(Float::ldexp(1f, -123), f1);
+        assert_eq!(Float::ldexp(1f, -111), f2);
+
+        assert_eq!(Float::ldexp(0f, -123), 0f);
+        assert_eq!(Float::ldexp(-0f, -123), -0f);
+        assert_eq!(Float::ldexp(Float::infinity::<float>(), -123),
+                   Float::infinity::<float>());
+        assert_eq!(Float::ldexp(Float::neg_infinity::<float>(), -123),
+                   Float::neg_infinity::<float>());
+        assert!(Float::ldexp(Float::NaN::<float>(), -123).is_NaN());
+    }
+
+    #[test]
+    fn test_frexp() {
+        // We have to use from_str until base-2 exponents
+        // are supported in floating-point literals
+        let f1: float = from_str_hex("1p-123").unwrap();
+        let f2: float = from_str_hex("1p-111").unwrap();
+        let (x1, exp1) = f1.frexp();
+        let (x2, exp2) = f2.frexp();
+        assert_eq!((x1, exp1), (0.5f, -122));
+        assert_eq!((x2, exp2), (0.5f, -110));
+        assert_eq!(Float::ldexp(x1, exp1), f1);
+        assert_eq!(Float::ldexp(x2, exp2), f2);
+
+        assert_eq!(0f.frexp(), (0f, 0));
+        assert_eq!((-0f).frexp(), (-0f, 0));
+        assert_eq!(match Float::infinity::<float>().frexp() { (x, _) => x },
+                   Float::infinity::<float>())
+        assert_eq!(match Float::neg_infinity::<float>().frexp() { (x, _) => x },
+                   Float::neg_infinity::<float>())
+        assert!(match Float::NaN::<float>().frexp() { (x, _) => x.is_NaN() })
+    }
+
+    #[test]
+    pub fn test_to_str_exact_do_decimal() {
+        let s = to_str_exact(5.0, 4u);
+        assert_eq!(s, ~"5.0000");
+    }
+
+    #[test]
+    pub fn test_from_str() {
+        assert_eq!(from_str(~"3"), Some(3.));
+        assert_eq!(from_str(~"3.14"), Some(3.14));
+        assert_eq!(from_str(~"+3.14"), Some(3.14));
+        assert_eq!(from_str(~"-3.14"), Some(-3.14));
+        assert_eq!(from_str(~"2.5E10"), Some(25000000000.));
+        assert_eq!(from_str(~"2.5e10"), Some(25000000000.));
+        assert_eq!(from_str(~"25000000000.E-10"), Some(2.5));
+        assert_eq!(from_str(~"."), Some(0.));
+        assert_eq!(from_str(~".e1"), Some(0.));
+        assert_eq!(from_str(~".e-1"), Some(0.));
+        assert_eq!(from_str(~"5."), Some(5.));
+        assert_eq!(from_str(~".5"), Some(0.5));
+        assert_eq!(from_str(~"0.5"), Some(0.5));
+        assert_eq!(from_str(~"-.5"), Some(-0.5));
+        assert_eq!(from_str(~"-5"), Some(-5.));
+        assert_eq!(from_str(~"inf"), Some(infinity));
+        assert_eq!(from_str(~"+inf"), Some(infinity));
+        assert_eq!(from_str(~"-inf"), Some(neg_infinity));
+        // note: NaN != NaN, hence this slightly complex test
+        match from_str(~"NaN") {
+            Some(f) => assert!(f.is_NaN()),
+            None => fail!()
+        }
+        // note: -0 == 0, hence these slightly more complex tests
+        match from_str(~"-0") {
+            Some(v) if v.is_zero() => assert!(v.is_negative()),
+            _ => fail!()
+        }
+        match from_str(~"0") {
+            Some(v) if v.is_zero() => assert!(v.is_positive()),
+            _ => fail!()
+        }
+
+        assert!(from_str(~"").is_none());
+        assert!(from_str(~"x").is_none());
+        assert!(from_str(~" ").is_none());
+        assert!(from_str(~"   ").is_none());
+        assert!(from_str(~"e").is_none());
+        assert!(from_str(~"E").is_none());
+        assert!(from_str(~"E1").is_none());
+        assert!(from_str(~"1e1e1").is_none());
+        assert!(from_str(~"1e1.1").is_none());
+        assert!(from_str(~"1e1-1").is_none());
+    }
+
+    #[test]
+    pub fn test_from_str_hex() {
+        assert_eq!(from_str_hex(~"a4"), Some(164.));
+        assert_eq!(from_str_hex(~"a4.fe"), Some(164.9921875));
+        assert_eq!(from_str_hex(~"-a4.fe"), Some(-164.9921875));
+        assert_eq!(from_str_hex(~"+a4.fe"), Some(164.9921875));
+        assert_eq!(from_str_hex(~"ff0P4"), Some(0xff00 as float));
+        assert_eq!(from_str_hex(~"ff0p4"), Some(0xff00 as float));
+        assert_eq!(from_str_hex(~"ff0p-4"), Some(0xff as float));
+        assert_eq!(from_str_hex(~"."), Some(0.));
+        assert_eq!(from_str_hex(~".p1"), Some(0.));
+        assert_eq!(from_str_hex(~".p-1"), Some(0.));
+        assert_eq!(from_str_hex(~"f."), Some(15.));
+        assert_eq!(from_str_hex(~".f"), Some(0.9375));
+        assert_eq!(from_str_hex(~"0.f"), Some(0.9375));
+        assert_eq!(from_str_hex(~"-.f"), Some(-0.9375));
+        assert_eq!(from_str_hex(~"-f"), Some(-15.));
+        assert_eq!(from_str_hex(~"inf"), Some(infinity));
+        assert_eq!(from_str_hex(~"+inf"), Some(infinity));
+        assert_eq!(from_str_hex(~"-inf"), Some(neg_infinity));
+        // note: NaN != NaN, hence this slightly complex test
+        match from_str_hex(~"NaN") {
+            Some(f) => assert!(f.is_NaN()),
+            None => fail!()
+        }
+        // note: -0 == 0, hence these slightly more complex tests
+        match from_str_hex(~"-0") {
+            Some(v) if v.is_zero() => assert!(v.is_negative()),
+            _ => fail!()
+        }
+        match from_str_hex(~"0") {
+            Some(v) if v.is_zero() => assert!(v.is_positive()),
+            _ => fail!()
+        }
+        assert_eq!(from_str_hex(~"e"), Some(14.));
+        assert_eq!(from_str_hex(~"E"), Some(14.));
+        assert_eq!(from_str_hex(~"E1"), Some(225.));
+        assert_eq!(from_str_hex(~"1e1e1"), Some(123361.));
+        assert_eq!(from_str_hex(~"1e1.1"), Some(481.0625));
+
+        assert!(from_str_hex(~"").is_none());
+        assert!(from_str_hex(~"x").is_none());
+        assert!(from_str_hex(~" ").is_none());
+        assert!(from_str_hex(~"   ").is_none());
+        assert!(from_str_hex(~"p").is_none());
+        assert!(from_str_hex(~"P").is_none());
+        assert!(from_str_hex(~"P1").is_none());
+        assert!(from_str_hex(~"1p1p1").is_none());
+        assert!(from_str_hex(~"1p1.1").is_none());
+        assert!(from_str_hex(~"1p1-1").is_none());
+    }
+
+    #[test]
+    pub fn test_to_str_hex() {
+        assert_eq!(to_str_hex(164.), ~"a4");
+        assert_eq!(to_str_hex(164.9921875), ~"a4.fe");
+        assert_eq!(to_str_hex(-164.9921875), ~"-a4.fe");
+        assert_eq!(to_str_hex(0xff00 as float), ~"ff00");
+        assert_eq!(to_str_hex(-(0xff00 as float)), ~"-ff00");
+        assert_eq!(to_str_hex(0.), ~"0");
+        assert_eq!(to_str_hex(15.), ~"f");
+        assert_eq!(to_str_hex(-15.), ~"-f");
+        assert_eq!(to_str_hex(0.9375), ~"0.f");
+        assert_eq!(to_str_hex(-0.9375), ~"-0.f");
+        assert_eq!(to_str_hex(infinity), ~"inf");
+        assert_eq!(to_str_hex(neg_infinity), ~"-inf");
+        assert_eq!(to_str_hex(NaN), ~"NaN");
+        assert_eq!(to_str_hex(0.), ~"0");
+        assert_eq!(to_str_hex(-0.), ~"-0");
+    }
+
+    #[test]
+    pub fn test_to_str_radix() {
+        assert_eq!(to_str_radix(36., 36u), ~"10");
+        assert_eq!(to_str_radix(8.125, 2u), ~"1000.001");
+    }
+
+    #[test]
+    pub fn test_from_str_radix() {
+        assert_eq!(from_str_radix(~"10", 36u), Some(36.));
+        assert_eq!(from_str_radix(~"1000.001", 2u), Some(8.125));
+    }
+
+    #[test]
+    pub fn test_to_str_inf() {
+        assert_eq!(to_str_digits(infinity, 10u), ~"inf");
+        assert_eq!(to_str_digits(-infinity, 10u), ~"-inf");
+    }
+}
diff --git a/src/libstd/num/int-template.rs b/src/libstd/num/int-template.rs
new file mode 100644
index 00000000000..3c31a7d5745
--- /dev/null
+++ b/src/libstd/num/int-template.rs
@@ -0,0 +1,929 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use T = self::inst::T;
+
+use num::{ToStrRadix, FromStrRadix};
+use num::{Zero, One, strconv};
+use prelude::*;
+
+pub use cmp::{min, max};
+
+pub static bits : uint = inst::bits;
+pub static bytes : uint = (inst::bits / 8);
+
+pub static min_value: T = (-1 as T) << (bits - 1);
+pub static max_value: T = min_value - 1 as T;
+
+#[inline(always)]
+pub fn add(x: T, y: T) -> T { x + y }
+#[inline(always)]
+pub fn sub(x: T, y: T) -> T { x - y }
+#[inline(always)]
+pub fn mul(x: T, y: T) -> T { x * y }
+#[inline(always)]
+pub fn div(x: T, y: T) -> T { x / y }
+
+///
+/// Returns the remainder of y / x.
+///
+/// # Examples
+/// ~~~
+/// assert!(int::rem(5 / 2) == 1);
+/// ~~~
+///
+/// When faced with negative numbers, the result copies the sign of the
+/// dividend.
+///
+/// ~~~
+/// assert!(int::rem(2 / -3) ==  2);
+/// ~~~
+///
+/// ~~~
+/// assert!(int::rem(-2 / 3) ==  -2);
+/// ~~~
+///
+///
+#[inline(always)]
+pub fn rem(x: T, y: T) -> T { x % y }
+
+#[inline(always)]
+pub fn lt(x: T, y: T) -> bool { x < y }
+#[inline(always)]
+pub fn le(x: T, y: T) -> bool { x <= y }
+#[inline(always)]
+pub fn eq(x: T, y: T) -> bool { x == y }
+#[inline(always)]
+pub fn ne(x: T, y: T) -> bool { x != y }
+#[inline(always)]
+pub fn ge(x: T, y: T) -> bool { x >= y }
+#[inline(always)]
+pub fn gt(x: T, y: T) -> bool { x > y }
+
+///
+/// Iterate over the range [`lo`..`hi`)
+///
+/// # Arguments
+///
+/// * `lo` - lower bound, inclusive
+/// * `hi` - higher bound, exclusive
+///
+/// # Examples
+/// ~~~
+/// let mut sum = 0;
+/// for int::range(1, 5) |i| {
+///     sum += i;
+/// }
+/// assert!(sum == 10);
+/// ~~~
+///
+#[inline(always)]
+/// Iterate over the range [`start`,`start`+`step`..`stop`)
+pub fn _range_step(start: T, stop: T, step: T, it: &fn(T) -> bool) -> bool {
+    let mut i = start;
+    if step == 0 {
+        fail!("range_step called with step == 0");
+    } else if step > 0 { // ascending
+        while i < stop {
+            if !it(i) { return false; }
+            // avoiding overflow. break if i + step > max_value
+            if i > max_value - step { return true; }
+            i += step;
+        }
+    } else { // descending
+        while i > stop {
+            if !it(i) { return false; }
+            // avoiding underflow. break if i + step < min_value
+            if i < min_value - step { return true; }
+            i += step;
+        }
+    }
+    return true;
+}
+
+pub fn range_step(start: T, stop: T, step: T, it: &fn(T) -> bool) -> bool {
+    _range_step(start, stop, step, it)
+}
+
+#[inline(always)]
+/// Iterate over the range [`lo`..`hi`)
+pub fn range(lo: T, hi: T, it: &fn(T) -> bool) -> bool {
+    range_step(lo, hi, 1 as T, it)
+}
+
+#[inline(always)]
+/// Iterate over the range [`hi`..`lo`)
+pub fn range_rev(hi: T, lo: T, it: &fn(T) -> bool) -> bool {
+    range_step(hi, lo, -1 as T, it)
+}
+
+/// Computes the bitwise complement
+#[inline(always)]
+pub fn compl(i: T) -> T {
+    -1 as T ^ i
+}
+
+/// Computes the absolute value
+#[inline(always)]
+pub fn abs(i: T) -> T { i.abs() }
+
+impl Num for T {}
+
+#[cfg(not(test))]
+impl Ord for T {
+    #[inline(always)]
+    fn lt(&self, other: &T) -> bool { return (*self) < (*other); }
+    #[inline(always)]
+    fn le(&self, other: &T) -> bool { return (*self) <= (*other); }
+    #[inline(always)]
+    fn ge(&self, other: &T) -> bool { return (*self) >= (*other); }
+    #[inline(always)]
+    fn gt(&self, other: &T) -> bool { return (*self) > (*other); }
+}
+
+#[cfg(not(test))]
+impl Eq for T {
+    #[inline(always)]
+    fn eq(&self, other: &T) -> bool { return (*self) == (*other); }
+    #[inline(always)]
+    fn ne(&self, other: &T) -> bool { return (*self) != (*other); }
+}
+
+impl Orderable for T {
+    #[inline(always)]
+    fn min(&self, other: &T) -> T {
+        if *self < *other { *self } else { *other }
+    }
+
+    #[inline(always)]
+    fn max(&self, other: &T) -> T {
+        if *self > *other { *self } else { *other }
+    }
+
+    /// Returns the number constrained within the range `mn <= self <= mx`.
+    #[inline(always)]
+    fn clamp(&self, mn: &T, mx: &T) -> T {
+        cond!(
+            (*self > *mx) { *mx   }
+            (*self < *mn) { *mn   }
+            _             { *self }
+        )
+    }
+}
+
+impl Zero for T {
+    #[inline(always)]
+    fn zero() -> T { 0 }
+
+    #[inline(always)]
+    fn is_zero(&self) -> bool { *self == 0 }
+}
+
+impl One for T {
+    #[inline(always)]
+    fn one() -> T { 1 }
+}
+
+#[cfg(not(test))]
+impl Add<T,T> for T {
+    #[inline(always)]
+    fn add(&self, other: &T) -> T { *self + *other }
+}
+
+#[cfg(not(test))]
+impl Sub<T,T> for T {
+    #[inline(always)]
+    fn sub(&self, other: &T) -> T { *self - *other }
+}
+
+#[cfg(not(test))]
+impl Mul<T,T> for T {
+    #[inline(always)]
+    fn mul(&self, other: &T) -> T { *self * *other }
+}
+
+#[cfg(not(test))]
+impl Div<T,T> for T {
+    ///
+    /// Integer division, truncated towards 0. As this behaviour reflects the underlying
+    /// machine implementation it is more efficient than `Integer::div_floor`.
+    ///
+    /// # Examples
+    ///
+    /// ~~~
+    /// assert!( 8 /  3 ==  2);
+    /// assert!( 8 / -3 == -2);
+    /// assert!(-8 /  3 == -2);
+    /// assert!(-8 / -3 ==  2);
+
+    /// assert!( 1 /  2 ==  0);
+    /// assert!( 1 / -2 ==  0);
+    /// assert!(-1 /  2 ==  0);
+    /// assert!(-1 / -2 ==  0);
+    /// ~~~
+    ///
+    #[inline(always)]
+    fn div(&self, other: &T) -> T { *self / *other }
+}
+
+#[cfg(not(test))]
+impl Rem<T,T> for T {
+    ///
+    /// Returns the integer remainder after division, satisfying:
+    ///
+    /// ~~~
+    /// assert!((n / d) * d + (n % d) == n)
+    /// ~~~
+    ///
+    /// # Examples
+    ///
+    /// ~~~
+    /// assert!( 8 %  3 ==  2);
+    /// assert!( 8 % -3 ==  2);
+    /// assert!(-8 %  3 == -2);
+    /// assert!(-8 % -3 == -2);
+
+    /// assert!( 1 %  2 ==  1);
+    /// assert!( 1 % -2 ==  1);
+    /// assert!(-1 %  2 == -1);
+    /// assert!(-1 % -2 == -1);
+    /// ~~~
+    ///
+    #[inline(always)]
+    fn rem(&self, other: &T) -> T { *self % *other }
+}
+
+#[cfg(not(test))]
+impl Neg<T> for T {
+    #[inline(always)]
+    fn neg(&self) -> T { -*self }
+}
+
+impl Signed for T {
+    /// Computes the absolute value
+    #[inline(always)]
+    fn abs(&self) -> T {
+        if self.is_negative() { -*self } else { *self }
+    }
+
+    ///
+    /// The positive difference of two numbers. Returns `0` if the number is less than or
+    /// equal to `other`, otherwise the difference between`self` and `other` is returned.
+    ///
+    #[inline(always)]
+    fn abs_sub(&self, other: &T) -> T {
+        if *self <= *other { 0 } else { *self - *other }
+    }
+
+    ///
+    /// # Returns
+    ///
+    /// - `0` if the number is zero
+    /// - `1` if the number is positive
+    /// - `-1` if the number is negative
+    ///
+    #[inline(always)]
+    fn signum(&self) -> T {
+        match *self {
+            n if n > 0 =>  1,
+            0          =>  0,
+            _          => -1,
+        }
+    }
+
+    /// Returns true if the number is positive
+    #[inline(always)]
+    fn is_positive(&self) -> bool { *self > 0 }
+
+    /// Returns true if the number is negative
+    #[inline(always)]
+    fn is_negative(&self) -> bool { *self < 0 }
+}
+
+impl Integer for T {
+    ///
+    /// Floored integer division
+    ///
+    /// # Examples
+    ///
+    /// ~~~
+    /// assert!(( 8).div_floor( 3) ==  2);
+    /// assert!(( 8).div_floor(-3) == -3);
+    /// assert!((-8).div_floor( 3) == -3);
+    /// assert!((-8).div_floor(-3) ==  2);
+    ///
+    /// assert!(( 1).div_floor( 2) ==  0);
+    /// assert!(( 1).div_floor(-2) == -1);
+    /// assert!((-1).div_floor( 2) == -1);
+    /// assert!((-1).div_floor(-2) ==  0);
+    /// ~~~
+    ///
+    #[inline(always)]
+    fn div_floor(&self, other: &T) -> T {
+        // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+        // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+        match self.div_rem(other) {
+            (d, r) if (r > 0 && *other < 0)
+                   || (r < 0 && *other > 0) => d - 1,
+            (d, _)                          => d,
+        }
+    }
+
+    ///
+    /// Integer modulo, satisfying:
+    ///
+    /// ~~~
+    /// assert!(n.div_floor(d) * d + n.mod_floor(d) == n)
+    /// ~~~
+    ///
+    /// # Examples
+    ///
+    /// ~~~
+    /// assert!(( 8).mod_floor( 3) ==  2);
+    /// assert!(( 8).mod_floor(-3) == -1);
+    /// assert!((-8).mod_floor( 3) ==  1);
+    /// assert!((-8).mod_floor(-3) == -2);
+    ///
+    /// assert!(( 1).mod_floor( 2) ==  1);
+    /// assert!(( 1).mod_floor(-2) == -1);
+    /// assert!((-1).mod_floor( 2) ==  1);
+    /// assert!((-1).mod_floor(-2) == -1);
+    /// ~~~
+    ///
+    #[inline(always)]
+    fn mod_floor(&self, other: &T) -> T {
+        // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+        // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+        match *self % *other {
+            r if (r > 0 && *other < 0)
+              || (r < 0 && *other > 0) => r + *other,
+            r                          => r,
+        }
+    }
+
+    /// Calculates `div_floor` and `mod_floor` simultaneously
+    #[inline(always)]
+    fn div_mod_floor(&self, other: &T) -> (T,T) {
+        // Algorithm from [Daan Leijen. _Division and Modulus for Computer Scientists_,
+        // December 2001](http://research.microsoft.com/pubs/151917/divmodnote-letter.pdf)
+        match self.div_rem(other) {
+            (d, r) if (r > 0 && *other < 0)
+                   || (r < 0 && *other > 0) => (d - 1, r + *other),
+            (d, r)                          => (d, r),
+        }
+    }
+
+    /// Calculates `div` (`\`) and `rem` (`%`) simultaneously
+    #[inline(always)]
+    fn div_rem(&self, other: &T) -> (T,T) {
+        (*self / *other, *self % *other)
+    }
+
+    ///
+    /// Calculates the Greatest Common Divisor (GCD) of the number and `other`
+    ///
+    /// The result is always positive
+    ///
+    #[inline(always)]
+    fn gcd(&self, other: &T) -> T {
+        // Use Euclid's algorithm
+        let mut m = *self, n = *other;
+        while m != 0 {
+            let temp = m;
+            m = n % temp;
+            n = temp;
+        }
+        n.abs()
+    }
+
+    ///
+    /// Calculates the Lowest Common Multiple (LCM) of the number and `other`
+    ///
+    #[inline(always)]
+    fn lcm(&self, other: &T) -> T {
+        ((*self * *other) / self.gcd(other)).abs() // should not have to recaluculate abs
+    }
+
+    /// Returns `true` if the number can be divided by `other` without leaving a remainder
+    #[inline(always)]
+    fn is_multiple_of(&self, other: &T) -> bool { *self % *other == 0 }
+
+    /// Returns `true` if the number is divisible by `2`
+    #[inline(always)]
+    fn is_even(&self) -> bool { self.is_multiple_of(&2) }
+
+    /// Returns `true` if the number is not divisible by `2`
+    #[inline(always)]
+    fn is_odd(&self) -> bool { !self.is_even() }
+}
+
+impl Bitwise for T {}
+
+#[cfg(not(test))]
+impl BitOr<T,T> for T {
+    #[inline(always)]
+    fn bitor(&self, other: &T) -> T { *self | *other }
+}
+
+#[cfg(not(test))]
+impl BitAnd<T,T> for T {
+    #[inline(always)]
+    fn bitand(&self, other: &T) -> T { *self & *other }
+}
+
+#[cfg(not(test))]
+impl BitXor<T,T> for T {
+    #[inline(always)]
+    fn bitxor(&self, other: &T) -> T { *self ^ *other }
+}
+
+#[cfg(not(test))]
+impl Shl<T,T> for T {
+    #[inline(always)]
+    fn shl(&self, other: &T) -> T { *self << *other }
+}
+
+#[cfg(not(test))]
+impl Shr<T,T> for T {
+    #[inline(always)]
+    fn shr(&self, other: &T) -> T { *self >> *other }
+}
+
+#[cfg(not(test))]
+impl Not<T> for T {
+    #[inline(always)]
+    fn not(&self) -> T { !*self }
+}
+
+impl Bounded for T {
+    #[inline(always)]
+    fn min_value() -> T { min_value }
+
+    #[inline(always)]
+    fn max_value() -> T { max_value }
+}
+
+impl Int for T {}
+
+// String conversion functions and impl str -> num
+
+/// Parse a string as a number in base 10.
+#[inline(always)]
+pub fn from_str(s: &str) -> Option<T> {
+    strconv::from_str_common(s, 10u, true, false, false,
+                         strconv::ExpNone, false, false)
+}
+
+/// Parse a string as a number in the given base.
+#[inline(always)]
+pub fn from_str_radix(s: &str, radix: uint) -> Option<T> {
+    strconv::from_str_common(s, radix, true, false, false,
+                         strconv::ExpNone, false, false)
+}
+
+/// Parse a byte slice as a number in the given base.
+#[inline(always)]
+pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<T> {
+    strconv::from_str_bytes_common(buf, radix, true, false, false,
+                               strconv::ExpNone, false, false)
+}
+
+impl FromStr for T {
+    #[inline(always)]
+    fn from_str(s: &str) -> Option<T> {
+        from_str(s)
+    }
+}
+
+impl FromStrRadix for T {
+    #[inline(always)]
+    fn from_str_radix(s: &str, radix: uint) -> Option<T> {
+        from_str_radix(s, radix)
+    }
+}
+
+// String conversion functions and impl num -> str
+
+/// Convert to a string as a byte slice in a given base.
+#[inline(always)]
+pub fn to_str_bytes<U>(n: T, radix: uint, f: &fn(v: &[u8]) -> U) -> U {
+    let (buf, _) = strconv::to_str_bytes_common(&n, radix, false,
+                            strconv::SignNeg, strconv::DigAll);
+    f(buf)
+}
+
+/// Convert to a string in base 10.
+#[inline(always)]
+pub fn to_str(num: T) -> ~str {
+    let (buf, _) = strconv::to_str_common(&num, 10u, false,
+                                      strconv::SignNeg, strconv::DigAll);
+    buf
+}
+
+/// Convert to a string in a given base.
+#[inline(always)]
+pub fn to_str_radix(num: T, radix: uint) -> ~str {
+    let (buf, _) = strconv::to_str_common(&num, radix, false,
+                                      strconv::SignNeg, strconv::DigAll);
+    buf
+}
+
+impl ToStr for T {
+    #[inline(always)]
+    fn to_str(&self) -> ~str {
+        to_str(*self)
+    }
+}
+
+impl ToStrRadix for T {
+    #[inline(always)]
+    fn to_str_radix(&self, radix: uint) -> ~str {
+        to_str_radix(*self, radix)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use super::inst::T;
+    use prelude::*;
+
+    #[test]
+    fn test_num() {
+        num::test_num(10 as T, 2 as T);
+    }
+
+    #[test]
+    fn test_orderable() {
+        assert_eq!((1 as T).min(&(2 as T)), 1 as T);
+        assert_eq!((2 as T).min(&(1 as T)), 1 as T);
+        assert_eq!((1 as T).max(&(2 as T)), 2 as T);
+        assert_eq!((2 as T).max(&(1 as T)), 2 as T);
+        assert_eq!((1 as T).clamp(&(2 as T), &(4 as T)), 2 as T);
+        assert_eq!((8 as T).clamp(&(2 as T), &(4 as T)), 4 as T);
+        assert_eq!((3 as T).clamp(&(2 as T), &(4 as T)), 3 as T);
+    }
+
+    #[test]
+    pub fn test_abs() {
+        assert_eq!((1 as T).abs(), 1 as T);
+        assert_eq!((0 as T).abs(), 0 as T);
+        assert_eq!((-1 as T).abs(), 1 as T);
+    }
+
+    #[test]
+    fn test_abs_sub() {
+        assert_eq!((-1 as T).abs_sub(&(1 as T)), 0 as T);
+        assert_eq!((1 as T).abs_sub(&(1 as T)), 0 as T);
+        assert_eq!((1 as T).abs_sub(&(0 as T)), 1 as T);
+        assert_eq!((1 as T).abs_sub(&(-1 as T)), 2 as T);
+    }
+
+    #[test]
+    fn test_signum() {
+        assert_eq!((1 as T).signum(), 1 as T);
+        assert_eq!((0 as T).signum(), 0 as T);
+        assert_eq!((-0 as T).signum(), 0 as T);
+        assert_eq!((-1 as T).signum(), -1 as T);
+    }
+
+    #[test]
+    fn test_is_positive() {
+        assert!((1 as T).is_positive());
+        assert!(!(0 as T).is_positive());
+        assert!(!(-0 as T).is_positive());
+        assert!(!(-1 as T).is_positive());
+    }
+
+    #[test]
+    fn test_is_negative() {
+        assert!(!(1 as T).is_negative());
+        assert!(!(0 as T).is_negative());
+        assert!(!(-0 as T).is_negative());
+        assert!((-1 as T).is_negative());
+    }
+
+    ///
+    /// Checks that the division rule holds for:
+    ///
+    /// - `n`: numerator (dividend)
+    /// - `d`: denominator (divisor)
+    /// - `qr`: quotient and remainder
+    ///
+    #[cfg(test)]
+    fn test_division_rule((n,d): (T,T), (q,r): (T,T)) {
+        assert_eq!(d * q + r, n);
+    }
+
+    #[test]
+    fn test_div_rem() {
+        fn test_nd_dr(nd: (T,T), qr: (T,T)) {
+            let (n,d) = nd;
+            let separate_div_rem = (n / d, n % d);
+            let combined_div_rem = n.div_rem(&d);
+
+            assert_eq!(separate_div_rem, qr);
+            assert_eq!(combined_div_rem, qr);
+
+            test_division_rule(nd, separate_div_rem);
+            test_division_rule(nd, combined_div_rem);
+        }
+
+        test_nd_dr(( 8,  3), ( 2,  2));
+        test_nd_dr(( 8, -3), (-2,  2));
+        test_nd_dr((-8,  3), (-2, -2));
+        test_nd_dr((-8, -3), ( 2, -2));
+
+        test_nd_dr(( 1,  2), ( 0,  1));
+        test_nd_dr(( 1, -2), ( 0,  1));
+        test_nd_dr((-1,  2), ( 0, -1));
+        test_nd_dr((-1, -2), ( 0, -1));
+    }
+
+    #[test]
+    fn test_div_mod_floor() {
+        fn test_nd_dm(nd: (T,T), dm: (T,T)) {
+            let (n,d) = nd;
+            let separate_div_mod_floor = (n.div_floor(&d), n.mod_floor(&d));
+            let combined_div_mod_floor = n.div_mod_floor(&d);
+
+            assert_eq!(separate_div_mod_floor, dm);
+            assert_eq!(combined_div_mod_floor, dm);
+
+            test_division_rule(nd, separate_div_mod_floor);
+            test_division_rule(nd, combined_div_mod_floor);
+        }
+
+        test_nd_dm(( 8,  3), ( 2,  2));
+        test_nd_dm(( 8, -3), (-3, -1));
+        test_nd_dm((-8,  3), (-3,  1));
+        test_nd_dm((-8, -3), ( 2, -2));
+
+        test_nd_dm(( 1,  2), ( 0,  1));
+        test_nd_dm(( 1, -2), (-1, -1));
+        test_nd_dm((-1,  2), (-1,  1));
+        test_nd_dm((-1, -2), ( 0, -1));
+    }
+
+    #[test]
+    fn test_gcd() {
+        assert_eq!((10 as T).gcd(&2), 2 as T);
+        assert_eq!((10 as T).gcd(&3), 1 as T);
+        assert_eq!((0 as T).gcd(&3), 3 as T);
+        assert_eq!((3 as T).gcd(&3), 3 as T);
+        assert_eq!((56 as T).gcd(&42), 14 as T);
+        assert_eq!((3 as T).gcd(&-3), 3 as T);
+        assert_eq!((-6 as T).gcd(&3), 3 as T);
+        assert_eq!((-4 as T).gcd(&-2), 2 as T);
+    }
+
+    #[test]
+    fn test_lcm() {
+        assert_eq!((1 as T).lcm(&0), 0 as T);
+        assert_eq!((0 as T).lcm(&1), 0 as T);
+        assert_eq!((1 as T).lcm(&1), 1 as T);
+        assert_eq!((-1 as T).lcm(&1), 1 as T);
+        assert_eq!((1 as T).lcm(&-1), 1 as T);
+        assert_eq!((-1 as T).lcm(&-1), 1 as T);
+        assert_eq!((8 as T).lcm(&9), 72 as T);
+        assert_eq!((11 as T).lcm(&5), 55 as T);
+    }
+
+    #[test]
+    fn test_bitwise() {
+        assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
+        assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T)));
+        assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T)));
+        assert_eq!(0b1110 as T, (0b0111 as T).shl(&(1 as T)));
+        assert_eq!(0b0111 as T, (0b1110 as T).shr(&(1 as T)));
+        assert_eq!(-(0b11 as T) - (1 as T), (0b11 as T).not());
+    }
+
+    #[test]
+    fn test_multiple_of() {
+        assert!((6 as T).is_multiple_of(&(6 as T)));
+        assert!((6 as T).is_multiple_of(&(3 as T)));
+        assert!((6 as T).is_multiple_of(&(1 as T)));
+        assert!((-8 as T).is_multiple_of(&(4 as T)));
+        assert!((8 as T).is_multiple_of(&(-1 as T)));
+        assert!((-8 as T).is_multiple_of(&(-2 as T)));
+    }
+
+    #[test]
+    fn test_even() {
+        assert_eq!((-4 as T).is_even(), true);
+        assert_eq!((-3 as T).is_even(), false);
+        assert_eq!((-2 as T).is_even(), true);
+        assert_eq!((-1 as T).is_even(), false);
+        assert_eq!((0 as T).is_even(), true);
+        assert_eq!((1 as T).is_even(), false);
+        assert_eq!((2 as T).is_even(), true);
+        assert_eq!((3 as T).is_even(), false);
+        assert_eq!((4 as T).is_even(), true);
+    }
+
+    #[test]
+    fn test_odd() {
+        assert_eq!((-4 as T).is_odd(), false);
+        assert_eq!((-3 as T).is_odd(), true);
+        assert_eq!((-2 as T).is_odd(), false);
+        assert_eq!((-1 as T).is_odd(), true);
+        assert_eq!((0 as T).is_odd(), false);
+        assert_eq!((1 as T).is_odd(), true);
+        assert_eq!((2 as T).is_odd(), false);
+        assert_eq!((3 as T).is_odd(), true);
+        assert_eq!((4 as T).is_odd(), false);
+    }
+
+    #[test]
+    fn test_bitcount() {
+        assert_eq!((0b010101 as T).population_count(), 3);
+    }
+
+    #[test]
+    fn test_primitive() {
+        assert_eq!(Primitive::bits::<T>(), sys::size_of::<T>() * 8);
+        assert_eq!(Primitive::bytes::<T>(), sys::size_of::<T>());
+    }
+
+    #[test]
+    fn test_from_str() {
+        assert_eq!(from_str(~"0"), Some(0 as T));
+        assert_eq!(from_str(~"3"), Some(3 as T));
+        assert_eq!(from_str(~"10"), Some(10 as T));
+        assert_eq!(i32::from_str(~"123456789"), Some(123456789 as i32));
+        assert_eq!(from_str(~"00100"), Some(100 as T));
+
+        assert_eq!(from_str(~"-1"), Some(-1 as T));
+        assert_eq!(from_str(~"-3"), Some(-3 as T));
+        assert_eq!(from_str(~"-10"), Some(-10 as T));
+        assert_eq!(i32::from_str(~"-123456789"), Some(-123456789 as i32));
+        assert_eq!(from_str(~"-00100"), Some(-100 as T));
+
+        assert!(from_str(~" ").is_none());
+        assert!(from_str(~"x").is_none());
+    }
+
+    #[test]
+    fn test_parse_bytes() {
+        use str::to_bytes;
+        assert_eq!(parse_bytes(to_bytes(~"123"), 10u), Some(123 as T));
+        assert_eq!(parse_bytes(to_bytes(~"1001"), 2u), Some(9 as T));
+        assert_eq!(parse_bytes(to_bytes(~"123"), 8u), Some(83 as T));
+        assert_eq!(i32::parse_bytes(to_bytes(~"123"), 16u), Some(291 as i32));
+        assert_eq!(i32::parse_bytes(to_bytes(~"ffff"), 16u), Some(65535 as i32));
+        assert_eq!(i32::parse_bytes(to_bytes(~"FFFF"), 16u), Some(65535 as i32));
+        assert_eq!(parse_bytes(to_bytes(~"z"), 36u), Some(35 as T));
+        assert_eq!(parse_bytes(to_bytes(~"Z"), 36u), Some(35 as T));
+
+        assert_eq!(parse_bytes(to_bytes(~"-123"), 10u), Some(-123 as T));
+        assert_eq!(parse_bytes(to_bytes(~"-1001"), 2u), Some(-9 as T));
+        assert_eq!(parse_bytes(to_bytes(~"-123"), 8u), Some(-83 as T));
+        assert_eq!(i32::parse_bytes(to_bytes(~"-123"), 16u), Some(-291 as i32));
+        assert_eq!(i32::parse_bytes(to_bytes(~"-ffff"), 16u), Some(-65535 as i32));
+        assert_eq!(i32::parse_bytes(to_bytes(~"-FFFF"), 16u), Some(-65535 as i32));
+        assert_eq!(parse_bytes(to_bytes(~"-z"), 36u), Some(-35 as T));
+        assert_eq!(parse_bytes(to_bytes(~"-Z"), 36u), Some(-35 as T));
+
+        assert!(parse_bytes(to_bytes(~"Z"), 35u).is_none());
+        assert!(parse_bytes(to_bytes(~"-9"), 2u).is_none());
+    }
+
+    #[test]
+    fn test_to_str() {
+        assert_eq!(to_str_radix(0 as T, 10u), ~"0");
+        assert_eq!(to_str_radix(1 as T, 10u), ~"1");
+        assert_eq!(to_str_radix(-1 as T, 10u), ~"-1");
+        assert_eq!(to_str_radix(127 as T, 16u), ~"7f");
+        assert_eq!(to_str_radix(100 as T, 10u), ~"100");
+
+    }
+
+    #[test]
+    fn test_int_to_str_overflow() {
+        let mut i8_val: i8 = 127_i8;
+        assert_eq!(i8::to_str(i8_val), ~"127");
+
+        i8_val += 1 as i8;
+        assert_eq!(i8::to_str(i8_val), ~"-128");
+
+        let mut i16_val: i16 = 32_767_i16;
+        assert_eq!(i16::to_str(i16_val), ~"32767");
+
+        i16_val += 1 as i16;
+        assert_eq!(i16::to_str(i16_val), ~"-32768");
+
+        let mut i32_val: i32 = 2_147_483_647_i32;
+        assert_eq!(i32::to_str(i32_val), ~"2147483647");
+
+        i32_val += 1 as i32;
+        assert_eq!(i32::to_str(i32_val), ~"-2147483648");
+
+        let mut i64_val: i64 = 9_223_372_036_854_775_807_i64;
+        assert_eq!(i64::to_str(i64_val), ~"9223372036854775807");
+
+        i64_val += 1 as i64;
+        assert_eq!(i64::to_str(i64_val), ~"-9223372036854775808");
+    }
+
+    #[test]
+    fn test_int_from_str_overflow() {
+        let mut i8_val: i8 = 127_i8;
+        assert_eq!(i8::from_str(~"127"), Some(i8_val));
+        assert!(i8::from_str(~"128").is_none());
+
+        i8_val += 1 as i8;
+        assert_eq!(i8::from_str(~"-128"), Some(i8_val));
+        assert!(i8::from_str(~"-129").is_none());
+
+        let mut i16_val: i16 = 32_767_i16;
+        assert_eq!(i16::from_str(~"32767"), Some(i16_val));
+        assert!(i16::from_str(~"32768").is_none());
+
+        i16_val += 1 as i16;
+        assert_eq!(i16::from_str(~"-32768"), Some(i16_val));
+        assert!(i16::from_str(~"-32769").is_none());
+
+        let mut i32_val: i32 = 2_147_483_647_i32;
+        assert_eq!(i32::from_str(~"2147483647"), Some(i32_val));
+        assert!(i32::from_str(~"2147483648").is_none());
+
+        i32_val += 1 as i32;
+        assert_eq!(i32::from_str(~"-2147483648"), Some(i32_val));
+        assert!(i32::from_str(~"-2147483649").is_none());
+
+        let mut i64_val: i64 = 9_223_372_036_854_775_807_i64;
+        assert_eq!(i64::from_str(~"9223372036854775807"), Some(i64_val));
+        assert!(i64::from_str(~"9223372036854775808").is_none());
+
+        i64_val += 1 as i64;
+        assert_eq!(i64::from_str(~"-9223372036854775808"), Some(i64_val));
+        assert!(i64::from_str(~"-9223372036854775809").is_none());
+    }
+
+    #[test]
+    fn test_ranges() {
+        let mut l = ~[];
+
+        for range(0,3) |i| {
+            l.push(i);
+        }
+        for range_rev(13,10) |i| {
+            l.push(i);
+        }
+        for range_step(20,26,2) |i| {
+            l.push(i);
+        }
+        for range_step(36,30,-2) |i| {
+            l.push(i);
+        }
+        for range_step(max_value - 2, max_value, 2) |i| {
+            l.push(i);
+        }
+        for range_step(max_value - 3, max_value, 2) |i| {
+            l.push(i);
+        }
+        for range_step(min_value + 2, min_value, -2) |i| {
+            l.push(i);
+        }
+        for range_step(min_value + 3, min_value, -2) |i| {
+            l.push(i);
+        }
+        assert_eq!(l, ~[0,1,2,
+                        13,12,11,
+                        20,22,24,
+                        36,34,32,
+                        max_value-2,
+                        max_value-3,max_value-1,
+                        min_value+2,
+                        min_value+3,min_value+1]);
+
+        // None of the `fail`s should execute.
+        for range(10,0) |_i| {
+            fail!("unreachable");
+        }
+        for range_rev(0,10) |_i| {
+            fail!("unreachable");
+        }
+        for range_step(10,0,1) |_i| {
+            fail!("unreachable");
+        }
+        for range_step(0,10,-1) |_i| {
+            fail!("unreachable");
+        }
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_range_step_zero_step() {
+        for range_step(0,10,0) |_i| {}
+    }
+}
diff --git a/src/libstd/num/int-template/i16.rs b/src/libstd/num/int-template/i16.rs
new file mode 100644
index 00000000000..28263378555
--- /dev/null
+++ b/src/libstd/num/int-template/i16.rs
@@ -0,0 +1,41 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations and constants for `i16`
+
+mod inst {
+    use num::{Primitive, BitCount};
+    use unstable::intrinsics;
+
+    pub type T = i16;
+    pub static bits: uint = ::u16::bits;
+
+    impl Primitive for i16 {
+        #[inline(always)]
+        fn bits() -> uint { 16 }
+
+        #[inline(always)]
+        fn bytes() -> uint { Primitive::bits::<i16>() / 8 }
+    }
+
+    impl BitCount for i16 {
+        /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+        #[inline(always)]
+        fn population_count(&self) -> i16 { unsafe { intrinsics::ctpop16(*self) } }
+
+        /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+        #[inline(always)]
+        fn leading_zeros(&self) -> i16 { unsafe { intrinsics::ctlz16(*self) } }
+
+        /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+        #[inline(always)]
+        fn trailing_zeros(&self) -> i16 { unsafe { intrinsics::cttz16(*self) } }
+    }
+}
diff --git a/src/libstd/num/int-template/i32.rs b/src/libstd/num/int-template/i32.rs
new file mode 100644
index 00000000000..959cf8f7d77
--- /dev/null
+++ b/src/libstd/num/int-template/i32.rs
@@ -0,0 +1,41 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations and constants for `i32`
+
+mod inst {
+    use num::{Primitive, BitCount};
+    use unstable::intrinsics;
+
+    pub type T = i32;
+    pub static bits: uint = ::u32::bits;
+
+    impl Primitive for i32 {
+        #[inline(always)]
+        fn bits() -> uint { 32 }
+
+        #[inline(always)]
+        fn bytes() -> uint { Primitive::bits::<i32>() / 8 }
+    }
+
+    impl BitCount for i32 {
+        /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+        #[inline(always)]
+        fn population_count(&self) -> i32 { unsafe { intrinsics::ctpop32(*self) } }
+
+        /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+        #[inline(always)]
+        fn leading_zeros(&self) -> i32 { unsafe { intrinsics::ctlz32(*self) } }
+
+        /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+        #[inline(always)]
+        fn trailing_zeros(&self) -> i32 { unsafe { intrinsics::cttz32(*self) } }
+    }
+}
diff --git a/src/libstd/num/int-template/i64.rs b/src/libstd/num/int-template/i64.rs
new file mode 100644
index 00000000000..3b51c70be12
--- /dev/null
+++ b/src/libstd/num/int-template/i64.rs
@@ -0,0 +1,41 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations and constants for `i64`
+
+mod inst {
+    use num::{Primitive, BitCount};
+    use unstable::intrinsics;
+
+    pub type T = i64;
+    pub static bits: uint = ::u64::bits;
+
+    impl Primitive for i64 {
+        #[inline(always)]
+        fn bits() -> uint { 64 }
+
+        #[inline(always)]
+        fn bytes() -> uint { Primitive::bits::<i64>() / 8 }
+    }
+
+    impl BitCount for i64 {
+        /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+        #[inline(always)]
+        fn population_count(&self) -> i64 { unsafe { intrinsics::ctpop64(*self) } }
+
+        /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+        #[inline(always)]
+        fn leading_zeros(&self) -> i64 { unsafe { intrinsics::ctlz64(*self) } }
+
+        /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+        #[inline(always)]
+        fn trailing_zeros(&self) -> i64 { unsafe { intrinsics::cttz64(*self) } }
+    }
+}
diff --git a/src/libstd/num/int-template/i8.rs b/src/libstd/num/int-template/i8.rs
new file mode 100644
index 00000000000..896fb4dbf50
--- /dev/null
+++ b/src/libstd/num/int-template/i8.rs
@@ -0,0 +1,41 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations and constants for `i8`
+
+mod inst {
+    use num::{Primitive, BitCount};
+    use unstable::intrinsics;
+
+    pub type T = i8;
+    pub static bits: uint = ::u8::bits;
+
+    impl Primitive for i8 {
+        #[inline(always)]
+        fn bits() -> uint { 8 }
+
+        #[inline(always)]
+        fn bytes() -> uint { Primitive::bits::<i8>() / 8 }
+    }
+
+    impl BitCount for i8 {
+        /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+        #[inline(always)]
+        fn population_count(&self) -> i8 { unsafe { intrinsics::ctpop8(*self) } }
+
+        /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+        #[inline(always)]
+        fn leading_zeros(&self) -> i8 { unsafe { intrinsics::ctlz8(*self) } }
+
+        /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+        #[inline(always)]
+        fn trailing_zeros(&self) -> i8 { unsafe { intrinsics::cttz8(*self) } }
+    }
+}
diff --git a/src/libstd/num/int-template/int.rs b/src/libstd/num/int-template/int.rs
new file mode 100644
index 00000000000..64f6f2d2a9a
--- /dev/null
+++ b/src/libstd/num/int-template/int.rs
@@ -0,0 +1,104 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations and constants for `int`
+
+pub use self::inst::pow;
+
+mod inst {
+    use num::{Primitive, BitCount};
+
+    pub type T = int;
+    pub static bits: uint = ::uint::bits;
+
+    impl Primitive for int {
+        #[cfg(target_word_size = "32")]
+        #[inline(always)]
+        fn bits() -> uint { 32 }
+
+        #[cfg(target_word_size = "64")]
+        #[inline(always)]
+        fn bits() -> uint { 64 }
+
+        #[inline(always)]
+        fn bytes() -> uint { Primitive::bits::<int>() / 8 }
+    }
+
+    #[cfg(target_word_size = "32")]
+    #[inline(always)]
+    impl BitCount for int {
+        /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+        #[inline(always)]
+        fn population_count(&self) -> int { (*self as i32).population_count() as int }
+
+        /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+        #[inline(always)]
+        fn leading_zeros(&self) -> int { (*self as i32).leading_zeros() as int }
+
+        /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+        #[inline(always)]
+        fn trailing_zeros(&self) -> int { (*self as i32).trailing_zeros() as int }
+    }
+
+    #[cfg(target_word_size = "64")]
+    #[inline(always)]
+    impl BitCount for int {
+        /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+        #[inline(always)]
+        fn population_count(&self) -> int { (*self as i64).population_count() as int }
+
+        /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+        #[inline(always)]
+        fn leading_zeros(&self) -> int { (*self as i64).leading_zeros() as int }
+
+        /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+        #[inline(always)]
+        fn trailing_zeros(&self) -> int { (*self as i64).trailing_zeros() as int }
+    }
+
+    /// Returns `base` raised to the power of `exponent`
+    pub fn pow(base: int, exponent: uint) -> int {
+        if exponent == 0u {
+            //Not mathemtically true if ~[base == 0]
+            return 1;
+        }
+        if base == 0 { return 0; }
+        let mut my_pow  = exponent;
+        let mut acc     = 1;
+        let mut multiplier = base;
+        while(my_pow > 0u) {
+            if my_pow % 2u == 1u {
+                acc *= multiplier;
+            }
+            my_pow     /= 2u;
+            multiplier *= multiplier;
+        }
+        return acc;
+    }
+
+    #[test]
+    fn test_pow() {
+        assert_eq!(pow(0, 0u), 1);
+        assert_eq!(pow(0, 1u), 0);
+        assert_eq!(pow(0, 2u), 0);
+        assert_eq!(pow(-1, 0u), 1);
+        assert_eq!(pow(1, 0u), 1);
+        assert_eq!(pow(-3, 2u), 9);
+        assert_eq!(pow(-3, 3u), -27);
+        assert_eq!(pow(4, 9u), 262144);
+    }
+
+    #[test]
+    fn test_overflows() {
+        assert!((::int::max_value > 0));
+        assert!((::int::min_value <= 0));
+        assert_eq!(::int::min_value + ::int::max_value + 1, 0);
+    }
+}
diff --git a/src/libstd/num/num.rs b/src/libstd/num/num.rs
new file mode 100644
index 00000000000..96b302d3174
--- /dev/null
+++ b/src/libstd/num/num.rs
@@ -0,0 +1,494 @@
+// 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.
+
+//! An interface for numeric types
+use cmp::{Eq, ApproxEq, Ord};
+use ops::{Add, Sub, Mul, Div, Rem, Neg};
+use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
+use option::Option;
+use kinds::Copy;
+
+pub mod strconv;
+
+///
+/// The base trait for numeric types
+///
+pub trait Num: Eq + Zero + One
+             + Neg<Self>
+             + Add<Self,Self>
+             + Sub<Self,Self>
+             + Mul<Self,Self>
+             + Div<Self,Self>
+             + Rem<Self,Self> {}
+
+pub trait IntConvertible {
+    fn to_int(&self) -> int;
+    fn from_int(n: int) -> Self;
+}
+
+pub trait Orderable: Ord {
+    // These should be methods on `Ord`, with overridable default implementations. We don't want
+    // to encumber all implementors of Ord by requiring them to implement these functions, but at
+    // the same time we want to be able to take advantage of the speed of the specific numeric
+    // functions (like the `fmin` and `fmax` intrinsics).
+    fn min(&self, other: &Self) -> Self;
+    fn max(&self, other: &Self) -> Self;
+    fn clamp(&self, mn: &Self, mx: &Self) -> Self;
+}
+
+pub trait Zero {
+    fn zero() -> Self;      // FIXME (#5527): This should be an associated constant
+    fn is_zero(&self) -> bool;
+}
+
+pub trait One {
+    fn one() -> Self;       // FIXME (#5527): This should be an associated constant
+}
+
+pub trait Signed: Num
+                + Neg<Self> {
+    fn abs(&self) -> Self;
+    fn abs_sub(&self, other: &Self) -> Self;
+    fn signum(&self) -> Self;
+
+    fn is_positive(&self) -> bool;
+    fn is_negative(&self) -> bool;
+}
+
+pub trait Unsigned: Num {}
+
+// This should be moved into the default implementation for Signed::abs
+pub fn abs<T:Ord + Zero + Neg<T>>(v: T) -> T {
+    if v < Zero::zero() { v.neg() } else { v }
+}
+
+pub trait Integer: Num
+                 + Orderable
+                 + Div<Self,Self>
+                 + Rem<Self,Self> {
+    fn div_rem(&self, other: &Self) -> (Self,Self);
+
+    fn div_floor(&self, other: &Self) -> Self;
+    fn mod_floor(&self, other: &Self) -> Self;
+    fn div_mod_floor(&self, other: &Self) -> (Self,Self);
+
+    fn gcd(&self, other: &Self) -> Self;
+    fn lcm(&self, other: &Self) -> Self;
+
+    fn is_multiple_of(&self, other: &Self) -> bool;
+    fn is_even(&self) -> bool;
+    fn is_odd(&self) -> bool;
+}
+
+pub trait Round {
+    fn floor(&self) -> Self;
+    fn ceil(&self) -> Self;
+    fn round(&self) -> Self;
+    fn trunc(&self) -> Self;
+    fn fract(&self) -> Self;
+}
+
+pub trait Fractional: Num
+                    + Orderable
+                    + Round
+                    + Div<Self,Self> {
+    fn recip(&self) -> Self;
+}
+
+pub trait Algebraic {
+    fn pow(&self, n: Self) -> Self;
+    fn sqrt(&self) -> Self;
+    fn rsqrt(&self) -> Self;
+    fn cbrt(&self) -> Self;
+    fn hypot(&self, other: Self) -> Self;
+}
+
+pub trait Trigonometric {
+    fn sin(&self) -> Self;
+    fn cos(&self) -> Self;
+    fn tan(&self) -> Self;
+    fn asin(&self) -> Self;
+    fn acos(&self) -> Self;
+    fn atan(&self) -> Self;
+    fn atan2(&self, other: Self) -> Self;
+    fn sin_cos(&self) -> (Self, Self);
+}
+
+pub trait Exponential {
+    fn exp(&self) -> Self;
+    fn exp2(&self) -> Self;
+    fn ln(&self) -> Self;
+    fn log(&self, base: Self) -> Self;
+    fn log2(&self) -> Self;
+    fn log10(&self) -> Self;
+}
+
+pub trait Hyperbolic: Exponential {
+    fn sinh(&self) -> Self;
+    fn cosh(&self) -> Self;
+    fn tanh(&self) -> Self;
+    fn asinh(&self) -> Self;
+    fn acosh(&self) -> Self;
+    fn atanh(&self) -> Self;
+}
+
+///
+/// Defines constants and methods common to real numbers
+///
+pub trait Real: Signed
+              + Fractional
+              + Algebraic
+              + Trigonometric
+              + Hyperbolic {
+    // Common Constants
+    // FIXME (#5527): These should be associated constants
+    fn pi() -> Self;
+    fn two_pi() -> Self;
+    fn frac_pi_2() -> Self;
+    fn frac_pi_3() -> Self;
+    fn frac_pi_4() -> Self;
+    fn frac_pi_6() -> Self;
+    fn frac_pi_8() -> Self;
+    fn frac_1_pi() -> Self;
+    fn frac_2_pi() -> Self;
+    fn frac_2_sqrtpi() -> Self;
+    fn sqrt2() -> Self;
+    fn frac_1_sqrt2() -> Self;
+    fn e() -> Self;
+    fn log2_e() -> Self;
+    fn log10_e() -> Self;
+    fn ln_2() -> Self;
+    fn ln_10() -> Self;
+
+    // Angular conversions
+    fn to_degrees(&self) -> Self;
+    fn to_radians(&self) -> Self;
+}
+
+///
+/// Methods that are harder to implement and not commonly used.
+///
+pub trait RealExt: Real {
+    // FIXME (#5527): usages of `int` should be replaced with an associated
+    // integer type once these are implemented
+
+    // Gamma functions
+    fn lgamma(&self) -> (int, Self);
+    fn tgamma(&self) -> Self;
+
+    // Bessel functions
+    fn j0(&self) -> Self;
+    fn j1(&self) -> Self;
+    fn jn(&self, n: int) -> Self;
+    fn y0(&self) -> Self;
+    fn y1(&self) -> Self;
+    fn yn(&self, n: int) -> Self;
+}
+
+///
+/// Collects the bitwise operators under one trait.
+///
+pub trait Bitwise: Not<Self>
+                 + BitAnd<Self,Self>
+                 + BitOr<Self,Self>
+                 + BitXor<Self,Self>
+                 + Shl<Self,Self>
+                 + Shr<Self,Self> {}
+
+pub trait BitCount {
+    fn population_count(&self) -> Self;
+    fn leading_zeros(&self) -> Self;
+    fn trailing_zeros(&self) -> Self;
+}
+
+pub trait Bounded {
+    // FIXME (#5527): These should be associated constants
+    fn min_value() -> Self;
+    fn max_value() -> Self;
+}
+
+///
+/// Specifies the available operations common to all of Rust's core numeric primitives.
+/// These may not always make sense from a purely mathematical point of view, but
+/// may be useful for systems programming.
+///
+pub trait Primitive: Num
+                   + NumCast
+                   + Bounded
+                   + Neg<Self>
+                   + Add<Self,Self>
+                   + Sub<Self,Self>
+                   + Mul<Self,Self>
+                   + Div<Self,Self>
+                   + Rem<Self,Self> {
+    // FIXME (#5527): These should be associated constants
+    fn bits() -> uint;
+    fn bytes() -> uint;
+}
+
+///
+/// A collection of traits relevant to primitive signed and unsigned integers
+///
+pub trait Int: Integer
+             + Primitive
+             + Bitwise
+             + BitCount {}
+
+///
+/// Used for representing the classification of floating point numbers
+///
+#[deriving(Eq)]
+pub enum FPCategory {
+    /// "Not a Number", often obtained by dividing by zero
+    FPNaN,
+    /// Positive or negative infinity
+    FPInfinite ,
+    /// Positive or negative zero
+    FPZero,
+    /// De-normalized floating point representation (less precise than `FPNormal`)
+    FPSubnormal,
+    /// A regular floating point number
+    FPNormal,
+}
+
+///
+/// Primitive floating point numbers
+///
+pub trait Float: Real
+               + Signed
+               + Primitive
+               + ApproxEq<Self> {
+    // FIXME (#5527): These should be associated constants
+    fn NaN() -> Self;
+    fn infinity() -> Self;
+    fn neg_infinity() -> Self;
+    fn neg_zero() -> Self;
+
+    fn is_NaN(&self) -> bool;
+    fn is_infinite(&self) -> bool;
+    fn is_finite(&self) -> bool;
+    fn is_normal(&self) -> bool;
+    fn classify(&self) -> FPCategory;
+
+    fn mantissa_digits() -> uint;
+    fn digits() -> uint;
+    fn epsilon() -> Self;
+    fn min_exp() -> int;
+    fn max_exp() -> int;
+    fn min_10_exp() -> int;
+    fn max_10_exp() -> int;
+
+    fn ldexp(x: Self, exp: int) -> Self;
+    fn frexp(&self) -> (Self, int);
+
+    fn exp_m1(&self) -> Self;
+    fn ln_1p(&self) -> Self;
+    fn mul_add(&self, a: Self, b: Self) -> Self;
+    fn next_after(&self, other: Self) -> Self;
+}
+
+///
+/// Cast from one machine scalar to another
+///
+/// # Example
+///
+/// ~~~
+/// let twenty: f32 = num::cast(0x14);
+/// assert_eq!(twenty, 20f32);
+/// ~~~
+///
+#[inline(always)]
+pub fn cast<T:NumCast,U:NumCast>(n: T) -> U {
+    NumCast::from(n)
+}
+
+///
+/// An interface for casting between machine scalars
+///
+pub trait NumCast {
+    fn from<T:NumCast>(n: T) -> Self;
+
+    fn to_u8(&self) -> u8;
+    fn to_u16(&self) -> u16;
+    fn to_u32(&self) -> u32;
+    fn to_u64(&self) -> u64;
+    fn to_uint(&self) -> uint;
+
+    fn to_i8(&self) -> i8;
+    fn to_i16(&self) -> i16;
+    fn to_i32(&self) -> i32;
+    fn to_i64(&self) -> i64;
+    fn to_int(&self) -> int;
+
+    fn to_f32(&self) -> f32;
+    fn to_f64(&self) -> f64;
+    fn to_float(&self) -> float;
+}
+
+macro_rules! impl_num_cast(
+    ($T:ty, $conv:ident) => (
+        impl NumCast for $T {
+            #[inline(always)]
+            fn from<N:NumCast>(n: N) -> $T {
+                // `$conv` could be generated using `concat_idents!`, but that
+                // macro seems to be broken at the moment
+                n.$conv()
+            }
+
+            #[inline(always)] fn to_u8(&self)    -> u8    { *self as u8    }
+            #[inline(always)] fn to_u16(&self)   -> u16   { *self as u16   }
+            #[inline(always)] fn to_u32(&self)   -> u32   { *self as u32   }
+            #[inline(always)] fn to_u64(&self)   -> u64   { *self as u64   }
+            #[inline(always)] fn to_uint(&self)  -> uint  { *self as uint  }
+
+            #[inline(always)] fn to_i8(&self)    -> i8    { *self as i8    }
+            #[inline(always)] fn to_i16(&self)   -> i16   { *self as i16   }
+            #[inline(always)] fn to_i32(&self)   -> i32   { *self as i32   }
+            #[inline(always)] fn to_i64(&self)   -> i64   { *self as i64   }
+            #[inline(always)] fn to_int(&self)   -> int   { *self as int   }
+
+            #[inline(always)] fn to_f32(&self)   -> f32   { *self as f32   }
+            #[inline(always)] fn to_f64(&self)   -> f64   { *self as f64   }
+            #[inline(always)] fn to_float(&self) -> float { *self as float }
+        }
+    )
+)
+
+impl_num_cast!(u8,    to_u8)
+impl_num_cast!(u16,   to_u16)
+impl_num_cast!(u32,   to_u32)
+impl_num_cast!(u64,   to_u64)
+impl_num_cast!(uint,  to_uint)
+impl_num_cast!(i8,    to_i8)
+impl_num_cast!(i16,   to_i16)
+impl_num_cast!(i32,   to_i32)
+impl_num_cast!(i64,   to_i64)
+impl_num_cast!(int,   to_int)
+impl_num_cast!(f32,   to_f32)
+impl_num_cast!(f64,   to_f64)
+impl_num_cast!(float, to_float)
+
+pub trait ToStrRadix {
+    pub fn to_str_radix(&self, radix: uint) -> ~str;
+}
+
+pub trait FromStrRadix {
+    pub fn from_str_radix(str: &str, radix: uint) -> Option<Self>;
+}
+
+///
+/// Calculates a power to a given radix, optimized for uint `pow` and `radix`.
+///
+/// Returns `radix^pow` as `T`.
+///
+/// Note:
+/// Also returns `1` for `0^0`, despite that technically being an
+/// undefined number. The reason for this is twofold:
+/// - If code written to use this function cares about that special case, it's
+///   probably going to catch it before making the call.
+/// - If code written to use this function doesn't care about it, it's
+///   probably assuming that `x^0` always equals `1`.
+///
+pub fn pow_with_uint<T:NumCast+One+Zero+Copy+Div<T,T>+Mul<T,T>>(radix: uint, pow: uint) -> T {
+    let _0: T = Zero::zero();
+    let _1: T = One::one();
+
+    if pow   == 0u { return _1; }
+    if radix == 0u { return _0; }
+    let mut my_pow     = pow;
+    let mut total      = _1;
+    let mut multiplier = cast(radix);
+    while (my_pow > 0u) {
+        if my_pow % 2u == 1u {
+            total *= multiplier;
+        }
+        my_pow     /= 2u;
+        multiplier *= multiplier;
+    }
+    total
+}
+
+/// Helper function for testing numeric operations
+#[cfg(test)]
+pub fn test_num<T:Num + NumCast>(ten: T, two: T) {
+    assert_eq!(ten.add(&two),  cast(12));
+    assert_eq!(ten.sub(&two),  cast(8));
+    assert_eq!(ten.mul(&two),  cast(20));
+    assert_eq!(ten.div(&two),  cast(5));
+    assert_eq!(ten.rem(&two),  cast(0));
+
+    assert_eq!(ten.add(&two),  ten + two);
+    assert_eq!(ten.sub(&two),  ten - two);
+    assert_eq!(ten.mul(&two),  ten * two);
+    assert_eq!(ten.div(&two),  ten / two);
+    assert_eq!(ten.rem(&two),  ten % two);
+}
+
+macro_rules! test_cast_20(
+    ($_20:expr) => ({
+        let _20 = $_20;
+
+        assert_eq!(20u,   _20.to_uint());
+        assert_eq!(20u8,  _20.to_u8());
+        assert_eq!(20u16, _20.to_u16());
+        assert_eq!(20u32, _20.to_u32());
+        assert_eq!(20u64, _20.to_u64());
+        assert_eq!(20i,   _20.to_int());
+        assert_eq!(20i8,  _20.to_i8());
+        assert_eq!(20i16, _20.to_i16());
+        assert_eq!(20i32, _20.to_i32());
+        assert_eq!(20i64, _20.to_i64());
+        assert_eq!(20f,   _20.to_float());
+        assert_eq!(20f32, _20.to_f32());
+        assert_eq!(20f64, _20.to_f64());
+
+        assert_eq!(_20, NumCast::from(20u));
+        assert_eq!(_20, NumCast::from(20u8));
+        assert_eq!(_20, NumCast::from(20u16));
+        assert_eq!(_20, NumCast::from(20u32));
+        assert_eq!(_20, NumCast::from(20u64));
+        assert_eq!(_20, NumCast::from(20i));
+        assert_eq!(_20, NumCast::from(20i8));
+        assert_eq!(_20, NumCast::from(20i16));
+        assert_eq!(_20, NumCast::from(20i32));
+        assert_eq!(_20, NumCast::from(20i64));
+        assert_eq!(_20, NumCast::from(20f));
+        assert_eq!(_20, NumCast::from(20f32));
+        assert_eq!(_20, NumCast::from(20f64));
+
+        assert_eq!(_20, cast(20u));
+        assert_eq!(_20, cast(20u8));
+        assert_eq!(_20, cast(20u16));
+        assert_eq!(_20, cast(20u32));
+        assert_eq!(_20, cast(20u64));
+        assert_eq!(_20, cast(20i));
+        assert_eq!(_20, cast(20i8));
+        assert_eq!(_20, cast(20i16));
+        assert_eq!(_20, cast(20i32));
+        assert_eq!(_20, cast(20i64));
+        assert_eq!(_20, cast(20f));
+        assert_eq!(_20, cast(20f32));
+        assert_eq!(_20, cast(20f64));
+    })
+)
+
+#[test] fn test_u8_cast()    { test_cast_20!(20u8)  }
+#[test] fn test_u16_cast()   { test_cast_20!(20u16) }
+#[test] fn test_u32_cast()   { test_cast_20!(20u32) }
+#[test] fn test_u64_cast()   { test_cast_20!(20u64) }
+#[test] fn test_uint_cast()  { test_cast_20!(20u)   }
+#[test] fn test_i8_cast()    { test_cast_20!(20i8)  }
+#[test] fn test_i16_cast()   { test_cast_20!(20i16) }
+#[test] fn test_i32_cast()   { test_cast_20!(20i32) }
+#[test] fn test_i64_cast()   { test_cast_20!(20i64) }
+#[test] fn test_int_cast()   { test_cast_20!(20i)   }
+#[test] fn test_f32_cast()   { test_cast_20!(20f32) }
+#[test] fn test_f64_cast()   { test_cast_20!(20f64) }
+#[test] fn test_float_cast() { test_cast_20!(20f)   }
diff --git a/src/libstd/num/rational.rs b/src/libstd/num/rational.rs
deleted file mode 100644
index d57c642c5a2..00000000000
--- a/src/libstd/num/rational.rs
+++ /dev/null
@@ -1,531 +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.
-
-
-//! Rational numbers
-
-use core::num::{Zero,One,ToStrRadix,FromStrRadix,Round};
-use core::from_str::FromStr;
-use super::bigint::BigInt;
-
-/// Represents the ratio between 2 numbers.
-#[deriving(Clone)]
-pub struct Ratio<T> {
-    numer: T,
-    denom: T
-}
-
-/// Alias for a `Ratio` of machine-sized integers.
-pub type Rational = Ratio<int>;
-pub type Rational32 = Ratio<i32>;
-pub type Rational64 = Ratio<i64>;
-
-/// Alias for arbitrary precision rationals.
-pub type BigRational = Ratio<BigInt>;
-
-impl<T: Clone + Integer + Ord>
-    Ratio<T> {
-    /// Create a ratio representing the integer `t`.
-    #[inline(always)]
-    pub fn from_integer(t: T) -> Ratio<T> {
-        Ratio::new_raw(t, One::one())
-    }
-
-    /// Create a ratio without checking for `denom == 0` or reducing.
-    #[inline(always)]
-    pub fn new_raw(numer: T, denom: T) -> Ratio<T> {
-        Ratio { numer: numer, denom: denom }
-    }
-
-    // Create a new Ratio. Fails if `denom == 0`.
-    #[inline(always)]
-    pub fn new(numer: T, denom: T) -> Ratio<T> {
-        if denom == Zero::zero() {
-            fail!("denominator == 0");
-        }
-        let mut ret = Ratio::new_raw(numer, denom);
-        ret.reduce();
-        ret
-    }
-
-    /// Put self into lowest terms, with denom > 0.
-    fn reduce(&mut self) {
-        let g : T = self.numer.gcd(&self.denom);
-
-        // FIXME(#6050): overloaded operators force moves with generic types
-        // self.numer /= g;
-        self.numer = self.numer / g;
-        // FIXME(#6050): overloaded operators force moves with generic types
-        // self.denom /= g;
-        self.denom = self.denom / g;
-
-        // keep denom positive!
-        if self.denom < Zero::zero() {
-            self.numer = -self.numer;
-            self.denom = -self.denom;
-        }
-    }
-
-    /// Return a `reduce`d copy of self.
-    fn reduced(&self) -> Ratio<T> {
-        let mut ret = self.clone();
-        ret.reduce();
-        ret
-    }
-}
-
-/* Comparisons */
-
-// comparing a/b and c/d is the same as comparing a*d and b*c, so we
-// abstract that pattern. The following macro takes a trait and either
-// a comma-separated list of "method name -> return value" or just
-// "method name" (return value is bool in that case)
-macro_rules! cmp_impl {
-    (impl $imp:ident, $($method:ident),+) => {
-        cmp_impl!(impl $imp, $($method -> bool),+)
-    };
-    // return something other than a Ratio<T>
-    (impl $imp:ident, $($method:ident -> $res:ty),+) => {
-        impl<T: Mul<T,T> + $imp> $imp for Ratio<T> {
-            $(
-                #[inline]
-                fn $method(&self, other: &Ratio<T>) -> $res {
-                    (self.numer * other.denom). $method (&(self.denom*other.numer))
-                }
-            )+
-        }
-    };
-}
-cmp_impl!(impl Eq, eq, ne)
-cmp_impl!(impl TotalEq, equals)
-cmp_impl!(impl Ord, lt, gt, le, ge)
-cmp_impl!(impl TotalOrd, cmp -> cmp::Ordering)
-
-/* Arithmetic */
-// a/b * c/d = (a*c)/(b*d)
-impl<T: Clone + Integer + Ord>
-    Mul<Ratio<T>,Ratio<T>> for Ratio<T> {
-    #[inline]
-    fn mul(&self, rhs: &Ratio<T>) -> Ratio<T> {
-        Ratio::new(self.numer * rhs.numer, self.denom * rhs.denom)
-    }
-}
-
-// (a/b) / (c/d) = (a*d)/(b*c)
-impl<T: Clone + Integer + Ord>
-    Div<Ratio<T>,Ratio<T>> for Ratio<T> {
-    #[inline]
-    fn div(&self, rhs: &Ratio<T>) -> Ratio<T> {
-        Ratio::new(self.numer * rhs.denom, self.denom * rhs.numer)
-    }
-}
-
-// Abstracts the a/b `op` c/d = (a*d `op` b*d) / (b*d) pattern
-macro_rules! arith_impl {
-    (impl $imp:ident, $method:ident) => {
-        impl<T: Clone + Integer + Ord>
-            $imp<Ratio<T>,Ratio<T>> for Ratio<T> {
-            #[inline]
-            fn $method(&self, rhs: &Ratio<T>) -> Ratio<T> {
-                Ratio::new((self.numer * rhs.denom).$method(&(self.denom * rhs.numer)),
-                           self.denom * rhs.denom)
-            }
-        }
-    }
-}
-
-// a/b + c/d = (a*d + b*c)/(b*d
-arith_impl!(impl Add, add)
-
-// a/b - c/d = (a*d - b*c)/(b*d)
-arith_impl!(impl Sub, sub)
-
-// a/b % c/d = (a*d % b*c)/(b*d)
-arith_impl!(impl Rem, rem)
-
-impl<T: Clone + Integer + Ord>
-    Neg<Ratio<T>> for Ratio<T> {
-    #[inline]
-    fn neg(&self) -> Ratio<T> {
-        Ratio::new_raw(-self.numer, self.denom.clone())
-    }
-}
-
-/* Constants */
-impl<T: Clone + Integer + Ord>
-    Zero for Ratio<T> {
-    #[inline]
-    fn zero() -> Ratio<T> {
-        Ratio::new_raw(Zero::zero(), One::one())
-    }
-
-    #[inline]
-    fn is_zero(&self) -> bool {
-        *self == Zero::zero()
-    }
-}
-
-impl<T: Clone + Integer + Ord>
-    One for Ratio<T> {
-    #[inline]
-    fn one() -> Ratio<T> {
-        Ratio::new_raw(One::one(), One::one())
-    }
-}
-
-impl<T: Clone + Integer + Ord>
-    Num for Ratio<T> {}
-
-/* Utils */
-impl<T: Clone + Integer + Ord>
-    Round for Ratio<T> {
-
-    fn floor(&self) -> Ratio<T> {
-        if *self < Zero::zero() {
-            Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom)
-        } else {
-            Ratio::from_integer(self.numer / self.denom)
-        }
-    }
-
-    fn ceil(&self) -> Ratio<T> {
-        if *self < Zero::zero() {
-            Ratio::from_integer(self.numer / self.denom)
-        } else {
-            Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom)
-        }
-    }
-
-    #[inline(always)]
-    fn round(&self) -> Ratio<T> {
-        if *self < Zero::zero() {
-            Ratio::from_integer((self.numer - self.denom + One::one()) / self.denom)
-        } else {
-            Ratio::from_integer((self.numer + self.denom - One::one()) / self.denom)
-        }
-    }
-
-    #[inline(always)]
-    fn trunc(&self) -> Ratio<T> {
-        Ratio::from_integer(self.numer / self.denom)
-    }
-
-    fn fract(&self) -> Ratio<T> {
-        Ratio::new_raw(self.numer % self.denom, self.denom.clone())
-    }
-}
-
-impl<T: Clone + Integer + Ord> Fractional for Ratio<T> {
-    #[inline]
-    fn recip(&self) -> Ratio<T> {
-        Ratio::new_raw(self.denom.clone(), self.numer.clone())
-    }
-}
-
-/* String conversions */
-impl<T: ToStr> ToStr for Ratio<T> {
-    /// Renders as `numer/denom`.
-    fn to_str(&self) -> ~str {
-        fmt!("%s/%s", self.numer.to_str(), self.denom.to_str())
-    }
-}
-impl<T: ToStrRadix> ToStrRadix for Ratio<T> {
-    /// Renders as `numer/denom` where the numbers are in base `radix`.
-    fn to_str_radix(&self, radix: uint) -> ~str {
-        fmt!("%s/%s", self.numer.to_str_radix(radix), self.denom.to_str_radix(radix))
-    }
-}
-
-impl<T: FromStr + Clone + Integer + Ord>
-    FromStr for Ratio<T> {
-    /// Parses `numer/denom`.
-    fn from_str(s: &str) -> Option<Ratio<T>> {
-        let split = vec::build(|push| {
-            for str::each_splitn_char(s, '/', 1) |s| {
-                push(s.to_owned());
-            }
-        });
-        if split.len() < 2 { return None; }
-        do FromStr::from_str::<T>(split[0]).chain |a| {
-            do FromStr::from_str::<T>(split[1]).chain |b| {
-                Some(Ratio::new(a.clone(), b.clone()))
-            }
-        }
-    }
-}
-impl<T: FromStrRadix + Clone + Integer + Ord>
-    FromStrRadix for Ratio<T> {
-    /// Parses `numer/denom` where the numbers are in base `radix`.
-    fn from_str_radix(s: &str, radix: uint) -> Option<Ratio<T>> {
-        let split = vec::build(|push| {
-            for str::each_splitn_char(s, '/', 1) |s| {
-                push(s.to_owned());
-            }
-        });
-        if split.len() < 2 { None }
-        else {
-            do FromStrRadix::from_str_radix::<T>(split[0], radix).chain |a| {
-                do FromStrRadix::from_str_radix::<T>(split[1], radix).chain |b| {
-                    Some(Ratio::new(a.clone(), b.clone()))
-                }
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use super::*;
-    use core::num::{Zero,One,FromStrRadix,IntConvertible};
-    use core::from_str::FromStr;
-
-    pub static _0 : Rational = Ratio { numer: 0, denom: 1};
-    pub static _1 : Rational = Ratio { numer: 1, denom: 1};
-    pub static _2: Rational = Ratio { numer: 2, denom: 1};
-    pub static _1_2: Rational = Ratio { numer: 1, denom: 2};
-    pub static _3_2: Rational = Ratio { numer: 3, denom: 2};
-    pub static _neg1_2: Rational =  Ratio { numer: -1, denom: 2};
-
-    pub fn to_big(n: Rational) -> BigRational {
-        Ratio::new(
-            IntConvertible::from_int(n.numer),
-            IntConvertible::from_int(n.denom)
-        )
-    }
-
-    #[test]
-    fn test_test_constants() {
-        // check our constants are what Ratio::new etc. would make.
-        assert_eq!(_0, Zero::zero());
-        assert_eq!(_1, One::one());
-        assert_eq!(_2, Ratio::from_integer(2));
-        assert_eq!(_1_2, Ratio::new(1,2));
-        assert_eq!(_3_2, Ratio::new(3,2));
-        assert_eq!(_neg1_2, Ratio::new(-1,2));
-    }
-
-    #[test]
-    fn test_new_reduce() {
-        let one22 = Ratio::new(2i,2);
-
-        assert_eq!(one22, One::one());
-    }
-    #[test]
-    #[should_fail]
-    fn test_new_zero() {
-        let _a = Ratio::new(1,0);
-    }
-
-
-    #[test]
-    fn test_cmp() {
-        assert!(_0 == _0 && _1 == _1);
-        assert!(_0 != _1 && _1 != _0);
-        assert!(_0 < _1 && !(_1 < _0));
-        assert!(_1 > _0 && !(_0 > _1));
-
-        assert!(_0 <= _0 && _1 <= _1);
-        assert!(_0 <= _1 && !(_1 <= _0));
-
-        assert!(_0 >= _0 && _1 >= _1);
-        assert!(_1 >= _0 && !(_0 >= _1));
-    }
-
-
-    mod arith {
-        use super::*;
-        use super::super::*;
-
-
-        #[test]
-        fn test_add() {
-            fn test(a: Rational, b: Rational, c: Rational) {
-                assert_eq!(a + b, c);
-                assert_eq!(to_big(a) + to_big(b), to_big(c));
-            }
-
-            test(_1, _1_2, _3_2);
-            test(_1, _1, _2);
-            test(_1_2, _3_2, _2);
-            test(_1_2, _neg1_2, _0);
-        }
-
-        #[test]
-        fn test_sub() {
-            fn test(a: Rational, b: Rational, c: Rational) {
-                assert_eq!(a - b, c);
-                assert_eq!(to_big(a) - to_big(b), to_big(c))
-            }
-
-            test(_1, _1_2, _1_2);
-            test(_3_2, _1_2, _1);
-            test(_1, _neg1_2, _3_2);
-        }
-
-        #[test]
-        fn test_mul() {
-            fn test(a: Rational, b: Rational, c: Rational) {
-                assert_eq!(a * b, c);
-                assert_eq!(to_big(a) * to_big(b), to_big(c))
-            }
-
-            test(_1, _1_2, _1_2);
-            test(_1_2, _3_2, Ratio::new(3,4));
-            test(_1_2, _neg1_2, Ratio::new(-1, 4));
-        }
-
-        #[test]
-        fn test_div() {
-            fn test(a: Rational, b: Rational, c: Rational) {
-                assert_eq!(a / b, c);
-                assert_eq!(to_big(a) / to_big(b), to_big(c))
-            }
-
-            test(_1, _1_2, _2);
-            test(_3_2, _1_2, _1 + _2);
-            test(_1, _neg1_2, _neg1_2 + _neg1_2 + _neg1_2 + _neg1_2);
-        }
-
-        #[test]
-        fn test_rem() {
-            fn test(a: Rational, b: Rational, c: Rational) {
-                assert_eq!(a % b, c);
-                assert_eq!(to_big(a) % to_big(b), to_big(c))
-            }
-
-            test(_3_2, _1, _1_2);
-            test(_2, _neg1_2, _0);
-            test(_1_2, _2,  _1_2);
-        }
-
-        #[test]
-        fn test_neg() {
-            fn test(a: Rational, b: Rational) {
-                assert_eq!(-a, b);
-                assert_eq!(-to_big(a), to_big(b))
-            }
-
-            test(_0, _0);
-            test(_1_2, _neg1_2);
-            test(-_1, _1);
-        }
-        #[test]
-        fn test_zero() {
-            assert_eq!(_0 + _0, _0);
-            assert_eq!(_0 * _0, _0);
-            assert_eq!(_0 * _1, _0);
-            assert_eq!(_0 / _neg1_2, _0);
-            assert_eq!(_0 - _0, _0);
-        }
-        #[test]
-        #[should_fail]
-        fn test_div_0() {
-            let _a =  _1 / _0;
-        }
-    }
-
-    #[test]
-    fn test_round() {
-        assert_eq!(_1_2.ceil(), _1);
-        assert_eq!(_1_2.floor(), _0);
-        assert_eq!(_1_2.round(), _1);
-        assert_eq!(_1_2.trunc(), _0);
-
-        assert_eq!(_neg1_2.ceil(), _0);
-        assert_eq!(_neg1_2.floor(), -_1);
-        assert_eq!(_neg1_2.round(), -_1);
-        assert_eq!(_neg1_2.trunc(), _0);
-
-        assert_eq!(_1.ceil(), _1);
-        assert_eq!(_1.floor(), _1);
-        assert_eq!(_1.round(), _1);
-        assert_eq!(_1.trunc(), _1);
-    }
-
-    #[test]
-    fn test_fract() {
-        assert_eq!(_1.fract(), _0);
-        assert_eq!(_neg1_2.fract(), _neg1_2);
-        assert_eq!(_1_2.fract(), _1_2);
-        assert_eq!(_3_2.fract(), _1_2);
-    }
-
-    #[test]
-    fn test_recip() {
-        assert_eq!(_1 * _1.recip(), _1);
-        assert_eq!(_2 * _2.recip(), _1);
-        assert_eq!(_1_2 * _1_2.recip(), _1);
-        assert_eq!(_3_2 * _3_2.recip(), _1);
-        assert_eq!(_neg1_2 * _neg1_2.recip(), _1);
-    }
-
-    #[test]
-    fn test_to_from_str() {
-        fn test(r: Rational, s: ~str) {
-            assert_eq!(FromStr::from_str(s), Some(r));
-            assert_eq!(r.to_str(), s);
-        }
-        test(_1, ~"1/1");
-        test(_0, ~"0/1");
-        test(_1_2, ~"1/2");
-        test(_3_2, ~"3/2");
-        test(_2, ~"2/1");
-        test(_neg1_2, ~"-1/2");
-    }
-    #[test]
-    fn test_from_str_fail() {
-        fn test(s: &str) {
-            assert_eq!(FromStr::from_str::<Rational>(s), None);
-        }
-
-        for ["0 /1", "abc", "", "1/", "--1/2","3/2/1"].each |&s| {
-            test(s);
-        }
-    }
-
-    #[test]
-    fn test_to_from_str_radix() {
-        fn test(r: Rational, s: ~str, n: uint) {
-            assert_eq!(FromStrRadix::from_str_radix(s, n), Some(r));
-            assert_eq!(r.to_str_radix(n), s);
-        }
-        fn test3(r: Rational, s: ~str) { test(r, s, 3) }
-        fn test16(r: Rational, s: ~str) { test(r, s, 16) }
-
-        test3(_1, ~"1/1");
-        test3(_0, ~"0/1");
-        test3(_1_2, ~"1/2");
-        test3(_3_2, ~"10/2");
-        test3(_2, ~"2/1");
-        test3(_neg1_2, ~"-1/2");
-        test3(_neg1_2 / _2, ~"-1/11");
-
-        test16(_1, ~"1/1");
-        test16(_0, ~"0/1");
-        test16(_1_2, ~"1/2");
-        test16(_3_2, ~"3/2");
-        test16(_2, ~"2/1");
-        test16(_neg1_2, ~"-1/2");
-        test16(_neg1_2 / _2, ~"-1/4");
-        test16(Ratio::new(13,15), ~"d/f");
-        test16(_1_2*_1_2*_1_2*_1_2, ~"1/10");
-    }
-
-    #[test]
-    fn test_from_str_radix_fail() {
-        fn test(s: &str) {
-            assert_eq!(FromStrRadix::from_str_radix::<Rational>(s, 3), None);
-        }
-
-        for ["0 /1", "abc", "", "1/", "--1/2","3/2/1", "3/2"].each |&s| {
-            test(s);
-        }
-    }
-}
diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs
new file mode 100644
index 00000000000..1d65b84b7ce
--- /dev/null
+++ b/src/libstd/num/strconv.rs
@@ -0,0 +1,673 @@
+// 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 core::cmp::{Ord, Eq};
+use ops::{Add, Sub, Mul, Div, Rem, Neg};
+use option::{None, Option, Some};
+use char;
+use str;
+use kinds::Copy;
+use vec;
+use vec::{CopyableVector, ImmutableVector};
+use vec::OwnedVector;
+use num::{NumCast, Zero, One, cast, pow_with_uint};
+use f64;
+
+pub enum ExponentFormat {
+    ExpNone,
+    ExpDec,
+    ExpBin
+}
+
+pub enum SignificantDigits {
+    DigAll,
+    DigMax(uint),
+    DigExact(uint)
+}
+
+pub enum SignFormat {
+    SignNone,
+    SignNeg,
+    SignAll
+}
+
+#[inline(always)]
+fn is_NaN<T:Eq>(num: &T) -> bool {
+    *num != *num
+}
+
+#[inline(always)]
+fn is_inf<T:Eq+NumStrConv>(num: &T) -> bool {
+    match NumStrConv::inf() {
+        None    => false,
+        Some(n) => *num == n
+    }
+}
+
+#[inline(always)]
+fn is_neg_inf<T:Eq+NumStrConv>(num: &T) -> bool {
+    match NumStrConv::neg_inf() {
+        None    => false,
+        Some(n) => *num == n
+    }
+}
+
+#[inline(always)]
+fn is_neg_zero<T:Eq+One+Zero+NumStrConv+Div<T,T>>(num: &T) -> bool {
+    let _0: T = Zero::zero();
+    let _1: T = One::one();
+
+    *num == _0 && is_neg_inf(&(_1 / *num))
+}
+
+pub trait NumStrConv {
+    fn NaN()      -> Option<Self>;
+    fn inf()      -> Option<Self>;
+    fn neg_inf()  -> Option<Self>;
+    fn neg_zero() -> Option<Self>;
+
+    fn round_to_zero(&self)   -> Self;
+    fn fractional_part(&self) -> Self;
+}
+
+macro_rules! impl_NumStrConv_Floating (($t:ty) => (
+    impl NumStrConv for $t {
+        #[inline(always)]
+        fn NaN()      -> Option<$t> { Some( 0.0 / 0.0) }
+        #[inline(always)]
+        fn inf()      -> Option<$t> { Some( 1.0 / 0.0) }
+        #[inline(always)]
+        fn neg_inf()  -> Option<$t> { Some(-1.0 / 0.0) }
+        #[inline(always)]
+        fn neg_zero() -> Option<$t> { Some(-0.0      ) }
+
+        #[inline(always)]
+        fn round_to_zero(&self) -> $t {
+            ( if *self < 0.0 { f64::ceil(*self as f64)  }
+              else           { f64::floor(*self as f64) }
+            ) as $t
+        }
+
+        #[inline(always)]
+        fn fractional_part(&self) -> $t {
+            *self - self.round_to_zero()
+        }
+    }
+))
+
+macro_rules! impl_NumStrConv_Integer (($t:ty) => (
+    impl NumStrConv for $t {
+        #[inline(always)] fn NaN()      -> Option<$t> { None }
+        #[inline(always)] fn inf()      -> Option<$t> { None }
+        #[inline(always)] fn neg_inf()  -> Option<$t> { None }
+        #[inline(always)] fn neg_zero() -> Option<$t> { None }
+
+        #[inline(always)] fn round_to_zero(&self)   -> $t { *self }
+        #[inline(always)] fn fractional_part(&self) -> $t {     0 }
+    }
+))
+
+// FIXME: #4955
+// Replace by two generic impls for traits 'Integral' and 'Floating'
+impl_NumStrConv_Floating!(float)
+impl_NumStrConv_Floating!(f32)
+impl_NumStrConv_Floating!(f64)
+
+impl_NumStrConv_Integer!(int)
+impl_NumStrConv_Integer!(i8)
+impl_NumStrConv_Integer!(i16)
+impl_NumStrConv_Integer!(i32)
+impl_NumStrConv_Integer!(i64)
+
+impl_NumStrConv_Integer!(uint)
+impl_NumStrConv_Integer!(u8)
+impl_NumStrConv_Integer!(u16)
+impl_NumStrConv_Integer!(u32)
+impl_NumStrConv_Integer!(u64)
+
+
+// Special value strings as [u8] consts.
+static inf_buf:          [u8, ..3] = ['i' as u8, 'n' as u8, 'f' as u8];
+static positive_inf_buf: [u8, ..4] = ['+' as u8, 'i' as u8, 'n' as u8,
+                                      'f' as u8];
+static negative_inf_buf: [u8, ..4] = ['-' as u8, 'i' as u8, 'n' as u8,
+                                      'f' as u8];
+static nan_buf:          [u8, ..3] = ['N' as u8, 'a' as u8, 'N' as u8];
+
+/**
+ * Converts a number to its string representation as a byte vector.
+ * This is meant to be a common base implementation for all numeric string
+ * conversion functions like `to_str()` or `to_str_radix()`.
+ *
+ * # Arguments
+ * - `num`           - The number to convert. Accepts any number that
+ *                     implements the numeric traits.
+ * - `radix`         - Base to use. Accepts only the values 2-36.
+ * - `negative_zero` - Whether to treat the special value `-0` as
+ *                     `-0` or as `+0`.
+ * - `sign`          - How to emit the sign. Options are:
+ *     - `SignNone`: No sign at all. Basically emits `abs(num)`.
+ *     - `SignNeg`:  Only `-` on negative values.
+ *     - `SignAll`:  Both `+` on positive, and `-` on negative numbers.
+ * - `digits`        - The amount of digits to use for emitting the
+ *                     fractional part, if any. Options are:
+ *     - `DigAll`:         All calculatable digits. Beware of bignums or
+ *                         fractions!
+ *     - `DigMax(uint)`:   Maximum N digits, truncating any trailing zeros.
+ *     - `DigExact(uint)`: Exactly N digits.
+ *
+ * # Return value
+ * A tuple containing the byte vector, and a boolean flag indicating
+ * whether it represents a special value like `inf`, `-inf`, `NaN` or not.
+ * It returns a tuple because there can be ambiguity between a special value
+ * and a number representation at higher bases.
+ *
+ * # Failure
+ * - Fails if `radix` < 2 or `radix` > 36.
+ */
+pub fn to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
+                                  Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
+        num: &T, radix: uint, negative_zero: bool,
+        sign: SignFormat, digits: SignificantDigits) -> (~[u8], bool) {
+    if (radix as int) < 2 {
+        fail!("to_str_bytes_common: radix %? to low, must lie in the range [2, 36]", radix);
+    } else if radix as int > 36 {
+        fail!("to_str_bytes_common: radix %? to high, must lie in the range [2, 36]", radix);
+    }
+
+    let _0: T = Zero::zero();
+    let _1: T = One::one();
+
+    if is_NaN(num) {
+        return (str::to_bytes("NaN"), true);
+    }
+    else if is_inf(num){
+        return match sign {
+            SignAll => (str::to_bytes("+inf"), true),
+            _       => (str::to_bytes("inf"), true)
+        }
+    }
+    else if is_neg_inf(num) {
+        return match sign {
+            SignNone => (str::to_bytes("inf"), true),
+            _        => (str::to_bytes("-inf"), true),
+        }
+    }
+
+    let neg = *num < _0 || (negative_zero && is_neg_zero(num));
+    let mut buf: ~[u8] = ~[];
+    let radix_gen: T   = cast(radix as int);
+
+    let mut deccum;
+
+    // First emit the non-fractional part, looping at least once to make
+    // sure at least a `0` gets emitted.
+    deccum = num.round_to_zero();
+    loop {
+        // Calculate the absolute value of each digit instead of only
+        // doing it once for the whole number because a
+        // representable negative number doesn't necessary have an
+        // representable additive inverse of the same type
+        // (See twos complement). But we assume that for the
+        // numbers [-35 .. 0] we always have [0 .. 35].
+        let current_digit_signed = deccum % radix_gen;
+        let current_digit = if current_digit_signed < _0 {
+            -current_digit_signed
+        } else {
+            current_digit_signed
+        };
+
+        // Decrease the deccumulator one digit at a time
+        deccum /= radix_gen;
+        deccum = deccum.round_to_zero();
+
+        buf.push(char::from_digit(current_digit.to_int() as uint, radix)
+             .unwrap() as u8);
+
+        // No more digits to calculate for the non-fractional part -> break
+        if deccum == _0 { break; }
+    }
+
+    // If limited digits, calculate one digit more for rounding.
+    let (limit_digits, digit_count, exact) = match digits {
+        DigAll          => (false, 0u,      false),
+        DigMax(count)   => (true,  count+1, false),
+        DigExact(count) => (true,  count+1, true)
+    };
+
+    // Decide what sign to put in front
+    match sign {
+        SignNeg | SignAll if neg => {
+            buf.push('-' as u8);
+        }
+        SignAll => {
+            buf.push('+' as u8);
+        }
+        _ => ()
+    }
+
+    vec::reverse(buf);
+
+    // Remember start of the fractional digits.
+    // Points one beyond end of buf if none get generated,
+    // or at the '.' otherwise.
+    let start_fractional_digits = buf.len();
+
+    // Now emit the fractional part, if any
+    deccum = num.fractional_part();
+    if deccum != _0 || (limit_digits && exact && digit_count > 0) {
+        buf.push('.' as u8);
+        let mut dig = 0u;
+
+        // calculate new digits while
+        // - there is no limit and there are digits left
+        // - or there is a limit, it's not reached yet and
+        //   - it's exact
+        //   - or it's a maximum, and there are still digits left
+        while (!limit_digits && deccum != _0)
+           || (limit_digits && dig < digit_count && (
+                   exact
+                || (!exact && deccum != _0)
+              )
+        ) {
+            // Shift first fractional digit into the integer part
+            deccum *= radix_gen;
+
+            // Calculate the absolute value of each digit.
+            // See note in first loop.
+            let current_digit_signed = deccum.round_to_zero();
+            let current_digit = if current_digit_signed < _0 {
+                -current_digit_signed
+            } else {
+                current_digit_signed
+            };
+
+            buf.push(char::from_digit(
+                current_digit.to_int() as uint, radix).unwrap() as u8);
+
+            // Decrease the deccumulator one fractional digit at a time
+            deccum = deccum.fractional_part();
+            dig += 1u;
+        }
+
+        // If digits are limited, and that limit has been reached,
+        // cut off the one extra digit, and depending on its value
+        // round the remaining ones.
+        if limit_digits && dig == digit_count {
+            let ascii2value = |chr: u8| {
+                char::to_digit(chr as char, radix).unwrap() as uint
+            };
+            let value2ascii = |val: uint| {
+                char::from_digit(val, radix).unwrap() as u8
+            };
+
+            let extra_digit = ascii2value(buf.pop());
+            if extra_digit >= radix / 2 { // -> need to round
+                let mut i: int = buf.len() as int - 1;
+                loop {
+                    // If reached left end of number, have to
+                    // insert additional digit:
+                    if i < 0
+                    || buf[i] == '-' as u8
+                    || buf[i] == '+' as u8 {
+                        buf.insert((i + 1) as uint, value2ascii(1));
+                        break;
+                    }
+
+                    // Skip the '.'
+                    if buf[i] == '.' as u8 { i -= 1; loop; }
+
+                    // Either increment the digit,
+                    // or set to 0 if max and carry the 1.
+                    let current_digit = ascii2value(buf[i]);
+                    if current_digit < (radix - 1) {
+                        buf[i] = value2ascii(current_digit+1);
+                        break;
+                    } else {
+                        buf[i] = value2ascii(0);
+                        i -= 1;
+                    }
+                }
+            }
+        }
+    }
+
+    // if number of digits is not exact, remove all trailing '0's up to
+    // and including the '.'
+    if !exact {
+        let buf_max_i = buf.len() - 1;
+
+        // index to truncate from
+        let mut i = buf_max_i;
+
+        // discover trailing zeros of fractional part
+        while i > start_fractional_digits && buf[i] == '0' as u8 {
+            i -= 1;
+        }
+
+        // Only attempt to truncate digits if buf has fractional digits
+        if i >= start_fractional_digits {
+            // If buf ends with '.', cut that too.
+            if buf[i] == '.' as u8 { i -= 1 }
+
+            // only resize buf if we actually remove digits
+            if i < buf_max_i {
+                buf = buf.slice(0, i + 1).to_owned();
+            }
+        }
+    } // If exact and trailing '.', just cut that
+    else {
+        let max_i = buf.len() - 1;
+        if buf[max_i] == '.' as u8 {
+            buf = buf.slice(0, max_i).to_owned();
+        }
+    }
+
+    (buf, false)
+}
+
+/**
+ * Converts a number to its string representation. This is a wrapper for
+ * `to_str_bytes_common()`, for details see there.
+ */
+#[inline(always)]
+pub fn to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Copy+
+                            Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
+        num: &T, radix: uint, negative_zero: bool,
+        sign: SignFormat, digits: SignificantDigits) -> (~str, bool) {
+    let (bytes, special) = to_str_bytes_common(num, radix,
+                               negative_zero, sign, digits);
+    (str::from_bytes(bytes), special)
+}
+
+// Some constants for from_str_bytes_common's input validation,
+// they define minimum radix values for which the character is a valid digit.
+priv static DIGIT_P_RADIX: uint = ('p' as uint) - ('a' as uint) + 11u;
+priv static DIGIT_I_RADIX: uint = ('i' as uint) - ('a' as uint) + 11u;
+priv static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
+
+/**
+ * Parses a byte slice as a number. This is meant to
+ * be a common base implementation for all numeric string conversion
+ * functions like `from_str()` or `from_str_radix()`.
+ *
+ * # Arguments
+ * - `buf`        - The byte slice to parse.
+ * - `radix`      - Which base to parse the number as. Accepts 2-36.
+ * - `negative`   - Whether to accept negative numbers.
+ * - `fractional` - Whether to accept numbers with fractional parts.
+ * - `special`    - Whether to accept special values like `inf`
+ *                  and `NaN`. Can conflict with `radix`, see Failure.
+ * - `exponent`   - Which exponent format to accept. Options are:
+ *     - `ExpNone`: No Exponent, accepts just plain numbers like `42` or
+ *                  `-8.2`.
+ *     - `ExpDec`:  Accepts numbers with a decimal exponent like `42e5` or
+ *                  `8.2E-2`. The exponent string itself is always base 10.
+ *                  Can conflict with `radix`, see Failure.
+ *     - `ExpBin`:  Accepts numbers with a binary exponent like `42P-8` or
+ *                  `FFp128`. The exponent string itself is always base 10.
+ *                  Can conflict with `radix`, see Failure.
+ * - `empty_zero` - Whether to accept a empty `buf` as a 0 or not.
+ * - `ignore_underscores` - Whether all underscores within the string should
+ *                          be ignored.
+ *
+ * # Return value
+ * Returns `Some(n)` if `buf` parses to a number n without overflowing, and
+ * `None` otherwise, depending on the constraints set by the remaining
+ * arguments.
+ *
+ * # Failure
+ * - Fails if `radix` < 2 or `radix` > 36.
+ * - Fails if `radix` > 14 and `exponent` is `ExpDec` due to conflict
+ *   between digit and exponent sign `'e'`.
+ * - Fails if `radix` > 25 and `exponent` is `ExpBin` due to conflict
+ *   between digit and exponent sign `'p'`.
+ * - Fails if `radix` > 18 and `special == true` due to conflict
+ *   between digit and lowest first character in `inf` and `NaN`, the `'i'`.
+ */
+pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
+                                    Mul<T,T>+Sub<T,T>+Neg<T>+Add<T,T>+
+                                    NumStrConv>(
+        buf: &[u8], radix: uint, negative: bool, fractional: bool,
+        special: bool, exponent: ExponentFormat, empty_zero: bool,
+        ignore_underscores: bool
+        ) -> Option<T> {
+    match exponent {
+        ExpDec if radix >= DIGIT_E_RADIX       // decimal exponent 'e'
+          => fail!("from_str_bytes_common: radix %? incompatible with \
+                    use of 'e' as decimal exponent", radix),
+        ExpBin if radix >= DIGIT_P_RADIX       // binary exponent 'p'
+          => fail!("from_str_bytes_common: radix %? incompatible with \
+                    use of 'p' as binary exponent", radix),
+        _ if special && radix >= DIGIT_I_RADIX // first digit of 'inf'
+          => fail!("from_str_bytes_common: radix %? incompatible with \
+                    special values 'inf' and 'NaN'", radix),
+        _ if (radix as int) < 2
+          => fail!("from_str_bytes_common: radix %? to low, \
+                    must lie in the range [2, 36]", radix),
+        _ if (radix as int) > 36
+          => fail!("from_str_bytes_common: radix %? to high, \
+                    must lie in the range [2, 36]", radix),
+        _ => ()
+    }
+
+    let _0: T = Zero::zero();
+    let _1: T = One::one();
+    let radix_gen: T = cast(radix as int);
+
+    let len = buf.len();
+
+    if len == 0 {
+        if empty_zero {
+            return Some(_0);
+        } else {
+            return None;
+        }
+    }
+
+    if special {
+        if buf == inf_buf || buf == positive_inf_buf {
+            return NumStrConv::inf();
+        } else if buf == negative_inf_buf {
+            if negative {
+                return NumStrConv::neg_inf();
+            } else {
+                return None;
+            }
+        } else if buf == nan_buf {
+            return NumStrConv::NaN();
+        }
+    }
+
+    let (start, accum_positive) = match buf[0] as char {
+      '-' if !negative => return None,
+      '-' => (1u, false),
+      '+' => (1u, true),
+       _  => (0u, true)
+    };
+
+    // Initialize accumulator with signed zero for floating point parsing to
+    // work
+    let mut accum      = if accum_positive { _0 } else { -_1 * _0};
+    let mut last_accum = accum; // Necessary to detect overflow
+    let mut i          = start;
+    let mut exp_found  = false;
+
+    // Parse integer part of number
+    while i < len {
+        let c = buf[i] as char;
+
+        match char::to_digit(c, radix) {
+            Some(digit) => {
+                // shift accum one digit left
+                accum *= radix_gen;
+
+                // add/subtract current digit depending on sign
+                if accum_positive {
+                    accum += cast(digit as int);
+                } else {
+                    accum -= cast(digit as int);
+                }
+
+                // Detect overflow by comparing to last value, except
+                // if we've not seen any non-zero digits.
+                if last_accum != _0 {
+                    if accum_positive && accum <= last_accum { return None; }
+                    if !accum_positive && accum >= last_accum { return None; }
+                }
+                last_accum = accum;
+            }
+            None => match c {
+                '_' if ignore_underscores => {}
+                'e' | 'E' | 'p' | 'P' => {
+                    exp_found = true;
+                    break;                       // start of exponent
+                }
+                '.' if fractional => {
+                    i += 1u;                     // skip the '.'
+                    break;                       // start of fractional part
+                }
+                _ => return None                 // invalid number
+            }
+        }
+
+        i += 1u;
+    }
+
+    // Parse fractional part of number
+    // Skip if already reached start of exponent
+    if !exp_found {
+        let mut power = _1;
+
+        while i < len {
+            let c = buf[i] as char;
+
+            match char::to_digit(c, radix) {
+                Some(digit) => {
+                    // Decrease power one order of magnitude
+                    power /= radix_gen;
+
+                    let digit_t: T = cast(digit);
+
+                    // add/subtract current digit depending on sign
+                    if accum_positive {
+                        accum += digit_t * power;
+                    } else {
+                        accum -= digit_t * power;
+                    }
+
+                    // Detect overflow by comparing to last value
+                    if accum_positive && accum < last_accum { return None; }
+                    if !accum_positive && accum > last_accum { return None; }
+                    last_accum = accum;
+                }
+                None => match c {
+                    '_' if ignore_underscores => {}
+                    'e' | 'E' | 'p' | 'P' => {
+                        exp_found = true;
+                        break;                   // start of exponent
+                    }
+                    _ => return None             // invalid number
+                }
+            }
+
+            i += 1u;
+        }
+    }
+
+    // Special case: buf not empty, but does not contain any digit in front
+    // of the exponent sign -> number is empty string
+    if i == start {
+        if empty_zero {
+            return Some(_0);
+        } else {
+            return None;
+        }
+    }
+
+    let mut multiplier = _1;
+
+    if exp_found {
+        let c = buf[i] as char;
+        let base = match (c, exponent) {
+            // c is never _ so don't need to handle specially
+            ('e', ExpDec) | ('E', ExpDec) => 10u,
+            ('p', ExpBin) | ('P', ExpBin) => 2u,
+            _ => return None // char doesn't fit given exponent format
+        };
+
+        // parse remaining bytes as decimal integer,
+        // skipping the exponent char
+        let exp: Option<int> = from_str_bytes_common(
+            buf.slice(i+1, len), 10, true, false, false, ExpNone, false,
+            ignore_underscores);
+
+        match exp {
+            Some(exp_pow) => {
+                multiplier = if exp_pow < 0 {
+                    _1 / pow_with_uint::<T>(base, (-exp_pow.to_int()) as uint)
+                } else {
+                    pow_with_uint::<T>(base, exp_pow.to_int() as uint)
+                }
+            }
+            None => return None // invalid exponent -> invalid number
+        }
+    }
+
+    Some(accum * multiplier)
+}
+
+/**
+ * Parses a string as a number. This is a wrapper for
+ * `from_str_bytes_common()`, for details see there.
+ */
+#[inline(always)]
+pub fn from_str_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+Mul<T,T>+
+                              Sub<T,T>+Neg<T>+Add<T,T>+NumStrConv>(
+        buf: &str, radix: uint, negative: bool, fractional: bool,
+        special: bool, exponent: ExponentFormat, empty_zero: bool,
+        ignore_underscores: bool
+        ) -> Option<T> {
+    from_str_bytes_common(str::to_bytes(buf), radix, negative,
+                          fractional, special, exponent, empty_zero,
+                          ignore_underscores)
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use option::*;
+
+    #[test]
+    fn from_str_ignore_underscores() {
+        let s : Option<u8> = from_str_common("__1__", 2, false, false, false,
+                                             ExpNone, false, true);
+        assert_eq!(s, Some(1u8));
+
+        let n : Option<u8> = from_str_common("__1__", 2, false, false, false,
+                                             ExpNone, false, false);
+        assert_eq!(n, None);
+
+        let f : Option<f32> = from_str_common("_1_._5_e_1_", 10, false, true, false,
+                                              ExpDec, false, true);
+        assert_eq!(f, Some(1.5e1f32));
+    }
+
+    #[test]
+    fn from_str_issue5770() {
+        // try to parse 0b1_1111_1111 = 511 as a u8. Caused problems
+        // since 255*2+1 == 255 (mod 256) so the overflow wasn't
+        // detected.
+        let n : Option<u8> = from_str_common("111111111", 2, false, false, false,
+                                             ExpNone, false, false);
+        assert_eq!(n, None);
+    }
+}
diff --git a/src/libstd/num/uint-template.rs b/src/libstd/num/uint-template.rs
new file mode 100644
index 00000000000..66ff16cbeb1
--- /dev/null
+++ b/src/libstd/num/uint-template.rs
@@ -0,0 +1,641 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use T = self::inst::T;
+use T_SIGNED = self::inst::T_SIGNED;
+
+use num::{ToStrRadix, FromStrRadix};
+use num::{Zero, One, strconv};
+use prelude::*;
+
+pub use cmp::{min, max};
+
+pub static bits : uint = inst::bits;
+pub static bytes : uint = (inst::bits / 8);
+
+pub static min_value: T = 0 as T;
+pub static max_value: T = 0 as T - 1 as T;
+
+#[inline(always)]
+pub fn add(x: T, y: T) -> T { x + y }
+#[inline(always)]
+pub fn sub(x: T, y: T) -> T { x - y }
+#[inline(always)]
+pub fn mul(x: T, y: T) -> T { x * y }
+#[inline(always)]
+pub fn div(x: T, y: T) -> T { x / y }
+#[inline(always)]
+pub fn rem(x: T, y: T) -> T { x % y }
+
+#[inline(always)]
+pub fn lt(x: T, y: T) -> bool { x < y }
+#[inline(always)]
+pub fn le(x: T, y: T) -> bool { x <= y }
+#[inline(always)]
+pub fn eq(x: T, y: T) -> bool { x == y }
+#[inline(always)]
+pub fn ne(x: T, y: T) -> bool { x != y }
+#[inline(always)]
+pub fn ge(x: T, y: T) -> bool { x >= y }
+#[inline(always)]
+pub fn gt(x: T, y: T) -> bool { x > y }
+
+#[inline(always)]
+///
+/// Iterate over the range [`start`,`start`+`step`..`stop`)
+///
+pub fn _range_step(start: T,
+                   stop: T,
+                   step: T_SIGNED,
+                   it: &fn(T) -> bool) -> bool {
+    let mut i = start;
+    if step == 0 {
+        fail!("range_step called with step == 0");
+    }
+    if step >= 0 {
+        while i < stop {
+            if !it(i) { return false; }
+            // avoiding overflow. break if i + step > max_value
+            if i > max_value - (step as T) { return true; }
+            i += step as T;
+        }
+    } else {
+        while i > stop {
+            if !it(i) { return false; }
+            // avoiding underflow. break if i + step < min_value
+            if i < min_value + ((-step) as T) { return true; }
+            i -= -step as T;
+        }
+    }
+    return true;
+}
+
+pub fn range_step(start: T, stop: T, step: T_SIGNED, it: &fn(T) -> bool) -> bool {
+    _range_step(start, stop, step, it)
+}
+
+#[inline(always)]
+/// Iterate over the range [`lo`..`hi`)
+pub fn range(lo: T, hi: T, it: &fn(T) -> bool) -> bool {
+    range_step(lo, hi, 1 as T_SIGNED, it)
+}
+
+#[inline(always)]
+/// Iterate over the range [`hi`..`lo`)
+pub fn range_rev(hi: T, lo: T, it: &fn(T) -> bool) -> bool {
+    range_step(hi, lo, -1 as T_SIGNED, it)
+}
+
+/// Computes the bitwise complement
+#[inline(always)]
+pub fn compl(i: T) -> T {
+    max_value ^ i
+}
+
+impl Num for T {}
+
+#[cfg(not(test))]
+impl Ord for T {
+    #[inline(always)]
+    fn lt(&self, other: &T) -> bool { (*self) < (*other) }
+    #[inline(always)]
+    fn le(&self, other: &T) -> bool { (*self) <= (*other) }
+    #[inline(always)]
+    fn ge(&self, other: &T) -> bool { (*self) >= (*other) }
+    #[inline(always)]
+    fn gt(&self, other: &T) -> bool { (*self) > (*other) }
+}
+
+#[cfg(not(test))]
+impl Eq for T {
+    #[inline(always)]
+    fn eq(&self, other: &T) -> bool { return (*self) == (*other); }
+    #[inline(always)]
+    fn ne(&self, other: &T) -> bool { return (*self) != (*other); }
+}
+
+impl Orderable for T {
+    #[inline(always)]
+    fn min(&self, other: &T) -> T {
+        if *self < *other { *self } else { *other }
+    }
+
+    #[inline(always)]
+    fn max(&self, other: &T) -> T {
+        if *self > *other { *self } else { *other }
+    }
+
+    /// Returns the number constrained within the range `mn <= self <= mx`.
+    #[inline(always)]
+    fn clamp(&self, mn: &T, mx: &T) -> T {
+        cond!(
+            (*self > *mx) { *mx   }
+            (*self < *mn) { *mn   }
+            _             { *self }
+        )
+    }
+}
+
+impl Zero for T {
+    #[inline(always)]
+    fn zero() -> T { 0 }
+
+    #[inline(always)]
+    fn is_zero(&self) -> bool { *self == 0 }
+}
+
+impl One for T {
+    #[inline(always)]
+    fn one() -> T { 1 }
+}
+
+#[cfg(not(test))]
+impl Add<T,T> for T {
+    #[inline(always)]
+    fn add(&self, other: &T) -> T { *self + *other }
+}
+
+#[cfg(not(test))]
+impl Sub<T,T> for T {
+    #[inline(always)]
+    fn sub(&self, other: &T) -> T { *self - *other }
+}
+
+#[cfg(not(test))]
+impl Mul<T,T> for T {
+    #[inline(always)]
+    fn mul(&self, other: &T) -> T { *self * *other }
+}
+
+#[cfg(not(test))]
+impl Div<T,T> for T {
+    #[inline(always)]
+    fn div(&self, other: &T) -> T { *self / *other }
+}
+
+#[cfg(not(test))]
+impl Rem<T,T> for T {
+    #[inline(always)]
+    fn rem(&self, other: &T) -> T { *self % *other }
+}
+
+#[cfg(not(test))]
+impl Neg<T> for T {
+    #[inline(always)]
+    fn neg(&self) -> T { -*self }
+}
+
+impl Unsigned for T {}
+
+impl Integer for T {
+    /// Calculates `div` (`\`) and `rem` (`%`) simultaneously
+    #[inline(always)]
+    fn div_rem(&self, other: &T) -> (T,T) {
+        (*self / *other, *self % *other)
+    }
+
+    /// Unsigned integer division. Returns the same result as `div` (`/`).
+    #[inline(always)]
+    fn div_floor(&self, other: &T) -> T { *self / *other }
+
+    /// Unsigned integer modulo operation. Returns the same result as `rem` (`%`).
+    #[inline(always)]
+    fn mod_floor(&self, other: &T) -> T { *self / *other }
+
+    /// Calculates `div_floor` and `modulo_floor` simultaneously
+    #[inline(always)]
+    fn div_mod_floor(&self, other: &T) -> (T,T) {
+        (*self / *other, *self % *other)
+    }
+
+    /// Calculates the Greatest Common Divisor (GCD) of the number and `other`
+    #[inline(always)]
+    fn gcd(&self, other: &T) -> T {
+        // Use Euclid's algorithm
+        let mut m = *self, n = *other;
+        while m != 0 {
+            let temp = m;
+            m = n % temp;
+            n = temp;
+        }
+        n
+    }
+
+    /// Calculates the Lowest Common Multiple (LCM) of the number and `other`
+    #[inline(always)]
+    fn lcm(&self, other: &T) -> T {
+        (*self * *other) / self.gcd(other)
+    }
+
+    /// Returns `true` if the number can be divided by `other` without leaving a remainder
+    #[inline(always)]
+    fn is_multiple_of(&self, other: &T) -> bool { *self % *other == 0 }
+
+    /// Returns `true` if the number is divisible by `2`
+    #[inline(always)]
+    fn is_even(&self) -> bool { self.is_multiple_of(&2) }
+
+    /// Returns `true` if the number is not divisible by `2`
+    #[inline(always)]
+    fn is_odd(&self) -> bool { !self.is_even() }
+}
+
+impl Bitwise for T {}
+
+#[cfg(not(test))]
+impl BitOr<T,T> for T {
+    #[inline(always)]
+    fn bitor(&self, other: &T) -> T { *self | *other }
+}
+
+#[cfg(not(test))]
+impl BitAnd<T,T> for T {
+    #[inline(always)]
+    fn bitand(&self, other: &T) -> T { *self & *other }
+}
+
+#[cfg(not(test))]
+impl BitXor<T,T> for T {
+    #[inline(always)]
+    fn bitxor(&self, other: &T) -> T { *self ^ *other }
+}
+
+#[cfg(not(test))]
+impl Shl<T,T> for T {
+    #[inline(always)]
+    fn shl(&self, other: &T) -> T { *self << *other }
+}
+
+#[cfg(not(test))]
+impl Shr<T,T> for T {
+    #[inline(always)]
+    fn shr(&self, other: &T) -> T { *self >> *other }
+}
+
+#[cfg(not(test))]
+impl Not<T> for T {
+    #[inline(always)]
+    fn not(&self) -> T { !*self }
+}
+
+impl Bounded for T {
+    #[inline(always)]
+    fn min_value() -> T { min_value }
+
+    #[inline(always)]
+    fn max_value() -> T { max_value }
+}
+
+impl Int for T {}
+
+// String conversion functions and impl str -> num
+
+/// Parse a string as a number in base 10.
+#[inline(always)]
+pub fn from_str(s: &str) -> Option<T> {
+    strconv::from_str_common(s, 10u, false, false, false,
+                             strconv::ExpNone, false, false)
+}
+
+/// Parse a string as a number in the given base.
+#[inline(always)]
+pub fn from_str_radix(s: &str, radix: uint) -> Option<T> {
+    strconv::from_str_common(s, radix, false, false, false,
+                             strconv::ExpNone, false, false)
+}
+
+/// Parse a byte slice as a number in the given base.
+#[inline(always)]
+pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<T> {
+    strconv::from_str_bytes_common(buf, radix, false, false, false,
+                                   strconv::ExpNone, false, false)
+}
+
+impl FromStr for T {
+    #[inline(always)]
+    fn from_str(s: &str) -> Option<T> {
+        from_str(s)
+    }
+}
+
+impl FromStrRadix for T {
+    #[inline(always)]
+    fn from_str_radix(s: &str, radix: uint) -> Option<T> {
+        from_str_radix(s, radix)
+    }
+}
+
+// String conversion functions and impl num -> str
+
+/// Convert to a string as a byte slice in a given base.
+#[inline(always)]
+pub fn to_str_bytes<U>(n: T, radix: uint, f: &fn(v: &[u8]) -> U) -> U {
+    let (buf, _) = strconv::to_str_bytes_common(&n, radix, false,
+                            strconv::SignNeg, strconv::DigAll);
+    f(buf)
+}
+
+/// Convert to a string in base 10.
+#[inline(always)]
+pub fn to_str(num: T) -> ~str {
+    let (buf, _) = strconv::to_str_common(&num, 10u, false,
+                            strconv::SignNeg, strconv::DigAll);
+    buf
+}
+
+/// Convert to a string in a given base.
+#[inline(always)]
+pub fn to_str_radix(num: T, radix: uint) -> ~str {
+    let (buf, _) = strconv::to_str_common(&num, radix, false,
+                            strconv::SignNeg, strconv::DigAll);
+    buf
+}
+
+impl ToStr for T {
+    #[inline(always)]
+    fn to_str(&self) -> ~str {
+        to_str(*self)
+    }
+}
+
+impl ToStrRadix for T {
+    #[inline(always)]
+    fn to_str_radix(&self, radix: uint) -> ~str {
+        to_str_radix(*self, radix)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use super::inst::T;
+    use prelude::*;
+
+    #[test]
+    fn test_num() {
+        num::test_num(10 as T, 2 as T);
+    }
+
+    #[test]
+    fn test_orderable() {
+        assert_eq!((1 as T).min(&(2 as T)), 1 as T);
+        assert_eq!((2 as T).min(&(1 as T)), 1 as T);
+        assert_eq!((1 as T).max(&(2 as T)), 2 as T);
+        assert_eq!((2 as T).max(&(1 as T)), 2 as T);
+        assert_eq!((1 as T).clamp(&(2 as T), &(4 as T)), 2 as T);
+        assert_eq!((8 as T).clamp(&(2 as T), &(4 as T)), 4 as T);
+        assert_eq!((3 as T).clamp(&(2 as T), &(4 as T)), 3 as T);
+    }
+
+    #[test]
+    fn test_gcd() {
+        assert_eq!((10 as T).gcd(&2), 2 as T);
+        assert_eq!((10 as T).gcd(&3), 1 as T);
+        assert_eq!((0 as T).gcd(&3), 3 as T);
+        assert_eq!((3 as T).gcd(&3), 3 as T);
+        assert_eq!((56 as T).gcd(&42), 14 as T);
+    }
+
+    #[test]
+    fn test_lcm() {
+        assert_eq!((1 as T).lcm(&0), 0 as T);
+        assert_eq!((0 as T).lcm(&1), 0 as T);
+        assert_eq!((1 as T).lcm(&1), 1 as T);
+        assert_eq!((8 as T).lcm(&9), 72 as T);
+        assert_eq!((11 as T).lcm(&5), 55 as T);
+        assert_eq!((99 as T).lcm(&17), 1683 as T);
+    }
+
+    #[test]
+    fn test_multiple_of() {
+        assert!((6 as T).is_multiple_of(&(6 as T)));
+        assert!((6 as T).is_multiple_of(&(3 as T)));
+        assert!((6 as T).is_multiple_of(&(1 as T)));
+    }
+
+    #[test]
+    fn test_even() {
+        assert_eq!((0 as T).is_even(), true);
+        assert_eq!((1 as T).is_even(), false);
+        assert_eq!((2 as T).is_even(), true);
+        assert_eq!((3 as T).is_even(), false);
+        assert_eq!((4 as T).is_even(), true);
+    }
+
+    #[test]
+    fn test_odd() {
+        assert_eq!((0 as T).is_odd(), false);
+        assert_eq!((1 as T).is_odd(), true);
+        assert_eq!((2 as T).is_odd(), false);
+        assert_eq!((3 as T).is_odd(), true);
+        assert_eq!((4 as T).is_odd(), false);
+    }
+
+    #[test]
+    fn test_bitwise() {
+        assert_eq!(0b1110 as T, (0b1100 as T).bitor(&(0b1010 as T)));
+        assert_eq!(0b1000 as T, (0b1100 as T).bitand(&(0b1010 as T)));
+        assert_eq!(0b0110 as T, (0b1100 as T).bitxor(&(0b1010 as T)));
+        assert_eq!(0b1110 as T, (0b0111 as T).shl(&(1 as T)));
+        assert_eq!(0b0111 as T, (0b1110 as T).shr(&(1 as T)));
+        assert_eq!(max_value - (0b1011 as T), (0b1011 as T).not());
+    }
+
+    #[test]
+    fn test_bitcount() {
+        assert_eq!((0b010101 as T).population_count(), 3);
+    }
+
+    #[test]
+    fn test_primitive() {
+        assert_eq!(Primitive::bits::<T>(), sys::size_of::<T>() * 8);
+        assert_eq!(Primitive::bytes::<T>(), sys::size_of::<T>());
+    }
+
+    #[test]
+    pub fn test_to_str() {
+        assert_eq!(to_str_radix(0 as T, 10u), ~"0");
+        assert_eq!(to_str_radix(1 as T, 10u), ~"1");
+        assert_eq!(to_str_radix(2 as T, 10u), ~"2");
+        assert_eq!(to_str_radix(11 as T, 10u), ~"11");
+        assert_eq!(to_str_radix(11 as T, 16u), ~"b");
+        assert_eq!(to_str_radix(255 as T, 16u), ~"ff");
+        assert_eq!(to_str_radix(0xff as T, 10u), ~"255");
+    }
+
+    #[test]
+    pub fn test_from_str() {
+        assert_eq!(from_str(~"0"), Some(0u as T));
+        assert_eq!(from_str(~"3"), Some(3u as T));
+        assert_eq!(from_str(~"10"), Some(10u as T));
+        assert_eq!(u32::from_str(~"123456789"), Some(123456789 as u32));
+        assert_eq!(from_str(~"00100"), Some(100u as T));
+
+        assert!(from_str(~"").is_none());
+        assert!(from_str(~" ").is_none());
+        assert!(from_str(~"x").is_none());
+    }
+
+    #[test]
+    pub fn test_parse_bytes() {
+        use str::to_bytes;
+        assert_eq!(parse_bytes(to_bytes(~"123"), 10u), Some(123u as T));
+        assert_eq!(parse_bytes(to_bytes(~"1001"), 2u), Some(9u as T));
+        assert_eq!(parse_bytes(to_bytes(~"123"), 8u), Some(83u as T));
+        assert_eq!(u16::parse_bytes(to_bytes(~"123"), 16u), Some(291u as u16));
+        assert_eq!(u16::parse_bytes(to_bytes(~"ffff"), 16u), Some(65535u as u16));
+        assert_eq!(parse_bytes(to_bytes(~"z"), 36u), Some(35u as T));
+
+        assert!(parse_bytes(to_bytes(~"Z"), 10u).is_none());
+        assert!(parse_bytes(to_bytes(~"_"), 2u).is_none());
+    }
+
+    #[test]
+    fn test_uint_to_str_overflow() {
+        let mut u8_val: u8 = 255_u8;
+        assert_eq!(u8::to_str(u8_val), ~"255");
+
+        u8_val += 1 as u8;
+        assert_eq!(u8::to_str(u8_val), ~"0");
+
+        let mut u16_val: u16 = 65_535_u16;
+        assert_eq!(u16::to_str(u16_val), ~"65535");
+
+        u16_val += 1 as u16;
+        assert_eq!(u16::to_str(u16_val), ~"0");
+
+        let mut u32_val: u32 = 4_294_967_295_u32;
+        assert_eq!(u32::to_str(u32_val), ~"4294967295");
+
+        u32_val += 1 as u32;
+        assert_eq!(u32::to_str(u32_val), ~"0");
+
+        let mut u64_val: u64 = 18_446_744_073_709_551_615_u64;
+        assert_eq!(u64::to_str(u64_val), ~"18446744073709551615");
+
+        u64_val += 1 as u64;
+        assert_eq!(u64::to_str(u64_val), ~"0");
+    }
+
+    #[test]
+    fn test_uint_from_str_overflow() {
+        let mut u8_val: u8 = 255_u8;
+        assert_eq!(u8::from_str(~"255"), Some(u8_val));
+        assert!(u8::from_str(~"256").is_none());
+
+        u8_val += 1 as u8;
+        assert_eq!(u8::from_str(~"0"), Some(u8_val));
+        assert!(u8::from_str(~"-1").is_none());
+
+        let mut u16_val: u16 = 65_535_u16;
+        assert_eq!(u16::from_str(~"65535"), Some(u16_val));
+        assert!(u16::from_str(~"65536").is_none());
+
+        u16_val += 1 as u16;
+        assert_eq!(u16::from_str(~"0"), Some(u16_val));
+        assert!(u16::from_str(~"-1").is_none());
+
+        let mut u32_val: u32 = 4_294_967_295_u32;
+        assert_eq!(u32::from_str(~"4294967295"), Some(u32_val));
+        assert!(u32::from_str(~"4294967296").is_none());
+
+        u32_val += 1 as u32;
+        assert_eq!(u32::from_str(~"0"), Some(u32_val));
+        assert!(u32::from_str(~"-1").is_none());
+
+        let mut u64_val: u64 = 18_446_744_073_709_551_615_u64;
+        assert_eq!(u64::from_str(~"18446744073709551615"), Some(u64_val));
+        assert!(u64::from_str(~"18446744073709551616").is_none());
+
+        u64_val += 1 as u64;
+        assert_eq!(u64::from_str(~"0"), Some(u64_val));
+        assert!(u64::from_str(~"-1").is_none());
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    pub fn to_str_radix1() {
+        uint::to_str_radix(100u, 1u);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    pub fn to_str_radix37() {
+        uint::to_str_radix(100u, 37u);
+    }
+
+    #[test]
+    pub fn test_ranges() {
+        let mut l = ~[];
+
+        for range(0,3) |i| {
+            l.push(i);
+        }
+        for range_rev(13,10) |i| {
+            l.push(i);
+        }
+        for range_step(20,26,2) |i| {
+            l.push(i);
+        }
+        for range_step(36,30,-2) |i| {
+            l.push(i);
+        }
+        for range_step(max_value - 2, max_value, 2) |i| {
+            l.push(i);
+        }
+        for range_step(max_value - 3, max_value, 2) |i| {
+            l.push(i);
+        }
+        for range_step(min_value + 2, min_value, -2) |i| {
+            l.push(i);
+        }
+        for range_step(min_value + 3, min_value, -2) |i| {
+            l.push(i);
+        }
+
+        assert_eq!(l, ~[0,1,2,
+                        13,12,11,
+                        20,22,24,
+                        36,34,32,
+                        max_value-2,
+                        max_value-3,max_value-1,
+                        min_value+2,
+                        min_value+3,min_value+1]);
+
+        // None of the `fail`s should execute.
+        for range(0,0) |_i| {
+            fail!("unreachable");
+        }
+        for range_rev(0,0) |_i| {
+            fail!("unreachable");
+        }
+        for range_step(10,0,1) |_i| {
+            fail!("unreachable");
+        }
+        for range_step(0,1,-10) |_i| {
+            fail!("unreachable");
+        }
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_range_step_zero_step_up() {
+        for range_step(0,10,0) |_i| {}
+    }
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_range_step_zero_step_down() {
+        for range_step(0,-10,0) |_i| {}
+    }
+}
diff --git a/src/libstd/num/uint-template/u16.rs b/src/libstd/num/uint-template/u16.rs
new file mode 100644
index 00000000000..cc262f6b4de
--- /dev/null
+++ b/src/libstd/num/uint-template/u16.rs
@@ -0,0 +1,43 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations and constants for `u16`
+
+mod inst {
+    use num::{Primitive, BitCount};
+    use unstable::intrinsics;
+
+    pub type T = u16;
+    #[allow(non_camel_case_types)]
+    pub type T_SIGNED = i16;
+    pub static bits: uint = 16;
+
+    impl Primitive for u16 {
+        #[inline(always)]
+        fn bits() -> uint { 16 }
+
+        #[inline(always)]
+        fn bytes() -> uint { Primitive::bits::<u16>() / 8 }
+    }
+
+    impl BitCount for u16 {
+        /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+        #[inline(always)]
+        fn population_count(&self) -> u16 { unsafe { intrinsics::ctpop16(*self as i16) as u16 } }
+
+        /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+        #[inline(always)]
+        fn leading_zeros(&self) -> u16 { unsafe { intrinsics::ctlz16(*self as i16) as u16 } }
+
+        /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+        #[inline(always)]
+        fn trailing_zeros(&self) -> u16 { unsafe { intrinsics::cttz16(*self as i16) as u16 } }
+    }
+}
diff --git a/src/libstd/num/uint-template/u32.rs b/src/libstd/num/uint-template/u32.rs
new file mode 100644
index 00000000000..7d7c8e3be30
--- /dev/null
+++ b/src/libstd/num/uint-template/u32.rs
@@ -0,0 +1,43 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations and constants for `u32`
+
+mod inst {
+    use num::{Primitive, BitCount};
+    use unstable::intrinsics;
+
+    pub type T = u32;
+    #[allow(non_camel_case_types)]
+    pub type T_SIGNED = i32;
+    pub static bits: uint = 32;
+
+    impl Primitive for u32 {
+        #[inline(always)]
+        fn bits() -> uint { 32 }
+
+        #[inline(always)]
+        fn bytes() -> uint { Primitive::bits::<u32>() / 8 }
+    }
+
+    impl BitCount for u32 {
+        /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+        #[inline(always)]
+        fn population_count(&self) -> u32 { unsafe { intrinsics::ctpop32(*self as i32) as u32 } }
+
+        /// Counts the number of leading zeros. Wraps LLVM's `ctlp` intrinsic.
+        #[inline(always)]
+        fn leading_zeros(&self) -> u32 { unsafe { intrinsics::ctlz32(*self as i32) as u32 } }
+
+        /// Counts the number of trailing zeros. Wraps LLVM's `cttp` intrinsic.
+        #[inline(always)]
+        fn trailing_zeros(&self) -> u32 { unsafe { intrinsics::cttz32(*self as i32) as u32 } }
+    }
+}
diff --git a/src/libstd/num/uint-template/u64.rs b/src/libstd/num/uint-template/u64.rs
new file mode 100644
index 00000000000..756c29950c3
--- /dev/null
+++ b/src/libstd/num/uint-template/u64.rs
@@ -0,0 +1,43 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations and constants for `u64`
+
+mod inst {
+    use num::{Primitive, BitCount};
+    use unstable::intrinsics;
+
+    pub type T = u64;
+    #[allow(non_camel_case_types)]
+    pub type T_SIGNED = i64;
+    pub static bits: uint = 64;
+
+    impl Primitive for u64 {
+        #[inline(always)]
+        fn bits() -> uint { 64 }
+
+        #[inline(always)]
+        fn bytes() -> uint { Primitive::bits::<u64>() / 8 }
+    }
+
+    impl BitCount for u64 {
+        /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+        #[inline(always)]
+        fn population_count(&self) -> u64 { unsafe { intrinsics::ctpop64(*self as i64) as u64 } }
+
+        /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+        #[inline(always)]
+        fn leading_zeros(&self) -> u64 { unsafe { intrinsics::ctlz64(*self as i64) as u64 } }
+
+        /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+        #[inline(always)]
+        fn trailing_zeros(&self) -> u64 { unsafe { intrinsics::cttz64(*self as i64) as u64 } }
+    }
+}
diff --git a/src/libstd/num/uint-template/u8.rs b/src/libstd/num/uint-template/u8.rs
new file mode 100644
index 00000000000..5ac860c0359
--- /dev/null
+++ b/src/libstd/num/uint-template/u8.rs
@@ -0,0 +1,43 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations and constants for `u8`
+
+mod inst {
+    use num::{Primitive, BitCount};
+    use unstable::intrinsics;
+
+    pub type T = u8;
+    #[allow(non_camel_case_types)]
+    pub type T_SIGNED = i8;
+    pub static bits: uint = 8;
+
+    impl Primitive for u8 {
+        #[inline(always)]
+        fn bits() -> uint { 8 }
+
+        #[inline(always)]
+        fn bytes() -> uint { Primitive::bits::<u8>() / 8 }
+    }
+
+    impl BitCount for u8 {
+        /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+        #[inline(always)]
+        fn population_count(&self) -> u8 { unsafe { intrinsics::ctpop8(*self as i8) as u8 } }
+
+        /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+        #[inline(always)]
+        fn leading_zeros(&self) -> u8 { unsafe { intrinsics::ctlz8(*self as i8) as u8 } }
+
+        /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+        #[inline(always)]
+        fn trailing_zeros(&self) -> u8 { unsafe { intrinsics::cttz8(*self as i8) as u8 } }
+    }
+}
diff --git a/src/libstd/num/uint-template/uint.rs b/src/libstd/num/uint-template/uint.rs
new file mode 100644
index 00000000000..763c305f221
--- /dev/null
+++ b/src/libstd/num/uint-template/uint.rs
@@ -0,0 +1,256 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations and constants for `uint`
+
+pub use self::inst::{
+    div_ceil, div_round, div_floor, iterate,
+    next_power_of_two
+};
+
+pub mod inst {
+    use iter;
+    use num::{Primitive, BitCount};
+    use sys;
+
+    pub type T = uint;
+    #[allow(non_camel_case_types)]
+    pub type T_SIGNED = int;
+
+    #[cfg(target_arch = "x86")]
+    #[cfg(target_arch = "arm")]
+    #[cfg(target_arch = "mips")]
+    pub static bits: uint = 32;
+
+    #[cfg(target_arch = "x86_64")]
+    pub static bits: uint = 64;
+
+    impl Primitive for uint {
+        #[cfg(target_word_size = "32")]
+        #[inline(always)]
+        fn bits() -> uint { 32 }
+
+        #[cfg(target_word_size = "64")]
+        #[inline(always)]
+        fn bits() -> uint { 64 }
+
+        #[inline(always)]
+        fn bytes() -> uint { Primitive::bits::<uint>() / 8 }
+    }
+
+    #[cfg(target_word_size = "32")]
+    #[inline(always)]
+    impl BitCount for uint {
+        /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+        #[inline(always)]
+        fn population_count(&self) -> uint { (*self as i32).population_count() as uint }
+
+        /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+        #[inline(always)]
+        fn leading_zeros(&self) -> uint { (*self as i32).leading_zeros() as uint }
+
+        /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+        #[inline(always)]
+        fn trailing_zeros(&self) -> uint { (*self as i32).trailing_zeros() as uint }
+    }
+
+    #[cfg(target_word_size = "64")]
+    #[inline(always)]
+    impl BitCount for uint {
+        /// Counts the number of bits set. Wraps LLVM's `ctpop` intrinsic.
+        #[inline(always)]
+        fn population_count(&self) -> uint { (*self as i64).population_count() as uint }
+
+        /// Counts the number of leading zeros. Wraps LLVM's `ctlz` intrinsic.
+        #[inline(always)]
+        fn leading_zeros(&self) -> uint { (*self as i64).leading_zeros() as uint }
+
+        /// Counts the number of trailing zeros. Wraps LLVM's `cttz` intrinsic.
+        #[inline(always)]
+        fn trailing_zeros(&self) -> uint { (*self as i64).trailing_zeros() as uint }
+    }
+
+    ///
+    /// Divide two numbers, return the result, rounded up.
+    ///
+    /// # Arguments
+    ///
+    /// * x - an integer
+    /// * y - an integer distinct from 0u
+    ///
+    /// # Return value
+    ///
+    /// The smallest integer `q` such that `x/y <= q`.
+    ///
+    pub fn div_ceil(x: uint, y: uint) -> uint {
+        let div = x / y;
+        if x % y == 0u { div }
+        else { div + 1u }
+    }
+
+    ///
+    /// Divide two numbers, return the result, rounded to the closest integer.
+    ///
+    /// # Arguments
+    ///
+    /// * x - an integer
+    /// * y - an integer distinct from 0u
+    ///
+    /// # Return value
+    ///
+    /// The integer `q` closest to `x/y`.
+    ///
+    pub fn div_round(x: uint, y: uint) -> uint {
+        let div = x / y;
+        if x % y * 2u  < y { div }
+        else { div + 1u }
+    }
+
+    ///
+    /// Divide two numbers, return the result, rounded down.
+    ///
+    /// Note: This is the same function as `div`.
+    ///
+    /// # Arguments
+    ///
+    /// * x - an integer
+    /// * y - an integer distinct from 0u
+    ///
+    /// # Return value
+    ///
+    /// The smallest integer `q` such that `x/y <= q`. This
+    /// is either `x/y` or `x/y + 1`.
+    ///
+    pub fn div_floor(x: uint, y: uint) -> uint { return x / y; }
+
+    ///
+    /// Iterate over the range [`lo`..`hi`), or stop when requested
+    ///
+    /// # Arguments
+    ///
+    /// * lo - The integer at which to start the loop (included)
+    /// * hi - The integer at which to stop the loop (excluded)
+    /// * it - A block to execute with each consecutive integer of the range.
+    ///        Return `true` to continue, `false` to stop.
+    ///
+    /// # Return value
+    ///
+    /// `true` If execution proceeded correctly, `false` if it was interrupted,
+    /// that is if `it` returned `false` at any point.
+    ///
+    pub fn iterate(lo: uint, hi: uint, it: &fn(uint) -> bool) -> bool {
+        let mut i = lo;
+        while i < hi {
+            if (!it(i)) { return false; }
+            i += 1u;
+        }
+        return true;
+    }
+
+    impl iter::Times for uint {
+        #[inline(always)]
+        ///
+        /// A convenience form for basic iteration. Given a uint `x`,
+        /// `for x.times { ... }` executes the given block x times.
+        ///
+        /// Equivalent to `for uint::range(0, x) |_| { ... }`.
+        ///
+        /// Not defined on all integer types to permit unambiguous
+        /// use with integer literals of inferred integer-type as
+        /// the self-value (eg. `for 100.times { ... }`).
+        ///
+        fn times(&self, it: &fn() -> bool) -> bool {
+            let mut i = *self;
+            while i > 0 {
+                if !it() { return false; }
+                i -= 1;
+            }
+            return true;
+        }
+    }
+
+    /// Returns the smallest power of 2 greater than or equal to `n`
+    #[inline(always)]
+    pub fn next_power_of_two(n: uint) -> uint {
+        let halfbits: uint = sys::size_of::<uint>() * 4u;
+        let mut tmp: uint = n - 1u;
+        let mut shift: uint = 1u;
+        while shift <= halfbits { tmp |= tmp >> shift; shift <<= 1u; }
+        return tmp + 1u;
+    }
+
+    #[test]
+    fn test_next_power_of_two() {
+        assert_eq!(next_power_of_two(0u), 0u);
+        assert_eq!(next_power_of_two(1u), 1u);
+        assert_eq!(next_power_of_two(2u), 2u);
+        assert_eq!(next_power_of_two(3u), 4u);
+        assert_eq!(next_power_of_two(4u), 4u);
+        assert_eq!(next_power_of_two(5u), 8u);
+        assert_eq!(next_power_of_two(6u), 8u);
+        assert_eq!(next_power_of_two(7u), 8u);
+        assert_eq!(next_power_of_two(8u), 8u);
+        assert_eq!(next_power_of_two(9u), 16u);
+        assert_eq!(next_power_of_two(10u), 16u);
+        assert_eq!(next_power_of_two(11u), 16u);
+        assert_eq!(next_power_of_two(12u), 16u);
+        assert_eq!(next_power_of_two(13u), 16u);
+        assert_eq!(next_power_of_two(14u), 16u);
+        assert_eq!(next_power_of_two(15u), 16u);
+        assert_eq!(next_power_of_two(16u), 16u);
+        assert_eq!(next_power_of_two(17u), 32u);
+        assert_eq!(next_power_of_two(18u), 32u);
+        assert_eq!(next_power_of_two(19u), 32u);
+        assert_eq!(next_power_of_two(20u), 32u);
+        assert_eq!(next_power_of_two(21u), 32u);
+        assert_eq!(next_power_of_two(22u), 32u);
+        assert_eq!(next_power_of_two(23u), 32u);
+        assert_eq!(next_power_of_two(24u), 32u);
+        assert_eq!(next_power_of_two(25u), 32u);
+        assert_eq!(next_power_of_two(26u), 32u);
+        assert_eq!(next_power_of_two(27u), 32u);
+        assert_eq!(next_power_of_two(28u), 32u);
+        assert_eq!(next_power_of_two(29u), 32u);
+        assert_eq!(next_power_of_two(30u), 32u);
+        assert_eq!(next_power_of_two(31u), 32u);
+        assert_eq!(next_power_of_two(32u), 32u);
+        assert_eq!(next_power_of_two(33u), 64u);
+        assert_eq!(next_power_of_two(34u), 64u);
+        assert_eq!(next_power_of_two(35u), 64u);
+        assert_eq!(next_power_of_two(36u), 64u);
+        assert_eq!(next_power_of_two(37u), 64u);
+        assert_eq!(next_power_of_two(38u), 64u);
+        assert_eq!(next_power_of_two(39u), 64u);
+    }
+
+    #[test]
+    fn test_overflows() {
+        use uint;
+        assert!((uint::max_value > 0u));
+        assert!((uint::min_value <= 0u));
+        assert_eq!(uint::min_value + uint::max_value + 1u, 0u);
+    }
+
+    #[test]
+    fn test_div() {
+        assert_eq!(div_floor(3u, 4u), 0u);
+        assert_eq!(div_ceil(3u, 4u), 1u);
+        assert_eq!(div_round(3u, 4u), 1u);
+    }
+
+    #[test]
+    pub fn test_times() {
+        use iter::Times;
+        let ten = 10 as uint;
+        let mut accum = 0;
+        for ten.times { accum += 1; }
+        assert_eq!(accum, 10);
+    }
+}
diff --git a/src/libstd/old_iter.rs b/src/libstd/old_iter.rs
new file mode 100644
index 00000000000..389b643572c
--- /dev/null
+++ b/src/libstd/old_iter.rs
@@ -0,0 +1,348 @@
+// 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.
+
+/*!
+
+**Deprecated** iteration traits and common implementations.
+
+*/
+
+use cmp::{Eq, Ord};
+use kinds::Copy;
+use option::{None, Option, Some};
+use vec;
+
+/// A function used to initialize the elements of a sequence
+pub type InitOp<'self,T> = &'self fn(uint) -> T;
+
+pub trait BaseIter<A> {
+    fn each(&self, blk: &fn(v: &A) -> bool) -> bool;
+    fn size_hint(&self) -> Option<uint>;
+}
+
+pub trait ReverseIter<A>: BaseIter<A> {
+    fn each_reverse(&self, blk: &fn(&A) -> bool) -> bool;
+}
+
+pub trait MutableIter<A>: BaseIter<A> {
+    fn each_mut(&mut self, blk: &fn(&mut A) -> bool) -> bool;
+}
+
+pub trait ExtendedIter<A> {
+    fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool;
+    fn all(&self, blk: &fn(&A) -> bool) -> bool;
+    fn any(&self, blk: &fn(&A) -> bool) -> bool;
+    fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B;
+    fn position(&self, f: &fn(&A) -> bool) -> Option<uint>;
+    fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B];
+    fn flat_map_to_vec<B,IB: BaseIter<B>>(&self, op: &fn(&A) -> IB) -> ~[B];
+}
+
+pub trait ExtendedMutableIter<A> {
+    fn eachi_mut(&mut self, blk: &fn(uint, &mut A) -> bool) -> bool;
+}
+
+pub trait EqIter<A:Eq> {
+    fn contains(&self, x: &A) -> bool;
+    fn count(&self, x: &A) -> uint;
+}
+
+pub trait CopyableIter<A:Copy> {
+    fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A];
+    fn to_vec(&self) -> ~[A];
+    fn find(&self, p: &fn(&A) -> bool) -> Option<A>;
+}
+
+pub trait CopyableOrderedIter<A:Copy + Ord> {
+    fn min(&self) -> A;
+    fn max(&self) -> A;
+}
+
+pub trait CopyableNonstrictIter<A:Copy> {
+    // Like "each", but copies out the value. If the receiver is mutated while
+    // iterating over it, the semantics must not be memory-unsafe but are
+    // otherwise undefined.
+    fn each_val(&const self, f: &fn(A) -> bool) -> bool;
+}
+
+// A trait for sequences that can be built by imperatively pushing elements
+// onto them.
+pub trait Buildable<A> {
+    /**
+     * Builds a buildable sequence by calling a provided function with
+     * an argument function that pushes an element onto the back of
+     * the sequence.
+     * This version takes an initial size for the sequence.
+     *
+     * # Arguments
+     *
+     * * size - A hint for an initial size of the sequence
+     * * builder - A function that will construct the sequence. It receives
+     *             as an argument a function that will push an element
+     *             onto the sequence being constructed.
+     */
+     fn build_sized(size: uint, builder: &fn(push: &fn(A))) -> Self;
+}
+
+#[inline(always)]
+pub fn _eachi<A,IA:BaseIter<A>>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool {
+    let mut i = 0;
+    for this.each |a| {
+        if !blk(i, a) {
+            return false;
+        }
+        i += 1;
+    }
+    return true;
+}
+
+pub fn eachi<A,IA:BaseIter<A>>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool {
+    _eachi(this, blk)
+}
+
+#[inline(always)]
+pub fn all<A,IA:BaseIter<A>>(this: &IA, blk: &fn(&A) -> bool) -> bool {
+    for this.each |a| {
+        if !blk(a) {
+            return false;
+        }
+    }
+    return true;
+}
+
+#[inline(always)]
+pub fn any<A,IA:BaseIter<A>>(this: &IA, blk: &fn(&A) -> bool) -> bool {
+    for this.each |a| {
+        if blk(a) {
+            return true;
+        }
+    }
+    return false;
+}
+
+#[inline(always)]
+pub fn filter_to_vec<A:Copy,IA:BaseIter<A>>(this: &IA,
+                                            prd: &fn(&A) -> bool)
+                                         -> ~[A] {
+    do vec::build_sized_opt(this.size_hint()) |push| {
+        for this.each |a| {
+            if prd(a) { push(*a); }
+        }
+    }
+}
+
+#[inline(always)]
+pub fn map_to_vec<A,B,IA:BaseIter<A>>(this: &IA, op: &fn(&A) -> B) -> ~[B] {
+    do vec::build_sized_opt(this.size_hint()) |push| {
+        for this.each |a| {
+            push(op(a));
+        }
+    }
+}
+
+#[inline(always)]
+pub fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(this: &IA,
+                                                          op: &fn(&A) -> IB)
+                                                       -> ~[B] {
+    do vec::build |push| {
+        for this.each |a| {
+            for op(a).each |&b| {
+                push(b);
+            }
+        }
+    }
+}
+
+#[inline(always)]
+pub fn foldl<A,B,IA:BaseIter<A>>(this: &IA, b0: B, blk: &fn(&B, &A) -> B)
+                              -> B {
+    let mut b = b0;
+    for this.each |a| {
+        b = blk(&b, a);
+    }
+    b
+}
+
+#[inline(always)]
+pub fn to_vec<A:Copy,IA:BaseIter<A>>(this: &IA) -> ~[A] {
+    map_to_vec(this, |&x| x)
+}
+
+#[inline(always)]
+pub fn contains<A:Eq,IA:BaseIter<A>>(this: &IA, x: &A) -> bool {
+    for this.each |a| {
+        if *a == *x { return true; }
+    }
+    return false;
+}
+
+#[inline(always)]
+pub fn count<A:Eq,IA:BaseIter<A>>(this: &IA, x: &A) -> uint {
+    do foldl(this, 0) |count, value| {
+        if *value == *x {
+            *count + 1
+        } else {
+            *count
+        }
+    }
+}
+
+#[inline(always)]
+pub fn position<A,IA:BaseIter<A>>(this: &IA, f: &fn(&A) -> bool)
+                               -> Option<uint> {
+    let mut i = 0;
+    for this.each |a| {
+        if f(a) { return Some(i); }
+        i += 1;
+    }
+    return None;
+}
+
+// note: 'rposition' would only make sense to provide with a bidirectional
+// iter interface, such as would provide "reach" in addition to "each". As is,
+// it would have to be implemented with foldr, which is too inefficient.
+
+#[inline(always)]
+pub fn min<A:Copy + Ord,IA:BaseIter<A>>(this: &IA) -> A {
+    match do foldl::<A,Option<A>,IA>(this, None) |a, b| {
+        match a {
+          &Some(ref a_) if *a_ < *b => {
+             *(a)
+          }
+          _ => Some(*b)
+        }
+    } {
+        Some(val) => val,
+        None => fail!("min called on empty iterator")
+    }
+}
+
+#[inline(always)]
+pub fn max<A:Copy + Ord,IA:BaseIter<A>>(this: &IA) -> A {
+    match do foldl::<A,Option<A>,IA>(this, None) |a, b| {
+        match a {
+          &Some(ref a_) if *a_ > *b => {
+              *(a)
+          }
+          _ => Some(*b)
+        }
+    } {
+        Some(val) => val,
+        None => fail!("max called on empty iterator")
+    }
+}
+
+#[inline(always)]
+pub fn find<A:Copy,IA:BaseIter<A>>(this: &IA, f: &fn(&A) -> bool)
+                                -> Option<A> {
+    for this.each |i| {
+        if f(i) { return Some(*i) }
+    }
+    return None;
+}
+
+// Some functions for just building
+
+/**
+ * Builds a sequence by calling a provided function with an argument
+ * function that pushes an element to the back of a sequence.
+ *
+ * # Arguments
+ *
+ * * builder - A function that will construct the sequence. It receives
+ *             as an argument a function that will push an element
+ *             onto the sequence being constructed.
+ */
+#[inline(always)]
+pub fn build<A,B: Buildable<A>>(builder: &fn(push: &fn(A))) -> B {
+    Buildable::build_sized(4, builder)
+}
+
+/**
+ * Builds a sequence by calling a provided function with an argument
+ * function that pushes an element to the back of the sequence.
+ * This version takes an initial size for the sequence.
+ *
+ * # Arguments
+ *
+ * * size - An option, maybe containing initial size of the sequence
+ *          to reserve.
+ * * builder - A function that will construct the sequence. It receives
+ *             as an argument a function that will push an element
+ *             onto the sequence being constructed.
+ */
+#[inline(always)]
+pub fn build_sized_opt<A,B: Buildable<A>>(size: Option<uint>,
+                                          builder: &fn(push: &fn(A))) -> B {
+    Buildable::build_sized(size.get_or_default(4), builder)
+}
+
+// Functions that combine iteration and building
+
+/// Applies a function to each element of an iterable and returns the results
+/// in a sequence built via `BU`.  See also `map_to_vec`.
+#[inline(always)]
+pub fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: &IT, f: &fn(&T) -> U)
+    -> BU {
+    do build_sized_opt(v.size_hint()) |push| {
+        for v.each() |elem| {
+            push(f(elem));
+        }
+    }
+}
+
+/**
+ * Creates and initializes a generic sequence from a function.
+ *
+ * Creates a generic sequence of size `n_elts` and initializes the elements
+ * to the value returned by the function `op`.
+ */
+#[inline(always)]
+pub fn from_fn<T,BT: Buildable<T>>(n_elts: uint, op: InitOp<T>) -> BT {
+    do Buildable::build_sized(n_elts) |push| {
+        let mut i: uint = 0u;
+        while i < n_elts { push(op(i)); i += 1u; }
+    }
+}
+
+/**
+ * Creates and initializes a generic sequence with some elements.
+ *
+ * Creates an immutable vector of size `n_elts` and initializes the elements
+ * to the value `t`.
+ */
+#[inline(always)]
+pub fn from_elem<T:Copy,BT:Buildable<T>>(n_elts: uint, t: T) -> BT {
+    do Buildable::build_sized(n_elts) |push| {
+        let mut i: uint = 0;
+        while i < n_elts { push(t); i += 1; }
+    }
+}
+
+/// Appends two generic sequences.
+#[inline(always)]
+pub fn append<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(lhs: &IT, rhs: &IT)
+                                                  -> BT {
+    let size_opt = lhs.size_hint().chain_ref(
+        |sz1| rhs.size_hint().map(|sz2| *sz1+*sz2));
+    do build_sized_opt(size_opt) |push| {
+        for lhs.each |x| { push(*x); }
+        for rhs.each |x| { push(*x); }
+    }
+}
+
+/// Copies a generic sequence, possibly converting it to a different
+/// type of sequence.
+#[inline(always)]
+pub fn copy_seq<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(v: &IT) -> BT {
+    do build_sized_opt(v.size_hint()) |push| {
+        for v.each |x| { push(*x); }
+    }
+}
diff --git a/src/libstd/ops.rs b/src/libstd/ops.rs
new file mode 100644
index 00000000000..47ff45be687
--- /dev/null
+++ b/src/libstd/ops.rs
@@ -0,0 +1,81 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Traits for the built-in operators
+
+#[lang="drop"]
+pub trait Drop {
+    fn finalize(&self);  // FIXME(#4332): Rename to "drop"? --pcwalton
+}
+
+#[lang="add"]
+pub trait Add<RHS,Result> {
+    fn add(&self, rhs: &RHS) -> Result;
+}
+
+#[lang="sub"]
+pub trait Sub<RHS,Result> {
+    fn sub(&self, rhs: &RHS) -> Result;
+}
+
+#[lang="mul"]
+pub trait Mul<RHS,Result> {
+    fn mul(&self, rhs: &RHS) -> Result;
+}
+
+#[lang="div"]
+pub trait Div<RHS,Result> {
+    fn div(&self, rhs: &RHS) -> Result;
+}
+
+#[lang="rem"]
+pub trait Rem<RHS,Result> {
+    fn rem(&self, rhs: &RHS) -> Result;
+}
+
+#[lang="neg"]
+pub trait Neg<Result> {
+    fn neg(&self) -> Result;
+}
+
+#[lang="not"]
+pub trait Not<Result> {
+    fn not(&self) -> Result;
+}
+
+#[lang="bitand"]
+pub trait BitAnd<RHS,Result> {
+    fn bitand(&self, rhs: &RHS) -> Result;
+}
+
+#[lang="bitor"]
+pub trait BitOr<RHS,Result> {
+    fn bitor(&self, rhs: &RHS) -> Result;
+}
+
+#[lang="bitxor"]
+pub trait BitXor<RHS,Result> {
+    fn bitxor(&self, rhs: &RHS) -> Result;
+}
+
+#[lang="shl"]
+pub trait Shl<RHS,Result> {
+    fn shl(&self, rhs: &RHS) -> Result;
+}
+
+#[lang="shr"]
+pub trait Shr<RHS,Result> {
+    fn shr(&self, rhs: &RHS) -> Result;
+}
+
+#[lang="index"]
+pub trait Index<Index,Result> {
+    fn index(&self, index: &Index) -> Result;
+}
diff --git a/src/libstd/option.rs b/src/libstd/option.rs
new file mode 100644
index 00000000000..bc1ffcdc81a
--- /dev/null
+++ b/src/libstd/option.rs
@@ -0,0 +1,468 @@
+// 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.
+
+/*!
+
+Operations on the ubiquitous `Option` type.
+
+Type `Option` represents an optional value.
+
+Every `Option<T>` value can either be `Some(T)` or `None`. Where in other
+languages you might use a nullable type, in Rust you would use an option
+type.
+
+Options are most commonly used with pattern matching to query the presence
+of a value and take action, always accounting for the `None` case.
+
+# Example
+
+~~~
+let msg = Some(~"howdy");
+
+// Take a reference to the contained string
+match msg {
+    Some(ref m) => io::println(m),
+    None => ()
+}
+
+// Remove the contained string, destroying the Option
+let unwrapped_msg = match msg {
+    Some(m) => m,
+    None => ~"default message"
+};
+~~~
+
+*/
+
+use cmp::{Eq,Ord};
+use ops::Add;
+use kinds::Copy;
+use util;
+use num::Zero;
+use old_iter::{BaseIter, MutableIter, ExtendedIter};
+use old_iter;
+use str::StrSlice;
+use clone::DeepClone;
+
+#[cfg(test)] use str;
+
+/// The option type
+#[deriving(Clone, Eq)]
+pub enum Option<T> {
+    None,
+    Some(T),
+}
+
+impl<T: DeepClone> DeepClone for Option<T> {
+    fn deep_clone(&self) -> Option<T> {
+        match *self {
+            Some(ref x) => Some(x.deep_clone()),
+            None => None
+        }
+    }
+}
+
+impl<T:Ord> Ord for Option<T> {
+    fn lt(&self, other: &Option<T>) -> bool {
+        match (self, other) {
+            (&None, &None) => false,
+            (&None, &Some(_)) => true,
+            (&Some(_), &None) => false,
+            (&Some(ref a), &Some(ref b)) => *a < *b
+        }
+    }
+
+    fn le(&self, other: &Option<T>) -> bool {
+        match (self, other) {
+            (&None, &None) => true,
+            (&None, &Some(_)) => true,
+            (&Some(_), &None) => false,
+            (&Some(ref a), &Some(ref b)) => *a <= *b
+        }
+    }
+
+    fn ge(&self, other: &Option<T>) -> bool {
+        !(self < other)
+    }
+
+    fn gt(&self, other: &Option<T>) -> bool {
+        !(self <= other)
+    }
+}
+
+impl<T: Copy + Add<T,T>> Add<Option<T>, Option<T>> for Option<T> {
+    #[inline(always)]
+    fn add(&self, other: &Option<T>) -> Option<T> {
+        match (*self, *other) {
+            (None, None) => None,
+            (_, None) => *self,
+            (None, _) => *other,
+            (Some(ref lhs), Some(ref rhs)) => Some(*lhs + *rhs)
+        }
+    }
+}
+
+impl<T> BaseIter<T> for Option<T> {
+    /// Performs an operation on the contained value by reference
+    #[inline(always)]
+    fn each<'a>(&'a self, f: &fn(x: &'a T) -> bool) -> bool {
+        match *self { None => true, Some(ref t) => { f(t) } }
+    }
+
+    #[inline(always)]
+    fn size_hint(&self) -> Option<uint> {
+        if self.is_some() { Some(1) } else { Some(0) }
+    }
+}
+
+impl<T> MutableIter<T> for Option<T> {
+    #[inline(always)]
+    fn each_mut<'a>(&'a mut self, f: &fn(&'a mut T) -> bool) -> bool {
+        match *self { None => true, Some(ref mut t) => { f(t) } }
+    }
+}
+
+impl<A> ExtendedIter<A> for Option<A> {
+    pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool {
+        old_iter::eachi(self, blk)
+    }
+    pub fn all(&self, blk: &fn(&A) -> bool) -> bool {
+        old_iter::all(self, blk)
+    }
+    pub fn any(&self, blk: &fn(&A) -> bool) -> bool {
+        old_iter::any(self, blk)
+    }
+    pub fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B {
+        old_iter::foldl(self, b0, blk)
+    }
+    pub fn position(&self, f: &fn(&A) -> bool) -> Option<uint> {
+        old_iter::position(self, f)
+    }
+    fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B] {
+        old_iter::map_to_vec(self, op)
+    }
+    fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: &fn(&A) -> IB)
+        -> ~[B] {
+        old_iter::flat_map_to_vec(self, op)
+    }
+}
+
+pub impl<T> Option<T> {
+    /// Returns true if the option equals `none`
+    fn is_none(&const self) -> bool {
+        match *self { None => true, Some(_) => false }
+    }
+
+    /// Returns true if the option contains some value
+    #[inline(always)]
+    fn is_some(&const self) -> bool { !self.is_none() }
+
+    /// Update an optional value by optionally running its content through a
+    /// function that returns an option.
+    #[inline(always)]
+    fn chain<U>(self, f: &fn(t: T) -> Option<U>) -> Option<U> {
+
+        match self {
+            Some(t) => f(t),
+            None => None
+        }
+    }
+
+    /// Returns the leftmost Some() value, or None if both are None.
+    #[inline(always)]
+    fn or(self, optb: Option<T>) -> Option<T> {
+        match self {
+            Some(opta) => Some(opta),
+            _ => optb
+        }
+    }
+
+    /// Update an optional value by optionally running its content by reference
+    /// through a function that returns an option.
+    #[inline(always)]
+    fn chain_ref<'a, U>(&'a self, f: &fn(x: &'a T) -> Option<U>) -> Option<U> {
+        match *self { Some(ref x) => f(x), None => None }
+    }
+
+    /// Maps a `some` value from one type to another by reference
+    #[inline(always)]
+    fn map<'a, U>(&self, f: &fn(&'a T) -> U) -> Option<U> {
+        match *self { Some(ref x) => Some(f(x)), None => None }
+    }
+
+    /// As `map`, but consumes the option and gives `f` ownership to avoid
+    /// copying.
+    #[inline(always)]
+    fn map_consume<U>(self, f: &fn(v: T) -> U) -> Option<U> {
+        match self { None => None, Some(v) => Some(f(v)) }
+    }
+
+    /// Applies a function to the contained value or returns a default
+    #[inline(always)]
+    fn map_default<'a, U>(&'a self, def: U, f: &fn(&'a T) -> U) -> U {
+        match *self { None => def, Some(ref t) => f(t) }
+    }
+
+    /// As `map_default`, but consumes the option and gives `f`
+    /// ownership to avoid copying.
+    #[inline(always)]
+    fn map_consume_default<U>(self, def: U, f: &fn(v: T) -> U) -> U {
+        match self { None => def, Some(v) => f(v) }
+    }
+
+    /// Apply a function to the contained value or do nothing
+    fn mutate(&mut self, f: &fn(T) -> T) {
+        if self.is_some() {
+            *self = Some(f(self.swap_unwrap()));
+        }
+    }
+
+    /// Apply a function to the contained value or set it to a default
+    fn mutate_default(&mut self, def: T, f: &fn(T) -> T) {
+        if self.is_some() {
+            *self = Some(f(self.swap_unwrap()));
+        } else {
+            *self = Some(def);
+        }
+    }
+
+    /**
+    Gets an immutable reference to the value inside an option.
+
+    # Failure
+
+    Fails if the value equals `None`
+
+    # Safety note
+
+    In general, because this function may fail, its use is discouraged
+    (calling `get` on `None` is akin to dereferencing a null pointer).
+    Instead, prefer to use pattern matching and handle the `None`
+    case explicitly.
+     */
+    #[inline(always)]
+    fn get_ref<'a>(&'a self) -> &'a T {
+        match *self {
+          Some(ref x) => x,
+          None => fail!("option::get_ref none")
+        }
+    }
+
+    /**
+    Gets a mutable reference to the value inside an option.
+
+    # Failure
+
+    Fails if the value equals `None`
+
+    # Safety note
+
+    In general, because this function may fail, its use is discouraged
+    (calling `get` on `None` is akin to dereferencing a null pointer).
+    Instead, prefer to use pattern matching and handle the `None`
+    case explicitly.
+     */
+    #[inline(always)]
+    fn get_mut_ref<'a>(&'a mut self) -> &'a mut T {
+        match *self {
+          Some(ref mut x) => x,
+          None => fail!("option::get_mut_ref none")
+        }
+    }
+
+    #[inline(always)]
+    fn unwrap(self) -> T {
+        /*!
+        Moves a value out of an option type and returns it.
+
+        Useful primarily for getting strings, vectors and unique pointers out
+        of option types without copying them.
+
+        # Failure
+
+        Fails if the value equals `None`.
+
+        # Safety note
+
+        In general, because this function may fail, its use is discouraged.
+        Instead, prefer to use pattern matching and handle the `None`
+        case explicitly.
+         */
+        match self {
+          Some(x) => x,
+          None => fail!("option::unwrap none")
+        }
+    }
+
+    /**
+     * The option dance. Moves a value out of an option type and returns it,
+     * replacing the original with `None`.
+     *
+     * # Failure
+     *
+     * Fails if the value equals `None`.
+     */
+    #[inline(always)]
+    fn swap_unwrap(&mut self) -> T {
+        if self.is_none() { fail!("option::swap_unwrap none") }
+        util::replace(self, None).unwrap()
+    }
+
+    /**
+     * Gets the value out of an option, printing a specified message on
+     * failure
+     *
+     * # Failure
+     *
+     * Fails if the value equals `none`
+     */
+    #[inline(always)]
+    fn expect(self, reason: &str) -> T {
+        match self {
+          Some(val) => val,
+          None => fail!(reason.to_owned()),
+        }
+    }
+}
+
+pub impl<T:Copy> Option<T> {
+    /**
+    Gets the value out of an option
+
+    # Failure
+
+    Fails if the value equals `None`
+
+    # Safety note
+
+    In general, because this function may fail, its use is discouraged
+    (calling `get` on `None` is akin to dereferencing a null pointer).
+    Instead, prefer to use pattern matching and handle the `None`
+    case explicitly.
+    */
+    #[inline(always)]
+    fn get(self) -> T {
+        match self {
+          Some(copy x) => return x,
+          None => fail!("option::get none")
+        }
+    }
+
+    /// Returns the contained value or a default
+    #[inline(always)]
+    fn get_or_default(self, def: T) -> T {
+        match self { Some(copy x) => x, None => def }
+    }
+
+    /// Applies a function zero or more times until the result is none.
+    #[inline(always)]
+    fn while_some(self, blk: &fn(v: T) -> Option<T>) {
+        let mut opt = self;
+        while opt.is_some() {
+            opt = blk(opt.unwrap());
+        }
+    }
+}
+
+pub impl<T:Copy + Zero> Option<T> {
+    /// Returns the contained value or zero (for this type)
+    #[inline(always)]
+    fn get_or_zero(self) -> T {
+        match self { Some(copy x) => x, None => Zero::zero() }
+    }
+}
+
+#[test]
+fn test_unwrap_ptr() {
+    unsafe {
+        let x = ~0;
+        let addr_x: *int = ::cast::transmute(&*x);
+        let opt = Some(x);
+        let y = opt.unwrap();
+        let addr_y: *int = ::cast::transmute(&*y);
+        assert_eq!(addr_x, addr_y);
+    }
+}
+
+#[test]
+fn test_unwrap_str() {
+    let x = ~"test";
+    let addr_x = str::as_buf(x, |buf, _len| buf);
+    let opt = Some(x);
+    let y = opt.unwrap();
+    let addr_y = str::as_buf(y, |buf, _len| buf);
+    assert_eq!(addr_x, addr_y);
+}
+
+#[test]
+fn test_unwrap_resource() {
+    struct R {
+       i: @mut int,
+    }
+
+    #[unsafe_destructor]
+    impl ::ops::Drop for R {
+       fn finalize(&self) { *(self.i) += 1; }
+    }
+
+    fn R(i: @mut int) -> R {
+        R {
+            i: i
+        }
+    }
+
+    let i = @mut 0;
+    {
+        let x = R(i);
+        let opt = Some(x);
+        let _y = opt.unwrap();
+    }
+    assert_eq!(*i, 1);
+}
+
+#[test]
+fn test_option_dance() {
+    let x = Some(());
+    let mut y = Some(5);
+    let mut y2 = 0;
+    for x.each |_x| {
+        y2 = y.swap_unwrap();
+    }
+    assert_eq!(y2, 5);
+    assert!(y.is_none());
+}
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_option_too_much_dance() {
+    let mut y = Some(util::NonCopyable());
+    let _y2 = y.swap_unwrap();
+    let _y3 = y.swap_unwrap();
+}
+
+#[test]
+fn test_option_while_some() {
+    let mut i = 0;
+    do Some(10).while_some |j| {
+        i += 1;
+        if (j > 0) {
+            Some(j-1)
+        } else {
+            None
+        }
+    }
+    assert_eq!(i, 11);
+}
+
+#[test]
+fn test_get_or_zero() {
+    let some_stuff = Some(42);
+    assert_eq!(some_stuff.get_or_zero(), 42);
+    let no_stuff: Option<int> = None;
+    assert_eq!(no_stuff.get_or_zero(), 0);
+}
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
new file mode 100644
index 00000000000..b2a30e50992
--- /dev/null
+++ b/src/libstd/os.rs
@@ -0,0 +1,1670 @@
+// 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.
+
+/*!
+ * Higher-level interfaces to libc::* functions and operating system services.
+ *
+ * In general these take and return rust types, use rust idioms (enums,
+ * closures, vectors) rather than C idioms, and do more extensive safety
+ * checks.
+ *
+ * This module is not meant to only contain 1:1 mappings to libc entries; any
+ * os-interface code that is reasonably useful and broadly applicable can go
+ * here. Including utility routines that merely build on other os code.
+ *
+ * We assume the general case is that users do not care, and do not want to
+ * be made to care, which operating system they are on. While they may want
+ * to special case various special cases -- and so we will not _hide_ the
+ * facts of which OS the user is on -- they should be given the opportunity
+ * to write OS-ignorant code by default.
+ */
+
+use cast;
+use io;
+use libc;
+use libc::{c_char, c_void, c_int, size_t};
+use libc::{mode_t, FILE};
+use option;
+use option::{Some, None};
+use prelude::*;
+use ptr;
+use str;
+use uint;
+use unstable::finally::Finally;
+use vec;
+
+pub use libc::fclose;
+pub use os::consts::*;
+
+pub fn close(fd: c_int) -> c_int {
+    unsafe {
+        libc::close(fd)
+    }
+}
+
+pub mod rustrt {
+    use libc::{c_char, c_int};
+    use libc;
+
+    pub extern {
+        unsafe fn rust_get_argc() -> c_int;
+        unsafe fn rust_get_argv() -> **c_char;
+        unsafe fn rust_path_is_dir(path: *libc::c_char) -> c_int;
+        unsafe fn rust_path_exists(path: *libc::c_char) -> c_int;
+        unsafe fn rust_set_exit_status(code: libc::intptr_t);
+    }
+}
+
+pub static TMPBUF_SZ : uint = 1000u;
+static BUF_BYTES : uint = 2048u;
+
+pub fn getcwd() -> Path {
+    let buf = [0 as libc::c_char, ..BUF_BYTES];
+    unsafe {
+        if(0 as *libc::c_char == libc::getcwd(
+            &buf[0],
+            BUF_BYTES as libc::size_t)) {
+            fail!();
+        }
+        Path(str::raw::from_c_str(&buf[0]))
+    }
+}
+
+// FIXME: move these to str perhaps? #2620
+
+pub fn as_c_charp<T>(s: &str, f: &fn(*c_char) -> T) -> T {
+    str::as_c_str(s, |b| f(b as *c_char))
+}
+
+pub fn fill_charp_buf(f: &fn(*mut c_char, size_t) -> bool)
+    -> Option<~str> {
+    let mut buf = vec::from_elem(TMPBUF_SZ, 0u8 as c_char);
+    do vec::as_mut_buf(buf) |b, sz| {
+        if f(b, sz as size_t) {
+            unsafe {
+                Some(str::raw::from_buf(b as *u8))
+            }
+        } else {
+            None
+        }
+    }
+}
+
+#[cfg(windows)]
+pub mod win32 {
+    use libc;
+    use vec;
+    use str;
+    use option::{None, Option};
+    use option;
+    use os::TMPBUF_SZ;
+    use libc::types::os::arch::extra::DWORD;
+
+    pub fn fill_utf16_buf_and_decode(f: &fn(*mut u16, DWORD) -> DWORD)
+        -> Option<~str> {
+        unsafe {
+            let mut n = TMPBUF_SZ as DWORD;
+            let mut res = None;
+            let mut done = false;
+            while !done {
+                let mut k: DWORD = 0;
+                let mut buf = vec::from_elem(n as uint, 0u16);
+                do vec::as_mut_buf(buf) |b, _sz| {
+                    k = f(b, TMPBUF_SZ as DWORD);
+                    if k == (0 as DWORD) {
+                        done = true;
+                    } else if (k == n &&
+                               libc::GetLastError() ==
+                               libc::ERROR_INSUFFICIENT_BUFFER as DWORD) {
+                        n *= (2 as DWORD);
+                    } else {
+                        done = true;
+                    }
+                }
+                if k != 0 && done {
+                    let sub = vec::slice(buf, 0u, k as uint);
+                    res = option::Some(str::from_utf16(sub));
+                }
+            }
+            return res;
+        }
+    }
+
+    pub fn as_utf16_p<T>(s: &str, f: &fn(*u16) -> T) -> T {
+        let mut t = str::to_utf16(s);
+        // Null terminate before passing on.
+        t += ~[0u16];
+        vec::as_imm_buf(t, |buf, _len| f(buf))
+    }
+}
+
+/*
+Accessing environment variables is not generally threadsafe.
+Serialize access through a global lock.
+*/
+fn with_env_lock<T>(f: &fn() -> T) -> T {
+    use unstable::finally::Finally;
+
+    unsafe {
+        return do (|| {
+            rust_take_env_lock();
+            f()
+        }).finally {
+            rust_drop_env_lock();
+        };
+    }
+
+    extern {
+        #[fast_ffi]
+        fn rust_take_env_lock();
+        #[fast_ffi]
+        fn rust_drop_env_lock();
+    }
+}
+
+pub fn env() -> ~[(~str,~str)] {
+    unsafe {
+        #[cfg(windows)]
+        unsafe fn get_env_pairs() -> ~[~str] {
+            use libc::types::os::arch::extra::LPTCH;
+            use libc::funcs::extra::kernel32::{
+                GetEnvironmentStringsA,
+                FreeEnvironmentStringsA
+            };
+            let ch = GetEnvironmentStringsA();
+            if (ch as uint == 0) {
+                fail!("os::env() failure getting env string from OS: %s", os::last_os_error());
+            }
+            let mut curr_ptr: uint = ch as uint;
+            let mut result = ~[];
+            while(*(curr_ptr as *libc::c_char) != 0 as libc::c_char) {
+                let env_pair = str::raw::from_c_str(
+                    curr_ptr as *libc::c_char);
+                result.push(env_pair);
+                curr_ptr +=
+                    libc::strlen(curr_ptr as *libc::c_char) as uint
+                    + 1;
+            }
+            FreeEnvironmentStringsA(ch);
+            result
+        }
+        #[cfg(unix)]
+        unsafe fn get_env_pairs() -> ~[~str] {
+            extern {
+                unsafe fn rust_env_pairs() -> **libc::c_char;
+            }
+            let environ = rust_env_pairs();
+            if (environ as uint == 0) {
+                fail!("os::env() failure getting env string from OS: %s", os::last_os_error());
+            }
+            let mut result = ~[];
+            ptr::array_each(environ, |e| {
+                let env_pair = str::raw::from_c_str(e);
+                debug!("get_env_pairs: %s",
+                       env_pair);
+                result.push(env_pair);
+            });
+            result
+        }
+
+        fn env_convert(input: ~[~str]) -> ~[(~str, ~str)] {
+            let mut pairs = ~[];
+            for input.each |p| {
+                let mut vs = ~[];
+                for str::each_splitn_char(*p, '=', 1) |s| { vs.push(s.to_owned()) }
+                debug!("splitting: len: %u",
+                    vs.len());
+                assert_eq!(vs.len(), 2);
+                pairs.push((copy vs[0], copy vs[1]));
+            }
+            pairs
+        }
+        do with_env_lock {
+            let unparsed_environ = get_env_pairs();
+            env_convert(unparsed_environ)
+        }
+    }
+}
+
+#[cfg(unix)]
+pub fn getenv(n: &str) -> Option<~str> {
+    unsafe {
+        do with_env_lock {
+            let s = str::as_c_str(n, |s| libc::getenv(s));
+            if ptr::null::<u8>() == cast::transmute(s) {
+                option::None::<~str>
+            } else {
+                let s = cast::transmute(s);
+                option::Some::<~str>(str::raw::from_buf(s))
+            }
+        }
+    }
+}
+
+#[cfg(windows)]
+pub fn getenv(n: &str) -> Option<~str> {
+    unsafe {
+        do with_env_lock {
+            use os::win32::{as_utf16_p, fill_utf16_buf_and_decode};
+            do as_utf16_p(n) |u| {
+                do fill_utf16_buf_and_decode() |buf, sz| {
+                    libc::GetEnvironmentVariableW(u, buf, sz)
+                }
+            }
+        }
+    }
+}
+
+
+#[cfg(unix)]
+pub fn setenv(n: &str, v: &str) {
+    unsafe {
+        do with_env_lock {
+            do str::as_c_str(n) |nbuf| {
+                do str::as_c_str(v) |vbuf| {
+                    libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1);
+                }
+            }
+        }
+    }
+}
+
+
+#[cfg(windows)]
+pub fn setenv(n: &str, v: &str) {
+    unsafe {
+        do with_env_lock {
+            use os::win32::as_utf16_p;
+            do as_utf16_p(n) |nbuf| {
+                do as_utf16_p(v) |vbuf| {
+                    libc::SetEnvironmentVariableW(nbuf, vbuf);
+                }
+            }
+        }
+    }
+}
+
+/// Remove a variable from the environment entirely
+pub fn unsetenv(n: &str) {
+    #[cfg(unix)]
+    fn _unsetenv(n: &str) {
+        unsafe {
+            do with_env_lock {
+                do str::as_c_str(n) |nbuf| {
+                    libc::funcs::posix01::unistd::unsetenv(nbuf);
+                }
+            }
+        }
+    }
+    #[cfg(windows)]
+    fn _unsetenv(n: &str) {
+        unsafe {
+            do with_env_lock {
+                use os::win32::as_utf16_p;
+                do as_utf16_p(n) |nbuf| {
+                    libc::SetEnvironmentVariableW(nbuf, ptr::null());
+                }
+            }
+        }
+    }
+
+    _unsetenv(n);
+}
+
+pub fn fdopen(fd: c_int) -> *FILE {
+    unsafe {
+        return do as_c_charp("r") |modebuf| {
+            libc::fdopen(fd, modebuf)
+        };
+    }
+}
+
+
+// fsync related
+
+#[cfg(windows)]
+pub fn fsync_fd(fd: c_int, _level: io::fsync::Level) -> c_int {
+    unsafe {
+        use libc::funcs::extra::msvcrt::*;
+        return commit(fd);
+    }
+}
+
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "android")]
+pub fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
+    unsafe {
+        use libc::funcs::posix01::unistd::*;
+        match level {
+          io::fsync::FSync
+          | io::fsync::FullFSync => return fsync(fd),
+          io::fsync::FDataSync => return fdatasync(fd)
+        }
+    }
+}
+
+#[cfg(target_os = "macos")]
+pub fn fsync_fd(fd: c_int, level: io::fsync::Level) -> c_int {
+    unsafe {
+        use libc::consts::os::extra::*;
+        use libc::funcs::posix88::fcntl::*;
+        use libc::funcs::posix01::unistd::*;
+        match level {
+          io::fsync::FSync => return fsync(fd),
+          _ => {
+            // According to man fnctl, the ok retval is only specified to be
+            // !=-1
+            if (fcntl(F_FULLFSYNC as c_int, fd) == -1 as c_int)
+                { return -1 as c_int; }
+            else
+                { return 0 as c_int; }
+          }
+        }
+    }
+}
+
+#[cfg(target_os = "freebsd")]
+pub fn fsync_fd(fd: c_int, _l: io::fsync::Level) -> c_int {
+    unsafe {
+        use libc::funcs::posix01::unistd::*;
+        return fsync(fd);
+    }
+}
+
+pub struct Pipe {
+    in: c_int,
+    out: c_int
+}
+
+#[cfg(unix)]
+pub fn pipe() -> Pipe {
+    unsafe {
+        let mut fds = Pipe {in: 0 as c_int,
+                            out: 0 as c_int };
+        assert_eq!(libc::pipe(&mut fds.in), (0 as c_int));
+        return Pipe {in: fds.in, out: fds.out};
+    }
+}
+
+
+
+#[cfg(windows)]
+pub fn pipe() -> Pipe {
+    unsafe {
+        // Windows pipes work subtly differently than unix pipes, and their
+        // inheritance has to be handled in a different way that I do not
+        // fully understand. Here we explicitly make the pipe non-inheritable,
+        // which means to pass it to a subprocess they need to be duplicated
+        // first, as in core::run.
+        let mut fds = Pipe {in: 0 as c_int,
+                    out: 0 as c_int };
+        let res = libc::pipe(&mut fds.in, 1024 as ::libc::c_uint,
+                             (libc::O_BINARY | libc::O_NOINHERIT) as c_int);
+        assert_eq!(res, 0 as c_int);
+        assert!((fds.in != -1 as c_int && fds.in != 0 as c_int));
+        assert!((fds.out != -1 as c_int && fds.in != 0 as c_int));
+        return Pipe {in: fds.in, out: fds.out};
+    }
+}
+
+fn dup2(src: c_int, dst: c_int) -> c_int {
+    unsafe {
+        libc::dup2(src, dst)
+    }
+}
+
+
+pub fn dll_filename(base: &str) -> ~str {
+    return str::to_owned(DLL_PREFIX) + str::to_owned(base) +
+           str::to_owned(DLL_SUFFIX)
+}
+
+
+pub fn self_exe_path() -> Option<Path> {
+
+    #[cfg(target_os = "freebsd")]
+    fn load_self() -> Option<~str> {
+        unsafe {
+            use libc::funcs::bsd44::*;
+            use libc::consts::os::extra::*;
+            do fill_charp_buf() |buf, sz| {
+                let mib = ~[CTL_KERN as c_int,
+                           KERN_PROC as c_int,
+                           KERN_PROC_PATHNAME as c_int, -1 as c_int];
+                let mut sz = sz;
+                sysctl(vec::raw::to_ptr(mib), mib.len() as ::libc::c_uint,
+                       buf as *mut c_void, &mut sz, ptr::null(),
+                       0u as size_t) == (0 as c_int)
+            }
+        }
+    }
+
+    #[cfg(target_os = "linux")]
+    #[cfg(target_os = "android")]
+    fn load_self() -> Option<~str> {
+        unsafe {
+            use libc::funcs::posix01::unistd::readlink;
+
+            let mut path_str = str::with_capacity(TMPBUF_SZ);
+            let len = do str::as_c_str(path_str) |buf| {
+                let buf = buf as *mut c_char;
+                do as_c_charp("/proc/self/exe") |proc_self_buf| {
+                    readlink(proc_self_buf, buf, TMPBUF_SZ as size_t)
+                }
+            };
+            if len == -1 {
+                None
+            } else {
+                str::raw::set_len(&mut path_str, len as uint);
+                Some(path_str)
+            }
+        }
+    }
+
+    #[cfg(target_os = "macos")]
+    fn load_self() -> Option<~str> {
+        unsafe {
+            do fill_charp_buf() |buf, sz| {
+                let mut sz = sz as u32;
+                libc::funcs::extra::_NSGetExecutablePath(
+                    buf, &mut sz) == (0 as c_int)
+            }
+        }
+    }
+
+    #[cfg(windows)]
+    fn load_self() -> Option<~str> {
+        unsafe {
+            use os::win32::fill_utf16_buf_and_decode;
+            do fill_utf16_buf_and_decode() |buf, sz| {
+                libc::GetModuleFileNameW(0u as libc::DWORD, buf, sz)
+            }
+        }
+    }
+
+    do load_self().map |pth| {
+        Path(*pth).dir_path()
+    }
+}
+
+
+/**
+ * Returns the path to the user's home directory, if known.
+ *
+ * On Unix, returns the value of the 'HOME' environment variable if it is set
+ * and not equal to the empty string.
+ *
+ * On Windows, returns the value of the 'HOME' environment variable if it is
+ * set and not equal to the empty string. Otherwise, returns the value of the
+ * 'USERPROFILE' environment variable if it is set and not equal to the empty
+ * string.
+ *
+ * Otherwise, homedir returns option::none.
+ */
+pub fn homedir() -> Option<Path> {
+    return match getenv("HOME") {
+        Some(ref p) => if !str::is_empty(*p) {
+          Some(Path(*p))
+        } else {
+          secondary()
+        },
+        None => secondary()
+    };
+
+    #[cfg(unix)]
+    fn secondary() -> Option<Path> {
+        None
+    }
+
+    #[cfg(windows)]
+    fn secondary() -> Option<Path> {
+        do getenv(~"USERPROFILE").chain |p| {
+            if !str::is_empty(p) {
+                Some(Path(p))
+            } else {
+                None
+            }
+        }
+    }
+}
+
+/**
+ * Returns the path to a temporary directory.
+ *
+ * On Unix, returns the value of the 'TMPDIR' environment variable if it is
+ * set and non-empty and '/tmp' otherwise.
+ *
+ * On Windows, returns the value of, in order, the 'TMP', 'TEMP',
+ * 'USERPROFILE' environment variable  if any are set and not the empty
+ * string. Otherwise, tmpdir returns the path to the Windows directory.
+ */
+pub fn tmpdir() -> Path {
+    return lookup();
+
+    fn getenv_nonempty(v: &str) -> Option<Path> {
+        match getenv(v) {
+            Some(x) =>
+                if str::is_empty(x) {
+                    None
+                } else {
+                    Some(Path(x))
+                },
+            _ => None
+        }
+    }
+
+    #[cfg(unix)]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn lookup() -> Path {
+        getenv_nonempty("TMPDIR").get_or_default(Path("/tmp"))
+    }
+
+    #[cfg(windows)]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn lookup() -> Path {
+        getenv_nonempty("TMP").or(
+            getenv_nonempty("TEMP").or(
+                getenv_nonempty("USERPROFILE").or(
+                   getenv_nonempty("WINDIR")))).get_or_default(Path("C:\\Windows"))
+    }
+}
+
+/// Recursively walk a directory structure
+pub fn walk_dir(p: &Path, f: &fn(&Path) -> bool) -> bool {
+    list_dir(p).each(|q| {
+        let path = &p.push(*q);
+        f(path) && (!path_is_dir(path) || walk_dir(path, f))
+    })
+}
+
+/// Indicates whether a path represents a directory
+pub fn path_is_dir(p: &Path) -> bool {
+    unsafe {
+        do str::as_c_str(p.to_str()) |buf| {
+            rustrt::rust_path_is_dir(buf) != 0 as c_int
+        }
+    }
+}
+
+/// Indicates whether a path exists
+pub fn path_exists(p: &Path) -> bool {
+    unsafe {
+        do str::as_c_str(p.to_str()) |buf| {
+            rustrt::rust_path_exists(buf) != 0 as c_int
+        }
+    }
+}
+
+/**
+ * Convert a relative path to an absolute path
+ *
+ * If the given path is relative, return it prepended with the current working
+ * directory. If the given path is already an absolute path, return it
+ * as is.
+ */
+// NB: this is here rather than in path because it is a form of environment
+// querying; what it does depends on the process working directory, not just
+// the input paths.
+pub fn make_absolute(p: &Path) -> Path {
+    if p.is_absolute {
+        copy *p
+    } else {
+        getcwd().push_many(p.components)
+    }
+}
+
+
+/// 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.to_str()) |buf| {
+                libc::CreateDirectoryW(buf, unsafe {
+                    cast::transmute(0)
+                })
+                    != (0 as libc::BOOL)
+            }
+        }
+    }
+
+    #[cfg(unix)]
+    fn mkdir(p: &Path, mode: c_int) -> bool {
+        unsafe {
+            do as_c_charp(p.to_str()) |c| {
+                libc::mkdir(c, mode as 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;
+    }
+    else if p.components.is_empty() {
+        return false;
+    }
+    else if p.components.len() == 1 {
+        // No parent directories to create
+        path_is_dir(p) || make_dir(p, mode)
+    }
+    else {
+        mkdir_recursive(&p.pop(), mode) && make_dir(p, mode)
+    }
+}
+
+/// Lists the contents of a directory
+#[allow(non_implicitly_copyable_typarams)]
+pub fn list_dir(p: &Path) -> ~[~str] {
+    unsafe {
+        #[cfg(target_os = "linux")]
+        #[cfg(target_os = "android")]
+        #[cfg(target_os = "freebsd")]
+        #[cfg(target_os = "macos")]
+        unsafe fn get_list(p: &Path) -> ~[~str] {
+            use libc::{dirent_t};
+            use libc::{opendir, readdir, closedir};
+            extern {
+                unsafe fn rust_list_dir_val(ptr: *dirent_t) -> *libc::c_char;
+            }
+            let input = p.to_str();
+            let mut strings = ~[];
+            let input_ptr = ::cast::transmute(&input[0]);
+            debug!("os::list_dir -- BEFORE OPENDIR");
+            let dir_ptr = opendir(input_ptr);
+            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) {
+                    strings.push(str::raw::from_c_str(rust_list_dir_val(
+                        entry_ptr)));
+                    entry_ptr = readdir(dir_ptr);
+                }
+                closedir(dir_ptr);
+            }
+            else {
+        debug!("os::list_dir -- opendir() FAILURE");
+            }
+            debug!(
+                "os::list_dir -- AFTER -- #: %?",
+                     strings.len());
+            strings
+        }
+        #[cfg(windows)]
+        unsafe fn get_list(p: &Path) -> ~[~str] {
+            use libc::types::os::arch::extra::{LPCTSTR, HANDLE, BOOL};
+            use libc::consts::os::extra::INVALID_HANDLE_VALUE;
+            use libc::wcslen;
+            use libc::funcs::extra::kernel32::{
+                FindFirstFileW,
+                FindNextFileW,
+                FindClose,
+            };
+            use os::win32::{
+                as_utf16_p
+            };
+            use rt::global_heap::{malloc_raw, free_raw};
+            #[nolink]
+            extern {
+                unsafe fn rust_list_dir_wfd_size() -> libc::size_t;
+                unsafe fn rust_list_dir_wfd_fp_buf(wfd: *libc::c_void)
+                    -> *u16;
+            }
+            fn star(p: &Path) -> Path { p.push("*") }
+            do as_utf16_p(star(p).to_str()) |path_ptr| {
+                let mut strings = ~[];
+                let wfd_ptr = malloc_raw(rust_list_dir_wfd_size() as uint);
+                let find_handle =
+                    FindFirstFileW(
+                        path_ptr,
+                        ::cast::transmute(wfd_ptr));
+                if find_handle as 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);
+                            strings.push(fp_str);
+                        }
+                        more_files = FindNextFileW(
+                            find_handle,
+                            ::cast::transmute(wfd_ptr));
+                    }
+                    FindClose(find_handle);
+                    free_raw(wfd_ptr);
+                }
+                strings
+            }
+        }
+        do get_list(p).filtered |filename| {
+            *filename != ~"." && *filename != ~".."
+        }
+    }
+}
+
+/**
+ * Lists the contents of a directory
+ *
+ * This version prepends each entry with the directory.
+ */
+pub fn list_dir_path(p: &Path) -> ~[~Path] {
+    list_dir(p).map(|f| ~p.push(*f))
+}
+
+/// 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;
+    for 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;
+                }
+            }
+        }
+    };
+    // 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.to_str()) |buf| {
+                libc::RemoveDirectoryW(buf) != (0 as libc::BOOL)
+            };
+        }
+    }
+
+    #[cfg(unix)]
+    fn rmdir(p: &Path) -> bool {
+        unsafe {
+            return do as_c_charp(p.to_str()) |buf| {
+                libc::rmdir(buf) == (0 as c_int)
+            };
+        }
+    }
+}
+
+pub fn change_dir(p: &Path) -> bool {
+    return chdir(p);
+
+    #[cfg(windows)]
+    fn chdir(p: &Path) -> bool {
+        unsafe {
+            use os::win32::as_utf16_p;
+            return do as_utf16_p(p.to_str()) |buf| {
+                libc::SetCurrentDirectoryW(buf) != (0 as libc::BOOL)
+            };
+        }
+    }
+
+    #[cfg(unix)]
+    fn chdir(p: &Path) -> bool {
+        unsafe {
+            return do as_c_charp(p.to_str()) |buf| {
+                libc::chdir(buf) == (0 as c_int)
+            };
+        }
+    }
+}
+
+/// Changes the current working directory to the specified
+/// path while acquiring a global lock, then calls `action`.
+/// If the change is successful, releases the lock and restores the
+/// CWD to what it was before, returning true.
+/// Returns false if the directory doesn't exist or if the directory change
+/// is otherwise unsuccessful.
+pub fn change_dir_locked(p: &Path, action: &fn()) -> bool {
+    use unstable::global::global_data_clone_create;
+    use unstable::sync::{Exclusive, exclusive};
+
+    fn key(_: Exclusive<()>) { }
+
+    let result = unsafe {
+        global_data_clone_create(key, || {
+            ~exclusive(())
+        })
+    };
+
+    do result.with_imm() |_| {
+        let old_dir = os::getcwd();
+        if change_dir(p) {
+            action();
+            change_dir(&old_dir)
+        }
+        else {
+            false
+        }
+    }
+}
+
+/// 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.to_str()) |fromp| {
+                do as_utf16_p(to.to_str()) |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 as_c_charp(from.to_str()) |fromp| {
+                do as_c_charp("rb") |modebuf| {
+                    libc::fopen(fromp, modebuf)
+                }
+            };
+            if istream as uint == 0u {
+                return false;
+            }
+            // Preserve permissions
+            let from_mode = from.get_mode().expect("copy_file: couldn't get permissions \
+                                                    for source file");
+
+            let ostream = do as_c_charp(to.to_str()) |top| {
+                do as_c_charp("w+b") |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 vec::as_mut_buf(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
+            unsafe {
+                if do str::as_c_str(to.to_str()) |to_buf| {
+                    libc::chmod(to_buf, from_mode as mode_t)
+                } != 0 {
+                    return false; // should be a condition...
+                }
+            }
+            return ok;
+        }
+    }
+}
+
+/// 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.to_str()) |buf| {
+                libc::DeleteFileW(buf) != (0 as libc::BOOL)
+            };
+        }
+    }
+
+    #[cfg(unix)]
+    fn unlink(p: &Path) -> bool {
+        unsafe {
+            return do as_c_charp(p.to_str()) |buf| {
+                libc::unlink(buf) == (0 as c_int)
+            };
+        }
+    }
+}
+
+#[cfg(unix)]
+pub fn errno() -> int {
+    #[cfg(target_os = "macos")]
+    #[cfg(target_os = "freebsd")]
+    fn errno_location() -> *c_int {
+        #[nolink]
+        extern {
+            unsafe fn __error() -> *c_int;
+        }
+        unsafe {
+            __error()
+        }
+    }
+
+    #[cfg(target_os = "linux")]
+    #[cfg(target_os = "android")]
+    fn errno_location() -> *c_int {
+        #[nolink]
+        extern {
+            unsafe fn __errno_location() -> *c_int;
+        }
+        unsafe {
+            __errno_location()
+        }
+    }
+
+    unsafe {
+        (*errno_location()) as int
+    }
+}
+
+#[cfg(windows)]
+pub fn errno() -> uint {
+    use libc::types::os::arch::extra::DWORD;
+
+    #[link_name = "kernel32"]
+    #[abi = "stdcall"]
+    extern "stdcall" {
+        unsafe fn GetLastError() -> DWORD;
+    }
+
+    unsafe {
+        GetLastError() as uint
+    }
+}
+
+/// Get a string representing the platform-dependent last error
+pub fn last_os_error() -> ~str {
+    #[cfg(unix)]
+    fn strerror() -> ~str {
+        #[cfg(target_os = "macos")]
+        #[cfg(target_os = "android")]
+        #[cfg(target_os = "freebsd")]
+        fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int {
+            #[nolink]
+            extern {
+                unsafe fn strerror_r(errnum: c_int, buf: *mut c_char,
+                                     buflen: size_t) -> c_int;
+            }
+            unsafe {
+                strerror_r(errnum, buf, buflen)
+            }
+        }
+
+        // GNU libc provides a non-compliant version of strerror_r by default
+        // and requires macros to instead use the POSIX compliant variant.
+        // So we just use __xpg_strerror_r which is always POSIX compliant
+        #[cfg(target_os = "linux")]
+        fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: size_t) -> c_int {
+            #[nolink]
+            extern {
+                unsafe fn __xpg_strerror_r(errnum: c_int, buf: *mut c_char,
+                                           buflen: size_t) -> c_int;
+            }
+            unsafe {
+                __xpg_strerror_r(errnum, buf, buflen)
+            }
+        }
+
+        let mut buf = [0 as c_char, ..TMPBUF_SZ];
+        unsafe {
+            let err = strerror_r(errno() as c_int, &mut buf[0],
+                                 TMPBUF_SZ as size_t);
+            if err < 0 {
+                fail!("strerror_r failure");
+            }
+
+            str::raw::from_c_str(&buf[0])
+        }
+    }
+
+    #[cfg(windows)]
+    fn strerror() -> ~str {
+        use libc::types::os::arch::extra::DWORD;
+        use libc::types::os::arch::extra::LPSTR;
+        use libc::types::os::arch::extra::LPVOID;
+
+        #[link_name = "kernel32"]
+        #[abi = "stdcall"]
+        extern "stdcall" {
+            unsafe fn FormatMessageA(flags: DWORD, lpSrc: LPVOID,
+                                     msgId: DWORD, langId: DWORD,
+                                     buf: LPSTR, nsize: DWORD,
+                                     args: *c_void) -> DWORD;
+        }
+
+        static FORMAT_MESSAGE_FROM_SYSTEM: DWORD = 0x00001000;
+        static FORMAT_MESSAGE_IGNORE_INSERTS: DWORD = 0x00000200;
+
+        let mut buf = [0 as c_char, ..TMPBUF_SZ];
+
+        // This value is calculated from the macro
+        // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
+        let langId = 0x0800 as DWORD;
+        let err = errno() as DWORD;
+        unsafe {
+            let res = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM |
+                                     FORMAT_MESSAGE_IGNORE_INSERTS,
+                                     ptr::mut_null(), err, langId,
+                                     &mut buf[0], TMPBUF_SZ as DWORD,
+                                     ptr::null());
+            if res == 0 {
+                fail!("[%?] FormatMessage failure", errno());
+            }
+
+            str::raw::from_c_str(&buf[0])
+        }
+    }
+
+    strerror()
+}
+
+/**
+ * Sets the process exit code
+ *
+ * Sets the exit code returned by the process if all supervised tasks
+ * terminate successfully (without failing). If the current root task fails
+ * and is supervised by the scheduler then any user-specified exit status is
+ * ignored and the process exits with the default failure status
+ */
+pub fn set_exit_status(code: int) {
+    unsafe {
+        rustrt::rust_set_exit_status(code as libc::intptr_t);
+    }
+}
+
+unsafe fn load_argc_and_argv(argc: c_int, argv: **c_char) -> ~[~str] {
+    let mut args = ~[];
+    for uint::range(0, argc as uint) |i| {
+        vec::push(&mut args, str::raw::from_c_str(*argv.offset(i)));
+    }
+    args
+}
+
+/**
+ * Returns the command line arguments
+ *
+ * Returns a list of the command line arguments.
+ */
+#[cfg(target_os = "macos")]
+pub fn real_args() -> ~[~str] {
+    unsafe {
+        let (argc, argv) = (*_NSGetArgc() as c_int,
+                            *_NSGetArgv() as **c_char);
+        load_argc_and_argv(argc, argv)
+    }
+}
+
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "android")]
+#[cfg(target_os = "freebsd")]
+pub fn real_args() -> ~[~str] {
+    unsafe {
+        let argc = rustrt::rust_get_argc();
+        let argv = rustrt::rust_get_argv();
+        load_argc_and_argv(argc, argv)
+    }
+}
+
+#[cfg(windows)]
+pub fn real_args() -> ~[~str] {
+    let mut nArgs: c_int = 0;
+    let lpArgCount = ptr::to_mut_unsafe_ptr(&mut nArgs);
+    let lpCmdLine = unsafe { GetCommandLineW() };
+    let szArgList = unsafe { CommandLineToArgvW(lpCmdLine, lpArgCount) };
+
+    let mut args = ~[];
+    for uint::range(0, nArgs as uint) |i| {
+        unsafe {
+            // Determine the length of this argument.
+            let ptr = *szArgList.offset(i);
+            let mut len = 0;
+            while *ptr.offset(len) != 0 { len += 1; }
+
+            // Push it onto the list.
+            vec::push(&mut args,
+                      vec::raw::buf_as_slice(ptr, len,
+                                             str::from_utf16));
+        }
+    }
+
+    unsafe {
+        LocalFree(cast::transmute(szArgList));
+    }
+
+    return args;
+}
+
+type LPCWSTR = *u16;
+
+#[cfg(windows)]
+#[link_name="kernel32"]
+#[abi="stdcall"]
+extern "stdcall" {
+    fn GetCommandLineW() -> LPCWSTR;
+    fn LocalFree(ptr: *c_void);
+}
+
+#[cfg(windows)]
+#[link_name="shell32"]
+#[abi="stdcall"]
+extern "stdcall" {
+    fn CommandLineToArgvW(lpCmdLine: LPCWSTR, pNumArgs: *mut c_int) -> **u16;
+}
+
+struct OverriddenArgs {
+    val: ~[~str]
+}
+
+fn overridden_arg_key(_v: @OverriddenArgs) {}
+
+pub fn args() -> ~[~str] {
+    unsafe {
+        match local_data::local_data_get(overridden_arg_key) {
+            None => real_args(),
+            Some(args) => copy args.val
+        }
+    }
+}
+
+pub fn set_args(new_args: ~[~str]) {
+    unsafe {
+        let overridden_args = @OverriddenArgs { val: copy new_args };
+        local_data::local_data_set(overridden_arg_key, overridden_args);
+    }
+}
+
+// FIXME #6100 we should really use an internal implementation of this - using
+// the POSIX glob functions isn't portable to windows, probably has slight
+// inconsistencies even where it is implemented, and makes extending
+// functionality a lot more difficult
+// FIXME #6101 also provide a non-allocating version - each_glob or so?
+/// Returns a vector of Path objects that match the given glob pattern
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "android")]
+#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "macos")]
+pub fn glob(pattern: &str) -> ~[Path] {
+    #[cfg(target_os = "linux")]
+    #[cfg(target_os = "android")]
+    fn default_glob_t () -> libc::glob_t {
+        libc::glob_t {
+            gl_pathc: 0,
+            gl_pathv: ptr::null(),
+            gl_offs: 0,
+            __unused1: ptr::null(),
+            __unused2: ptr::null(),
+            __unused3: ptr::null(),
+            __unused4: ptr::null(),
+            __unused5: ptr::null(),
+        }
+    }
+
+    #[cfg(target_os = "freebsd")]
+    fn default_glob_t () -> libc::glob_t {
+        libc::glob_t {
+            gl_pathc: 0,
+            __unused1: 0,
+            gl_offs: 0,
+            __unused2: 0,
+            gl_pathv: ptr::null(),
+            __unused3: ptr::null(),
+            __unused4: ptr::null(),
+            __unused5: ptr::null(),
+            __unused6: ptr::null(),
+            __unused7: ptr::null(),
+            __unused8: ptr::null(),
+        }
+    }
+
+    #[cfg(target_os = "macos")]
+    fn default_glob_t () -> libc::glob_t {
+        libc::glob_t {
+            gl_pathc: 0,
+            __unused1: 0,
+            gl_offs: 0,
+            __unused2: 0,
+            gl_pathv: ptr::null(),
+            __unused3: ptr::null(),
+            __unused4: ptr::null(),
+            __unused5: ptr::null(),
+            __unused6: ptr::null(),
+            __unused7: ptr::null(),
+            __unused8: ptr::null(),
+        }
+    }
+
+    let mut g = default_glob_t();
+    do str::as_c_str(pattern) |c_pattern| {
+        unsafe { libc::glob(c_pattern, 0, ptr::null(), &mut g) }
+    };
+    do(|| {
+        let paths = unsafe {
+            vec::raw::from_buf_raw(g.gl_pathv, g.gl_pathc as uint)
+        };
+        do paths.map |&c_str| {
+            Path(unsafe { str::raw::from_c_str(c_str) })
+        }
+    }).finally {
+        unsafe { libc::globfree(&mut g) };
+    }
+}
+
+/// Returns a vector of Path objects that match the given glob pattern
+#[cfg(target_os = "win32")]
+pub fn glob(pattern: &str) -> ~[Path] {
+    fail!("glob() is unimplemented on Windows")
+}
+
+#[cfg(target_os = "macos")]
+extern {
+    // These functions are in crt_externs.h.
+    pub fn _NSGetArgc() -> *c_int;
+    pub fn _NSGetArgv() -> ***c_char;
+}
+
+pub mod consts {
+
+    #[cfg(unix)]
+    pub use os::consts::unix::*;
+
+    #[cfg(windows)]
+    pub use os::consts::windows::*;
+
+    #[cfg(target_os = "macos")]
+    pub use os::consts::macos::*;
+
+    #[cfg(target_os = "freebsd")]
+    pub use os::consts::freebsd::*;
+
+    #[cfg(target_os = "linux")]
+    pub use os::consts::linux::*;
+
+    #[cfg(target_os = "android")]
+    pub use os::consts::android::*;
+
+    #[cfg(target_os = "win32")]
+    pub use os::consts::win32::*;
+
+    #[cfg(target_arch = "x86")]
+    pub use os::consts::x86::*;
+
+    #[cfg(target_arch = "x86_64")]
+    pub use os::consts::x86_64::*;
+
+    #[cfg(target_arch = "arm")]
+    pub use os::consts::arm::*;
+
+    #[cfg(target_arch = "mips")]
+    use os::consts::mips::*;
+
+    pub mod unix {
+        pub static FAMILY: &'static str = "unix";
+    }
+
+    pub mod windows {
+        pub static FAMILY: &'static str = "windows";
+    }
+
+    pub mod macos {
+        pub static SYSNAME: &'static str = "macos";
+        pub static DLL_PREFIX: &'static str = "lib";
+        pub static DLL_SUFFIX: &'static str = ".dylib";
+        pub static EXE_SUFFIX: &'static str = "";
+    }
+
+    pub mod freebsd {
+        pub static SYSNAME: &'static str = "freebsd";
+        pub static DLL_PREFIX: &'static str = "lib";
+        pub static DLL_SUFFIX: &'static str = ".so";
+        pub static EXE_SUFFIX: &'static str = "";
+    }
+
+    pub mod linux {
+        pub static SYSNAME: &'static str = "linux";
+        pub static DLL_PREFIX: &'static str = "lib";
+        pub static DLL_SUFFIX: &'static str = ".so";
+        pub static EXE_SUFFIX: &'static str = "";
+    }
+
+    pub mod android {
+        pub static SYSNAME: &'static str = "android";
+        pub static DLL_PREFIX: &'static str = "lib";
+        pub static DLL_SUFFIX: &'static str = ".so";
+        pub static EXE_SUFFIX: &'static str = "";
+    }
+
+    pub mod win32 {
+        pub static SYSNAME: &'static str = "win32";
+        pub static DLL_PREFIX: &'static str = "";
+        pub static DLL_SUFFIX: &'static str = ".dll";
+        pub static EXE_SUFFIX: &'static str = ".exe";
+    }
+
+
+    pub mod x86 {
+        pub static ARCH: &'static str = "x86";
+    }
+    pub mod x86_64 {
+        pub static ARCH: &'static str = "x86_64";
+    }
+    pub mod arm {
+        pub static ARCH: &'static str = "arm";
+    }
+    pub mod mips {
+        pub static ARCH: &'static str = "mips";
+    }
+}
+
+#[cfg(test)]
+#[allow(non_implicitly_copyable_typarams)]
+mod tests {
+    use libc::{c_int, c_void, size_t};
+    use libc;
+    use option::Some;
+    use option;
+    use os::{as_c_charp, env, getcwd, getenv, make_absolute, real_args};
+    use os::{remove_file, setenv, unsetenv};
+    use os;
+    use path::Path;
+    use rand::RngUtil;
+    use rand;
+    use run;
+    use str;
+    use vec;
+    use libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
+
+
+    #[test]
+    pub fn last_os_error() {
+        debug!(os::last_os_error());
+    }
+
+    #[test]
+    pub fn test_args() {
+        let a = real_args();
+        assert!(a.len() >= 1);
+    }
+
+    fn make_rand_name() -> ~str {
+        let mut rng = rand::rng();
+        let n = ~"TEST" + rng.gen_str(10u);
+        assert!(getenv(n).is_none());
+        n
+    }
+
+    #[test]
+    fn test_setenv() {
+        let n = make_rand_name();
+        setenv(n, ~"VALUE");
+        assert_eq!(getenv(n), option::Some(~"VALUE"));
+    }
+
+    #[test]
+    fn test_unsetenv() {
+        let n = make_rand_name();
+        setenv(n, ~"VALUE");
+        unsetenv(n);
+        assert_eq!(getenv(n), option::None);
+    }
+
+    #[test]
+    #[ignore(cfg(windows))]
+    #[ignore]
+    fn test_setenv_overwrite() {
+        let n = make_rand_name();
+        setenv(n, ~"1");
+        setenv(n, ~"2");
+        assert_eq!(getenv(n), option::Some(~"2"));
+        setenv(n, ~"");
+        assert_eq!(getenv(n), option::Some(~""));
+    }
+
+    // Windows GetEnvironmentVariable requires some extra work to make sure
+    // the buffer the variable is copied into is the right size
+    #[test]
+    #[ignore(cfg(windows))]
+    #[ignore]
+    fn test_getenv_big() {
+        let mut s = ~"";
+        let mut i = 0;
+        while i < 100 { s += ~"aaaaaaaaaa"; i += 1; }
+        let n = make_rand_name();
+        setenv(n, s);
+        debug!(copy s);
+        assert_eq!(getenv(n), option::Some(s));
+    }
+
+    #[test]
+    fn test_self_exe_path() {
+        let path = os::self_exe_path();
+        assert!(path.is_some());
+        let path = path.get();
+        debug!(copy path);
+
+        // Hard to test this function
+        assert!(path.is_absolute);
+    }
+
+    #[test]
+    #[ignore]
+    fn test_env_getenv() {
+        let e = env();
+        assert!(e.len() > 0u);
+        for e.each |p| {
+            let (n, v) = copy *p;
+            debug!(copy n);
+            let v2 = getenv(n);
+            // MingW seems to set some funky environment variables like
+            // "=C:=C:\MinGW\msys\1.0\bin" and "!::=::\" that are returned
+            // from env() but not visible from getenv().
+            assert!(v2.is_none() || v2 == option::Some(v));
+        }
+    }
+
+    #[test]
+    fn test_env_setenv() {
+        let n = make_rand_name();
+
+        let mut e = env();
+        setenv(n, ~"VALUE");
+        assert!(!vec::contains(e, &(copy n, ~"VALUE")));
+
+        e = env();
+        assert!(vec::contains(e, &(n, ~"VALUE")));
+    }
+
+    #[test]
+    fn test() {
+        assert!((!Path("test-path").is_absolute));
+
+        debug!(~"Current working directory: " + getcwd().to_str());
+
+        debug!(make_absolute(&Path("test-path")));
+        debug!(make_absolute(&Path("/usr/bin")));
+    }
+
+    #[test]
+    #[cfg(unix)]
+    fn homedir() {
+        let oldhome = getenv(~"HOME");
+
+        setenv(~"HOME", ~"/home/MountainView");
+        assert_eq!(os::homedir(), Some(Path("/home/MountainView")));
+
+        setenv(~"HOME", ~"");
+        assert!(os::homedir().is_none());
+
+        for oldhome.each |s| { setenv(~"HOME", *s) }
+    }
+
+    #[test]
+    #[cfg(windows)]
+    fn homedir() {
+
+        let oldhome = getenv(~"HOME");
+        let olduserprofile = getenv(~"USERPROFILE");
+
+        setenv(~"HOME", ~"");
+        setenv(~"USERPROFILE", ~"");
+
+        assert!(os::homedir().is_none());
+
+        setenv(~"HOME", ~"/home/MountainView");
+        assert_eq!(os::homedir(), Some(Path("/home/MountainView")));
+
+        setenv(~"HOME", ~"");
+
+        setenv(~"USERPROFILE", ~"/home/MountainView");
+        assert_eq!(os::homedir(), Some(Path("/home/MountainView")));
+
+        setenv(~"HOME", ~"/home/MountainView");
+        setenv(~"USERPROFILE", ~"/home/PaloAlto");
+        assert_eq!(os::homedir(), Some(Path("/home/MountainView")));
+
+        oldhome.each(|s| {setenv(~"HOME", *s);true});
+        olduserprofile.each(|s| {setenv(~"USERPROFILE", *s);true});
+    }
+
+    #[test]
+    fn tmpdir() {
+        assert!(!str::is_empty(os::tmpdir().to_str()));
+    }
+
+    // Issue #712
+    #[test]
+    fn test_list_dir_no_invalid_memory_access() {
+        os::list_dir(&Path("."));
+    }
+
+    #[test]
+    fn list_dir() {
+        let dirs = os::list_dir(&Path("."));
+        // Just assuming that we've got some contents in the current directory
+        assert!(dirs.len() > 0u);
+
+        for dirs.each |dir| {
+            debug!(copy *dir);
+        }
+    }
+
+    #[test]
+    fn path_is_dir() {
+        assert!((os::path_is_dir(&Path("."))));
+        assert!((!os::path_is_dir(&Path("test/stdtest/fs.rs"))));
+    }
+
+    #[test]
+    fn path_exists() {
+        assert!((os::path_exists(&Path("."))));
+        assert!((!os::path_exists(&Path(
+                     "test/nonexistent-bogus-path"))));
+    }
+
+    #[test]
+    fn copy_file_does_not_exist() {
+      assert!(!os::copy_file(&Path("test/nonexistent-bogus-path"),
+                            &Path("test/other-bogus-path")));
+      assert!(!os::path_exists(&Path("test/other-bogus-path")));
+    }
+
+    #[test]
+    fn copy_file_ok() {
+        unsafe {
+          let tempdir = getcwd(); // would like to use $TMPDIR,
+                                  // doesn't seem to work on Linux
+          assert!((str::len(tempdir.to_str()) > 0u));
+          let in = tempdir.push("in.txt");
+          let out = tempdir.push("out.txt");
+
+          /* Write the temp input file */
+            let ostream = do as_c_charp(in.to_str()) |fromp| {
+                do as_c_charp("w+b") |modebuf| {
+                    libc::fopen(fromp, modebuf)
+                }
+          };
+          assert!((ostream as uint != 0u));
+          let s = ~"hello";
+          let mut buf = str::to_bytes(s) + ~[0 as u8];
+          do vec::as_mut_buf(buf) |b, _len| {
+              assert!((libc::fwrite(b as *c_void, 1u as size_t,
+                                   (str::len(s) + 1u) as size_t, ostream)
+                      == buf.len() as size_t))
+          }
+          assert_eq!(libc::fclose(ostream), (0u as c_int));
+          let in_mode = in.get_mode();
+          let rs = os::copy_file(&in, &out);
+          if (!os::path_exists(&in)) {
+            fail!("%s doesn't exist", in.to_str());
+          }
+          assert!((rs));
+          let rslt = run::run_program(~"diff", ~[in.to_str(), out.to_str()]);
+          assert_eq!(rslt, 0);
+          assert_eq!(out.get_mode(), in_mode);
+          assert!((remove_file(&in)));
+          assert!((remove_file(&out)));
+        }
+    }
+
+    #[test]
+    fn recursive_mkdir_slash() {
+        let path = Path("/");
+        assert!(os::mkdir_recursive(&path,  (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
+    }
+
+    #[test]
+    fn recursive_mkdir_empty() {
+        let path = Path("");
+        assert!(!os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
+    }
+
+    // More recursive_mkdir tests are in std::tempfile
+}
diff --git a/src/libstd/owned.rs b/src/libstd/owned.rs
new file mode 100644
index 00000000000..3262fb4afdc
--- /dev/null
+++ b/src/libstd/owned.rs
@@ -0,0 +1,33 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations on unique pointer types
+
+#[cfg(not(test))] use cmp::{Eq, Ord};
+
+#[cfg(not(test))]
+impl<T:Eq> Eq for ~T {
+    #[inline(always)]
+    fn eq(&self, other: &~T) -> bool { *(*self) == *(*other) }
+    #[inline(always)]
+    fn ne(&self, other: &~T) -> bool { *(*self) != *(*other) }
+}
+
+#[cfg(not(test))]
+impl<T:Ord> Ord for ~T {
+    #[inline(always)]
+    fn lt(&self, other: &~T) -> bool { *(*self) < *(*other) }
+    #[inline(always)]
+    fn le(&self, other: &~T) -> bool { *(*self) <= *(*other) }
+    #[inline(always)]
+    fn ge(&self, other: &~T) -> bool { *(*self) >= *(*other) }
+    #[inline(always)]
+    fn gt(&self, other: &~T) -> bool { *(*self) > *(*other) }
+}
diff --git a/src/libstd/par.rs b/src/libstd/par.rs
deleted file mode 100644
index e766d2d3bf0..00000000000
--- a/src/libstd/par.rs
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use future_spawn = future::spawn;
-
-/**
- * The maximum number of tasks this module will spawn for a single
- * operation.
- */
-static max_tasks : uint = 32u;
-
-/// The minimum number of elements each task will process.
-static min_granularity : uint = 1024u;
-
-/**
- * An internal helper to map a function over a large vector and
- * return the intermediate results.
- *
- * This is used to build most of the other parallel vector functions,
- * like map or alli.
- */
-fn map_slices<A:Copy + Owned,B:Copy + Owned>(
-    xs: &[A],
-    f: &fn() -> ~fn(uint, v: &[A]) -> B)
-    -> ~[B] {
-
-    let len = xs.len();
-    if len < min_granularity {
-        info!("small slice");
-        // This is a small vector, fall back on the normal map.
-        ~[f()(0u, xs)]
-    }
-    else {
-        let num_tasks = uint::min(max_tasks, len / min_granularity);
-
-        let items_per_task = len / num_tasks;
-
-        let mut futures = ~[];
-        let mut base = 0u;
-        info!("spawning tasks");
-        while base < len {
-            let end = uint::min(len, base + items_per_task);
-            do vec::as_imm_buf(xs) |p, _len| {
-                let f = f();
-                let base = base;
-                let f = do future_spawn() || {
-                    unsafe {
-                        let len = end - base;
-                        let slice = (ptr::offset(p, base),
-                                     len * sys::size_of::<A>());
-                        info!("pre-slice: %?", (base, slice));
-                        let slice : &[A] =
-                            cast::transmute(slice);
-                        info!("slice: %?", (base, slice.len(), end - base));
-                        assert_eq!(slice.len(), end - base);
-                        f(base, slice)
-                    }
-                };
-                futures.push(f);
-            };
-            base += items_per_task;
-        }
-        info!("tasks spawned");
-
-        info!("num_tasks: %?", (num_tasks, futures.len()));
-        assert_eq!(num_tasks, futures.len());
-
-        let r = do vec::map_consume(futures) |ys| {
-            let mut ys = ys;
-            ys.get()
-        };
-        r
-    }
-}
-
-/// A parallel version of map.
-pub fn map<A:Copy + Owned,B:Copy + Owned>(
-    xs: &[A], fn_factory: &fn() -> ~fn(&A) -> B) -> ~[B] {
-    vec::concat(map_slices(xs, || {
-        let f = fn_factory();
-        let result: ~fn(uint, &[A]) -> ~[B] =
-            |_, slice| vec::map(slice, |x| f(x));
-        result
-    }))
-}
-
-/// A parallel version of mapi.
-pub fn mapi<A:Copy + Owned,B:Copy + Owned>(
-        xs: &[A],
-        fn_factory: &fn() -> ~fn(uint, &A) -> B) -> ~[B] {
-    let slices = map_slices(xs, || {
-        let f = fn_factory();
-        let result: ~fn(uint, &[A]) -> ~[B] = |base, slice| {
-            vec::mapi(slice, |i, x| {
-                f(i + base, x)
-            })
-        };
-        result
-    });
-    let r = vec::concat(slices);
-    info!("%?", (r.len(), xs.len()));
-    assert_eq!(r.len(), xs.len());
-    r
-}
-
-/// Returns true if the function holds for all elements in the vector.
-pub fn alli<A:Copy + Owned>(
-    xs: &[A],
-    fn_factory: &fn() -> ~fn(uint, &A) -> bool) -> bool
-{
-    do vec::all(map_slices(xs, || {
-        let f = fn_factory();
-        let result: ~fn(uint, &[A]) -> bool = |base, slice| {
-            vec::alli(slice, |i, x| {
-                f(i + base, x)
-            })
-        };
-        result
-    })) |x| { *x }
-}
-
-/// Returns true if the function holds for any elements in the vector.
-pub fn any<A:Copy + Owned>(
-    xs: &[A],
-    fn_factory: &fn() -> ~fn(&A) -> bool) -> bool {
-    do vec::any(map_slices(xs, || {
-        let f = fn_factory();
-        let result: ~fn(uint, &[A]) -> bool =
-            |_, slice| vec::any(slice, |x| f(x));
-        result
-    })) |x| { *x }
-}
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
new file mode 100644
index 00000000000..ed9ef864f80
--- /dev/null
+++ b/src/libstd/path.rs
@@ -0,0 +1,1200 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+Cross-platform file path handling
+
+*/
+
+use container::Container;
+use cmp::Eq;
+use libc;
+use option::{None, Option, Some};
+use str;
+use str::StrSlice;
+use to_str::ToStr;
+use ascii::{AsciiCast, AsciiStr};
+use old_iter::BaseIter;
+use vec::OwnedVector;
+
+#[cfg(windows)]
+pub use Path = self::WindowsPath;
+#[cfg(unix)]
+pub use Path = self::PosixPath;
+
+#[deriving(Clone, Eq)]
+pub struct WindowsPath {
+    host: Option<~str>,
+    device: Option<~str>,
+    is_absolute: bool,
+    components: ~[~str],
+}
+
+pub fn WindowsPath(s: &str) -> WindowsPath {
+    GenericPath::from_str(s)
+}
+
+#[deriving(Clone, Eq)]
+pub struct PosixPath {
+    is_absolute: bool,
+    components: ~[~str],
+}
+
+pub fn PosixPath(s: &str) -> PosixPath {
+    GenericPath::from_str(s)
+}
+
+pub trait GenericPath {
+    /// Converts a string to a Path
+    fn from_str(&str) -> Self;
+
+    /// Returns the directory component of `self`, as a string
+    fn dirname(&self) -> ~str;
+    /// Returns the file component of `self`, as a string option.
+    /// Returns None if `self` names a directory.
+    fn filename(&self) -> Option<~str>;
+    /// Returns the stem of the file component of `self`, as a string option.
+    /// The stem is the slice of a filename starting at 0 and ending just before
+    /// the last '.' in the name.
+    /// Returns None if `self` names a directory.
+    fn filestem(&self) -> Option<~str>;
+    /// Returns the type of the file component of `self`, as a string option.
+    /// The file type is the slice of a filename starting just after the last
+    /// '.' in the name and ending at the last index in the filename.
+    /// Returns None if `self` names a directory.
+    fn filetype(&self) -> Option<~str>;
+
+    /// Returns a new path consisting of `self` with the parent directory component replaced
+    /// with the given string.
+    fn with_dirname(&self, (&str)) -> Self;
+    /// Returns a new path consisting of `self` with the file component replaced
+    /// with the given string.
+    fn with_filename(&self, (&str)) -> Self;
+    /// Returns a new path consisting of `self` with the file stem replaced
+    /// with the given string.
+    fn with_filestem(&self, (&str)) -> Self;
+    /// Returns a new path consisting of `self` with the file type replaced
+    /// with the given string.
+    fn with_filetype(&self, (&str)) -> Self;
+
+    /// Returns the directory component of `self`, as a new path.
+    /// If `self` has no parent, returns `self`.
+    fn dir_path(&self) -> Self;
+    /// Returns the file component of `self`, as a new path.
+    /// If `self` names a directory, returns the empty path.
+    fn file_path(&self) -> Self;
+
+    /// Returns a new Path whose parent directory is `self` and whose
+    /// file component is the given string.
+    fn push(&self, (&str)) -> Self;
+    /// Returns a new Path consisting of the given path, made relative to `self`.
+    fn push_rel(&self, (&Self)) -> Self;
+    /// Returns a new Path consisting of the path given by the given vector
+    /// of strings, relative to `self`.
+    fn push_many(&self, (&[~str])) -> Self;
+    /// Identical to `dir_path` except in the case where `self` has only one
+    /// component. In this case, `pop` returns the empty path.
+    fn pop(&self) -> Self;
+
+    /// The same as `push_rel`, except that the directory argument must not
+    /// contain directory separators in any of its components.
+    fn unsafe_join(&self, (&Self)) -> Self;
+    /// On Unix, always returns false. On Windows, returns true iff `self`'s
+    /// file stem is one of: `con` `aux` `com1` `com2` `com3` `com4`
+    /// `lpt1` `lpt2` `lpt3` `prn` `nul`
+    fn is_restricted(&self) -> bool;
+
+    /// Returns a new path that names the same file as `self`, without containing
+    /// any '.', '..', or empty components. On Windows, uppercases the drive letter
+    /// as well.
+    fn normalize(&self) -> Self;
+
+    /// Returns `true` if `self` is an absolute path.
+    fn is_absolute(&self) -> bool;
+}
+
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "android")]
+mod stat {
+    #[cfg(target_arch = "x86")]
+    #[cfg(target_arch = "arm")]
+    pub mod arch {
+        use libc;
+
+        pub fn default_stat() -> libc::stat {
+            libc::stat {
+                st_dev: 0,
+                __pad1: 0,
+                st_ino: 0,
+                st_mode: 0,
+                st_nlink: 0,
+                st_uid: 0,
+                st_gid: 0,
+                st_rdev: 0,
+                __pad2: 0,
+                st_size: 0,
+                st_blksize: 0,
+                st_blocks: 0,
+                st_atime: 0,
+                st_atime_nsec: 0,
+                st_mtime: 0,
+                st_mtime_nsec: 0,
+                st_ctime: 0,
+                st_ctime_nsec: 0,
+                __unused4: 0,
+                __unused5: 0,
+            }
+        }
+    }
+
+    #[cfg(target_arch = "mips")]
+    pub mod arch {
+        use libc;
+
+        pub fn default_stat() -> libc::stat {
+            libc::stat {
+                st_dev: 0,
+                st_pad1: [0, ..3],
+                st_ino: 0,
+                st_mode: 0,
+                st_nlink: 0,
+                st_uid: 0,
+                st_gid: 0,
+                st_rdev: 0,
+                st_pad2: [0, ..2],
+                st_size: 0,
+                st_pad3: 0,
+                st_atime: 0,
+                st_atime_nsec: 0,
+                st_mtime: 0,
+                st_mtime_nsec: 0,
+                st_ctime: 0,
+                st_ctime_nsec: 0,
+                st_blksize: 0,
+                st_blocks: 0,
+                st_pad5: [0, ..14],
+            }
+        }
+    }
+
+    #[cfg(target_arch = "x86_64")]
+    pub mod arch {
+        use libc;
+
+        pub fn default_stat() -> libc::stat {
+            libc::stat {
+                st_dev: 0,
+                st_ino: 0,
+                st_nlink: 0,
+                st_mode: 0,
+                st_uid: 0,
+                st_gid: 0,
+                __pad0: 0,
+                st_rdev: 0,
+                st_size: 0,
+                st_blksize: 0,
+                st_blocks: 0,
+                st_atime: 0,
+                st_atime_nsec: 0,
+                st_mtime: 0,
+                st_mtime_nsec: 0,
+                st_ctime: 0,
+                st_ctime_nsec: 0,
+                __unused: [0, 0, 0],
+            }
+        }
+    }
+}
+
+#[cfg(target_os = "freebsd")]
+mod stat {
+    #[cfg(target_arch = "x86_64")]
+    pub mod arch {
+        use libc;
+
+        pub fn default_stat() -> libc::stat {
+            libc::stat {
+                st_dev: 0,
+                st_ino: 0,
+                st_mode: 0,
+                st_nlink: 0,
+                st_uid: 0,
+                st_gid: 0,
+                st_rdev: 0,
+                st_atime: 0,
+                st_atime_nsec: 0,
+                st_mtime: 0,
+                st_mtime_nsec: 0,
+                st_ctime: 0,
+                st_ctime_nsec: 0,
+                st_size: 0,
+                st_blocks: 0,
+                st_blksize: 0,
+                st_flags: 0,
+                st_gen: 0,
+                st_lspare: 0,
+                st_birthtime: 0,
+                st_birthtime_nsec: 0,
+                __unused: [0, 0],
+            }
+        }
+    }
+}
+
+#[cfg(target_os = "macos")]
+mod stat {
+    pub mod arch {
+        use libc;
+
+        pub fn default_stat() -> libc::stat {
+            libc::stat {
+                st_dev: 0,
+                st_mode: 0,
+                st_nlink: 0,
+                st_ino: 0,
+                st_uid: 0,
+                st_gid: 0,
+                st_rdev: 0,
+                st_atime: 0,
+                st_atime_nsec: 0,
+                st_mtime: 0,
+                st_mtime_nsec: 0,
+                st_ctime: 0,
+                st_ctime_nsec: 0,
+                st_birthtime: 0,
+                st_birthtime_nsec: 0,
+                st_size: 0,
+                st_blocks: 0,
+                st_blksize: 0,
+                st_flags: 0,
+                st_gen: 0,
+                st_lspare: 0,
+                st_qspare: [0, 0],
+            }
+        }
+    }
+}
+
+#[cfg(target_os = "win32")]
+mod stat {
+    pub mod arch {
+        use libc;
+        pub fn default_stat() -> libc::stat {
+            libc::stat {
+                st_dev: 0,
+                st_ino: 0,
+                st_mode: 0,
+                st_nlink: 0,
+                st_uid: 0,
+                st_gid: 0,
+                st_rdev: 0,
+                st_size: 0,
+                st_atime: 0,
+                st_mtime: 0,
+                st_ctime: 0,
+            }
+        }
+    }
+}
+
+
+pub impl Path {
+    fn stat(&self) -> Option<libc::stat> {
+        unsafe {
+             do str::as_c_str(self.to_str()) |buf| {
+                let mut st = stat::arch::default_stat();
+                match libc::stat(buf, &mut st) {
+                    0 => Some(st),
+                    _ => None,
+                }
+            }
+        }
+    }
+
+    #[cfg(unix)]
+    fn lstat(&self) -> Option<libc::stat> {
+        unsafe {
+            do str::as_c_str(self.to_str()) |buf| {
+                let mut st = stat::arch::default_stat();
+                match libc::lstat(buf, &mut st) {
+                    0 => Some(st),
+                    _ => None,
+                }
+            }
+        }
+    }
+
+    fn exists(&self) -> bool {
+        match self.stat() {
+            None => false,
+            Some(_) => true,
+        }
+    }
+
+    fn get_size(&self) -> Option<i64> {
+        match self.stat() {
+            None => None,
+            Some(ref st) => Some(st.st_size as i64),
+        }
+    }
+
+    fn get_mode(&self) -> Option<uint> {
+        match self.stat() {
+            None => None,
+            Some(ref st) => Some(st.st_mode as uint),
+        }
+    }
+}
+
+#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "linux")]
+#[cfg(target_os = "macos")]
+pub impl Path {
+    fn get_atime(&self) -> Option<(i64, int)> {
+        match self.stat() {
+            None => None,
+            Some(ref st) => {
+                Some((st.st_atime as i64,
+                      st.st_atime_nsec as int))
+            }
+        }
+    }
+
+    fn get_mtime(&self) -> Option<(i64, int)> {
+        match self.stat() {
+            None => None,
+            Some(ref st) => {
+                Some((st.st_mtime as i64,
+                      st.st_mtime_nsec as int))
+            }
+        }
+    }
+
+    fn get_ctime(&self) -> Option<(i64, int)> {
+        match self.stat() {
+            None => None,
+            Some(ref st) => {
+                Some((st.st_ctime as i64,
+                      st.st_ctime_nsec as int))
+            }
+        }
+    }
+}
+
+#[cfg(target_os = "freebsd")]
+#[cfg(target_os = "macos")]
+pub impl Path {
+    fn get_birthtime(&self) -> Option<(i64, int)> {
+        match self.stat() {
+            None => None,
+            Some(ref st) => {
+                Some((st.st_birthtime as i64,
+                      st.st_birthtime_nsec as int))
+            }
+        }
+    }
+}
+
+#[cfg(target_os = "win32")]
+pub impl Path {
+    fn get_atime(&self) -> Option<(i64, int)> {
+        match self.stat() {
+            None => None,
+            Some(ref st) => {
+                Some((st.st_atime as i64, 0))
+            }
+        }
+    }
+
+    fn get_mtime(&self) -> Option<(i64, int)> {
+        match self.stat() {
+            None => None,
+            Some(ref st) => {
+                Some((st.st_mtime as i64, 0))
+            }
+        }
+    }
+
+    fn get_ctime(&self) -> Option<(i64, int)> {
+        match self.stat() {
+            None => None,
+            Some(ref st) => {
+                Some((st.st_ctime as i64, 0))
+            }
+        }
+    }
+}
+
+impl ToStr for PosixPath {
+    fn to_str(&self) -> ~str {
+        let mut s = ~"";
+        if self.is_absolute {
+            s += "/";
+        }
+        s + str::connect(self.components, "/")
+    }
+}
+
+// FIXME (#3227): when default methods in traits are working, de-duplicate
+// PosixPath and WindowsPath, most of their methods are common.
+impl GenericPath for PosixPath {
+    fn from_str(s: &str) -> PosixPath {
+        let mut components = ~[];
+        for str::each_split_nonempty(s, |c| c == '/') |s| {
+            components.push(s.to_owned())
+        }
+        let is_absolute = (s.len() != 0 && s[0] == '/' as u8);
+        PosixPath {
+            is_absolute: is_absolute,
+            components: components,
+        }
+    }
+
+    fn dirname(&self) -> ~str {
+        let s = self.dir_path().to_str();
+        match s.len() {
+            0 => ~".",
+            _ => s,
+        }
+    }
+
+    fn filename(&self) -> Option<~str> {
+        match self.components.len() {
+            0 => None,
+            n => Some(copy self.components[n - 1]),
+        }
+    }
+
+    fn filestem(&self) -> Option<~str> {
+        match self.filename() {
+            None => None,
+            Some(ref f) => {
+                match str::rfind_char(*f, '.') {
+                    Some(p) => Some(f.slice(0, p).to_owned()),
+                    None => Some(copy *f),
+                }
+            }
+        }
+    }
+
+    fn filetype(&self) -> Option<~str> {
+        match self.filename() {
+            None => None,
+            Some(ref f) => {
+                match str::rfind_char(*f, '.') {
+                    Some(p) if p < f.len() => Some(f.slice(p, f.len()).to_owned()),
+                    _ => None,
+                }
+            }
+        }
+    }
+
+    fn with_dirname(&self, d: &str) -> PosixPath {
+        let dpath = PosixPath(d);
+        match self.filename() {
+            Some(ref f) => dpath.push(*f),
+            None => dpath,
+        }
+    }
+
+    fn with_filename(&self, f: &str) -> PosixPath {
+        assert!(! str::any(f, |c| windows::is_sep(c as u8)));
+        self.dir_path().push(f)
+    }
+
+    fn with_filestem(&self, s: &str) -> PosixPath {
+        match self.filetype() {
+            None => self.with_filename(s),
+            Some(ref t) => self.with_filename(str::to_owned(s) + *t),
+        }
+    }
+
+    fn with_filetype(&self, t: &str) -> PosixPath {
+        match (t.len(), self.filestem()) {
+            (0, None)        => copy *self,
+            (0, Some(ref s)) => self.with_filename(*s),
+            (_, None)        => self.with_filename(fmt!(".%s", t)),
+            (_, Some(ref s)) => self.with_filename(fmt!("%s.%s", *s, t)),
+        }
+    }
+
+    fn dir_path(&self) -> PosixPath {
+        match self.components.len() {
+            0 => copy *self,
+            _ => self.pop(),
+        }
+    }
+
+    fn file_path(&self) -> PosixPath {
+        let cs = match self.filename() {
+          None => ~[],
+          Some(ref f) => ~[copy *f]
+        };
+        PosixPath {
+            is_absolute: false,
+            components: cs,
+        }
+    }
+
+    fn push_rel(&self, other: &PosixPath) -> PosixPath {
+        assert!(!other.is_absolute);
+        self.push_many(other.components)
+    }
+
+    fn unsafe_join(&self, other: &PosixPath) -> PosixPath {
+        if other.is_absolute {
+            PosixPath {
+                is_absolute: true,
+                components: copy other.components,
+            }
+        } else {
+            self.push_rel(other)
+        }
+    }
+
+    fn is_restricted(&self) -> bool {
+        false
+    }
+
+    fn push_many(&self, cs: &[~str]) -> PosixPath {
+        let mut v = copy self.components;
+        for cs.each |e| {
+            let mut ss = ~[];
+            for str::each_split_nonempty(*e, |c| windows::is_sep(c as u8)) |s| {
+                ss.push(s.to_owned())
+            }
+            v.push_all_move(ss);
+        }
+        PosixPath {
+            is_absolute: self.is_absolute,
+            components: v,
+        }
+    }
+
+    fn push(&self, s: &str) -> PosixPath {
+        let mut v = copy self.components;
+        let mut ss = ~[];
+        for str::each_split_nonempty(s, |c| windows::is_sep(c as u8)) |s| {
+            ss.push(s.to_owned())
+        }
+        v.push_all_move(ss);
+        PosixPath { components: v, ..copy *self }
+    }
+
+    fn pop(&self) -> PosixPath {
+        let mut cs = copy self.components;
+        if cs.len() != 0 {
+            cs.pop();
+        }
+        PosixPath {
+            is_absolute: self.is_absolute,
+            components: cs,
+        } //..self }
+    }
+
+    fn normalize(&self) -> PosixPath {
+        PosixPath {
+            is_absolute: self.is_absolute,
+            components: normalize(self.components),
+        } // ..self }
+    }
+
+    fn is_absolute(&self) -> bool {
+        self.is_absolute
+    }
+}
+
+
+impl ToStr for WindowsPath {
+    fn to_str(&self) -> ~str {
+        let mut s = ~"";
+        match self.host {
+          Some(ref h) => { s += "\\\\"; s += *h; }
+          None => { }
+        }
+        match self.device {
+          Some(ref d) => { s += *d; s += ":"; }
+          None => { }
+        }
+        if self.is_absolute {
+            s += "\\";
+        }
+        s + str::connect(self.components, "\\")
+    }
+}
+
+
+impl GenericPath for WindowsPath {
+    fn from_str(s: &str) -> WindowsPath {
+        let host;
+        let device;
+        let rest;
+
+        match (
+            windows::extract_drive_prefix(s),
+            windows::extract_unc_prefix(s),
+        ) {
+            (Some((ref d, ref r)), _) => {
+                host = None;
+                device = Some(copy *d);
+                rest = copy *r;
+            }
+            (None, Some((ref h, ref r))) => {
+                host = Some(copy *h);
+                device = None;
+                rest = copy *r;
+            }
+            (None, None) => {
+                host = None;
+                device = None;
+                rest = str::to_owned(s);
+            }
+        }
+
+        let mut components = ~[];
+        for str::each_split_nonempty(rest, |c| windows::is_sep(c as u8)) |s| {
+            components.push(s.to_owned())
+        }
+        let is_absolute = (rest.len() != 0 && windows::is_sep(rest[0]));
+        WindowsPath {
+            host: host,
+            device: device,
+            is_absolute: is_absolute,
+            components: components,
+        }
+    }
+
+    fn dirname(&self) -> ~str {
+        let s = self.dir_path().to_str();
+        match s.len() {
+            0 => ~".",
+            _ => s,
+        }
+    }
+
+    fn filename(&self) -> Option<~str> {
+        match self.components.len() {
+            0 => None,
+            n => Some(copy self.components[n - 1]),
+        }
+    }
+
+    fn filestem(&self) -> Option<~str> {
+        match self.filename() {
+            None => None,
+            Some(ref f) => {
+                match str::rfind_char(*f, '.') {
+                    Some(p) => Some(f.slice(0, p).to_owned()),
+                    None => Some(copy *f),
+                }
+            }
+        }
+    }
+
+    fn filetype(&self) -> Option<~str> {
+        match self.filename() {
+          None => None,
+          Some(ref f) => {
+            match str::rfind_char(*f, '.') {
+                Some(p) if p < f.len() => Some(f.slice(p, f.len()).to_owned()),
+                _ => None,
+            }
+          }
+        }
+    }
+
+    fn with_dirname(&self, d: &str) -> WindowsPath {
+        let dpath = WindowsPath(d);
+        match self.filename() {
+            Some(ref f) => dpath.push(*f),
+            None => dpath,
+        }
+    }
+
+    fn with_filename(&self, f: &str) -> WindowsPath {
+        assert!(! str::any(f, |c| windows::is_sep(c as u8)));
+        self.dir_path().push(f)
+    }
+
+    fn with_filestem(&self, s: &str) -> WindowsPath {
+        match self.filetype() {
+            None => self.with_filename(s),
+            Some(ref t) => self.with_filename(str::to_owned(s) + *t),
+        }
+    }
+
+    fn with_filetype(&self, t: &str) -> WindowsPath {
+        match (t.len(), self.filestem()) {
+            (0, None)        => copy *self,
+            (0, Some(ref s)) => self.with_filename(*s),
+            (_, None)        => self.with_filename(fmt!(".%s", t)),
+            (_, Some(ref s)) => self.with_filename(fmt!("%s.%s", *s, t)),
+        }
+    }
+
+    fn dir_path(&self) -> WindowsPath {
+        match self.components.len() {
+            0 => copy *self,
+            _ => self.pop(),
+        }
+    }
+
+    fn file_path(&self) -> WindowsPath {
+        WindowsPath {
+            host: None,
+            device: None,
+            is_absolute: false,
+            components: match self.filename() {
+                None => ~[],
+                Some(ref f) => ~[copy *f],
+            }
+        }
+    }
+
+    fn push_rel(&self, other: &WindowsPath) -> WindowsPath {
+        assert!(!other.is_absolute);
+        self.push_many(other.components)
+    }
+
+    fn unsafe_join(&self, other: &WindowsPath) -> WindowsPath {
+        /* rhs not absolute is simple push */
+        if !other.is_absolute {
+            return self.push_many(other.components);
+        }
+
+        /* if rhs has a host set, then the whole thing wins */
+        match other.host {
+            Some(copy host) => {
+                return WindowsPath {
+                    host: Some(host),
+                    device: copy other.device,
+                    is_absolute: true,
+                    components: copy other.components,
+                };
+            }
+            _ => {}
+        }
+
+        /* if rhs has a device set, then a part wins */
+        match other.device {
+            Some(copy device) => {
+                return WindowsPath {
+                    host: None,
+                    device: Some(device),
+                    is_absolute: true,
+                    components: copy other.components,
+                };
+            }
+            _ => {}
+        }
+
+        /* fallback: host and device of lhs win, but the
+           whole path of the right */
+        WindowsPath {
+            host: copy self.host,
+            device: copy self.device,
+            is_absolute: self.is_absolute || other.is_absolute,
+            components: copy other.components,
+        }
+    }
+
+    fn is_restricted(&self) -> bool {
+        match self.filestem() {
+            Some(stem) => {
+                // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
+                // to_ascii_consume and to_str_consume to not do a unnecessary copy.
+                match stem.to_ascii().to_lower().to_str_ascii() {
+                    ~"con" | ~"aux" | ~"com1" | ~"com2" | ~"com3" | ~"com4" |
+                    ~"lpt1" | ~"lpt2" | ~"lpt3" | ~"prn" | ~"nul" => true,
+                    _ => false
+                }
+            },
+            None => false
+        }
+    }
+
+    fn push_many(&self, cs: &[~str]) -> WindowsPath {
+        let mut v = copy self.components;
+        for cs.each |e| {
+            let mut ss = ~[];
+            for str::each_split_nonempty(*e, |c| windows::is_sep(c as u8)) |s| {
+                ss.push(s.to_owned())
+            }
+            v.push_all_move(ss);
+        }
+        // tedious, but as-is, we can't use ..self
+        WindowsPath {
+            host: copy self.host,
+            device: copy self.device,
+            is_absolute: self.is_absolute,
+            components: v
+        }
+    }
+
+    fn push(&self, s: &str) -> WindowsPath {
+        let mut v = copy self.components;
+        let mut ss = ~[];
+        for str::each_split_nonempty(s, |c| windows::is_sep(c as u8)) |s| {
+            ss.push(s.to_owned())
+        }
+        v.push_all_move(ss);
+        WindowsPath { components: v, ..copy *self }
+    }
+
+    fn pop(&self) -> WindowsPath {
+        let mut cs = copy self.components;
+        if cs.len() != 0 {
+            cs.pop();
+        }
+        WindowsPath {
+            host: copy self.host,
+            device: copy self.device,
+            is_absolute: self.is_absolute,
+            components: cs,
+        }
+    }
+
+    fn normalize(&self) -> WindowsPath {
+        WindowsPath {
+            host: copy self.host,
+            device: match self.device {
+                None => None,
+
+                // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
+                // to_ascii_consume and to_str_consume to not do a unnecessary copy.
+                Some(ref device) => Some(device.to_ascii().to_upper().to_str_ascii())
+            },
+            is_absolute: self.is_absolute,
+            components: normalize(self.components)
+        }
+    }
+
+    fn is_absolute(&self) -> bool {
+        self.is_absolute
+    }
+}
+
+
+pub fn normalize(components: &[~str]) -> ~[~str] {
+    let mut cs = ~[];
+    for components.each |c| {
+        if *c == ~"." && components.len() > 1 { loop; }
+        if *c == ~"" { loop; }
+        if *c == ~".." && cs.len() != 0 {
+            cs.pop();
+            loop;
+        }
+        cs.push(copy *c);
+    }
+    cs
+}
+
+// Various windows helpers, and tests for the impl.
+pub mod windows {
+    use libc;
+    use option::{None, Option, Some};
+
+    #[inline(always)]
+    pub fn is_sep(u: u8) -> bool {
+        u == '/' as u8 || u == '\\' as u8
+    }
+
+    pub fn extract_unc_prefix(s: &str) -> Option<(~str,~str)> {
+        if (s.len() > 1 &&
+            (s[0] == '\\' as u8 || s[0] == '/' as u8) &&
+            s[0] == s[1]) {
+            let mut i = 2;
+            while i < s.len() {
+                if is_sep(s[i]) {
+                    let pre = s.slice(2, i).to_owned();
+                    let rest = s.slice(i, s.len()).to_owned();
+                    return Some((pre, rest));
+                }
+                i += 1;
+            }
+        }
+        None
+    }
+
+    pub fn extract_drive_prefix(s: &str) -> Option<(~str,~str)> {
+        unsafe {
+            if (s.len() > 1 &&
+                libc::isalpha(s[0] as libc::c_int) != 0 &&
+                s[1] == ':' as u8) {
+                let rest = if s.len() == 2 {
+                    ~""
+                } else {
+                    s.slice(2, s.len()).to_owned()
+                };
+                return Some((s.slice(0,1).to_owned(), rest));
+            }
+            None
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use option::{None, Some};
+    use path::{PosixPath, WindowsPath, windows};
+    use str;
+
+    #[test]
+    fn test_double_slash_collapsing() {
+        let path = PosixPath("tmp/");
+        let path = path.push("/hmm");
+        let path = path.normalize();
+        assert_eq!(~"tmp/hmm", path.to_str());
+
+        let path = WindowsPath("tmp/");
+        let path = path.push("/hmm");
+        let path = path.normalize();
+        assert_eq!(~"tmp\\hmm", path.to_str());
+    }
+
+    #[test]
+    fn test_filetype_foo_bar() {
+        let wp = PosixPath("foo.bar");
+        assert_eq!(wp.filetype(), Some(~".bar"));
+
+        let wp = WindowsPath("foo.bar");
+        assert_eq!(wp.filetype(), Some(~".bar"));
+    }
+
+    #[test]
+    fn test_filetype_foo() {
+        let wp = PosixPath("foo");
+        assert_eq!(wp.filetype(), None);
+
+        let wp = WindowsPath("foo");
+        assert_eq!(wp.filetype(), None);
+    }
+
+    #[test]
+    fn test_posix_paths() {
+        fn t(wp: &PosixPath, s: &str) {
+            let ss = wp.to_str();
+            let sss = str::to_owned(s);
+            if (ss != sss) {
+                debug!("got %s", ss);
+                debug!("expected %s", sss);
+                assert_eq!(ss, sss);
+            }
+        }
+
+        t(&(PosixPath("hi")), "hi");
+        t(&(PosixPath("/lib")), "/lib");
+        t(&(PosixPath("hi/there")), "hi/there");
+        t(&(PosixPath("hi/there.txt")), "hi/there.txt");
+
+        t(&(PosixPath("hi/there.txt")), "hi/there.txt");
+        t(&(PosixPath("hi/there.txt")
+           .with_filetype("")), "hi/there");
+
+        t(&(PosixPath("/a/b/c/there.txt")
+            .with_dirname("hi")), "hi/there.txt");
+
+        t(&(PosixPath("hi/there.txt")
+            .with_dirname(".")), "./there.txt");
+
+        t(&(PosixPath("a/b/c")
+            .push("..")), "a/b/c/..");
+
+        t(&(PosixPath("there.txt")
+            .with_filetype("o")), "there.o");
+
+        t(&(PosixPath("hi/there.txt")
+            .with_filetype("o")), "hi/there.o");
+
+        t(&(PosixPath("hi/there.txt")
+            .with_filetype("o")
+            .with_dirname("/usr/lib")),
+          "/usr/lib/there.o");
+
+        t(&(PosixPath("hi/there.txt")
+            .with_filetype("o")
+            .with_dirname("/usr/lib/")),
+          "/usr/lib/there.o");
+
+        t(&(PosixPath("hi/there.txt")
+            .with_filetype("o")
+            .with_dirname("/usr//lib//")),
+            "/usr/lib/there.o");
+
+        t(&(PosixPath("/usr/bin/rust")
+            .push_many([~"lib", ~"thingy.so"])
+            .with_filestem("librustc")),
+          "/usr/bin/rust/lib/librustc.so");
+
+    }
+
+    #[test]
+    fn test_normalize() {
+        fn t(wp: &PosixPath, s: &str) {
+            let ss = wp.to_str();
+            let sss = str::to_owned(s);
+            if (ss != sss) {
+                debug!("got %s", ss);
+                debug!("expected %s", sss);
+                assert_eq!(ss, sss);
+            }
+        }
+
+        t(&(PosixPath("hi/there.txt")
+            .with_dirname(".").normalize()), "there.txt");
+
+        t(&(PosixPath("a/b/../c/././/../foo.txt/").normalize()),
+          "a/foo.txt");
+
+        t(&(PosixPath("a/b/c")
+            .push("..").normalize()), "a/b");
+    }
+
+    #[test]
+    fn test_extract_unc_prefixes() {
+        assert!(windows::extract_unc_prefix("\\\\").is_none());
+        assert!(windows::extract_unc_prefix("//").is_none());
+        assert!(windows::extract_unc_prefix("\\\\hi").is_none());
+        assert!(windows::extract_unc_prefix("//hi").is_none());
+        assert!(windows::extract_unc_prefix("\\\\hi\\") ==
+            Some((~"hi", ~"\\")));
+        assert!(windows::extract_unc_prefix("//hi\\") ==
+            Some((~"hi", ~"\\")));
+        assert!(windows::extract_unc_prefix("\\\\hi\\there") ==
+            Some((~"hi", ~"\\there")));
+        assert!(windows::extract_unc_prefix("//hi/there") ==
+            Some((~"hi", ~"/there")));
+        assert!(windows::extract_unc_prefix(
+            "\\\\hi\\there\\friends.txt") ==
+            Some((~"hi", ~"\\there\\friends.txt")));
+        assert!(windows::extract_unc_prefix(
+            "//hi\\there\\friends.txt") ==
+            Some((~"hi", ~"\\there\\friends.txt")));
+    }
+
+    #[test]
+    fn test_extract_drive_prefixes() {
+        assert!(windows::extract_drive_prefix("c").is_none());
+        assert!(windows::extract_drive_prefix("c:") ==
+                     Some((~"c", ~"")));
+        assert!(windows::extract_drive_prefix("d:") ==
+                     Some((~"d", ~"")));
+        assert!(windows::extract_drive_prefix("z:") ==
+                     Some((~"z", ~"")));
+        assert!(windows::extract_drive_prefix("c:\\hi") ==
+                     Some((~"c", ~"\\hi")));
+        assert!(windows::extract_drive_prefix("d:hi") ==
+                     Some((~"d", ~"hi")));
+        assert!(windows::extract_drive_prefix("c:hi\\there.txt") ==
+                     Some((~"c", ~"hi\\there.txt")));
+        assert!(windows::extract_drive_prefix("c:\\hi\\there.txt") ==
+                     Some((~"c", ~"\\hi\\there.txt")));
+    }
+
+    #[test]
+    fn test_windows_paths() {
+        fn t(wp: &WindowsPath, s: &str) {
+            let ss = wp.to_str();
+            let sss = str::to_owned(s);
+            if (ss != sss) {
+                debug!("got %s", ss);
+                debug!("expected %s", sss);
+                assert_eq!(ss, sss);
+            }
+        }
+
+        t(&(WindowsPath("hi")), "hi");
+        t(&(WindowsPath("hi/there")), "hi\\there");
+        t(&(WindowsPath("hi/there.txt")), "hi\\there.txt");
+
+        t(&(WindowsPath("there.txt")
+            .with_filetype("o")), "there.o");
+
+        t(&(WindowsPath("hi/there.txt")
+            .with_filetype("o")), "hi\\there.o");
+
+        t(&(WindowsPath("hi/there.txt")
+            .with_filetype("o")
+            .with_dirname("c:\\program files A")),
+          "c:\\program files A\\there.o");
+
+        t(&(WindowsPath("hi/there.txt")
+            .with_filetype("o")
+            .with_dirname("c:\\program files B\\")),
+          "c:\\program files B\\there.o");
+
+        t(&(WindowsPath("hi/there.txt")
+            .with_filetype("o")
+            .with_dirname("c:\\program files C\\/")),
+            "c:\\program files C\\there.o");
+
+        t(&(WindowsPath("c:\\program files (x86)\\rust")
+            .push_many([~"lib", ~"thingy.dll"])
+            .with_filename("librustc.dll")),
+          "c:\\program files (x86)\\rust\\lib\\librustc.dll");
+
+        t(&(WindowsPath("\\\\computer\\share")
+            .unsafe_join(&WindowsPath("\\a"))),
+          "\\\\computer\\a");
+
+        t(&(WindowsPath("//computer/share")
+            .unsafe_join(&WindowsPath("\\a"))),
+          "\\\\computer\\a");
+
+        t(&(WindowsPath("//computer/share")
+            .unsafe_join(&WindowsPath("\\\\computer\\share"))),
+          "\\\\computer\\share");
+
+        t(&(WindowsPath("C:/whatever")
+            .unsafe_join(&WindowsPath("//computer/share/a/b"))),
+          "\\\\computer\\share\\a\\b");
+
+        t(&(WindowsPath("C:")
+            .unsafe_join(&WindowsPath("D:/foo"))),
+          "D:\\foo");
+
+        t(&(WindowsPath("C:")
+            .unsafe_join(&WindowsPath("B"))),
+          "C:B");
+
+        t(&(WindowsPath("C:")
+            .unsafe_join(&WindowsPath("/foo"))),
+          "C:\\foo");
+
+        t(&(WindowsPath("C:\\")
+            .unsafe_join(&WindowsPath("\\bar"))),
+          "C:\\bar");
+
+        t(&(WindowsPath("")
+            .unsafe_join(&WindowsPath(""))),
+          "");
+
+        t(&(WindowsPath("")
+            .unsafe_join(&WindowsPath("a"))),
+          "a");
+
+        t(&(WindowsPath("")
+            .unsafe_join(&WindowsPath("C:\\a"))),
+          "C:\\a");
+
+        t(&(WindowsPath("c:\\foo")
+            .normalize()),
+          "C:\\foo");
+    }
+
+    #[test]
+    fn test_windows_path_restrictions() {
+        assert_eq!(WindowsPath("hi").is_restricted(), false);
+        assert_eq!(WindowsPath("C:\\NUL").is_restricted(), true);
+        assert_eq!(WindowsPath("C:\\COM1.TXT").is_restricted(), true);
+        assert_eq!(WindowsPath("c:\\prn.exe").is_restricted(), true);
+    }
+}
diff --git a/src/libstd/pipes.rs b/src/libstd/pipes.rs
new file mode 100644
index 00000000000..1c2b57bb2df
--- /dev/null
+++ b/src/libstd/pipes.rs
@@ -0,0 +1,916 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*! Runtime support for message passing with protocol enforcement.
+
+
+Pipes consist of two endpoints. One endpoint can send messages and
+the other can receive messages. The set of legal messages and which
+directions they can flow at any given point are determined by a
+protocol. Below is an example protocol.
+
+~~~
+proto! pingpong (
+    ping: send {
+        ping -> pong
+    }
+    pong: recv {
+        pong -> ping
+    }
+)
+~~~
+
+The `proto!` syntax extension will convert this into a module called
+`pingpong`, which includes a set of types and functions that can be
+used to write programs that follow the pingpong protocol.
+
+*/
+
+/* IMPLEMENTATION NOTES
+
+The initial design for this feature is available at:
+
+https://github.com/eholk/rust/wiki/Proposal-for-channel-contracts
+
+Much of the design in that document is still accurate. There are
+several components for the pipe implementation. First of all is the
+syntax extension. To see how that works, it is best see comments in
+libsyntax/ext/pipes.rs.
+
+This module includes two related pieces of the runtime
+implementation: support for unbounded and bounded
+protocols. The main difference between the two is the type of the
+buffer that is carried along in the endpoint data structures.
+
+
+The heart of the implementation is the packet type. It contains a
+header and a payload field. Much of the code in this module deals with
+the header field. This is where the synchronization information is
+stored. In the case of a bounded protocol, the header also includes a
+pointer to the buffer the packet is contained in.
+
+Packets represent a single message in a protocol. The payload field
+gets instatiated at the type of the message, which is usually an enum
+generated by the pipe compiler. Packets are conceptually single use,
+although in bounded protocols they are reused each time around the
+loop.
+
+
+Packets are usually handled through a send_packet_buffered or
+recv_packet_buffered object. Each packet is referenced by one
+send_packet and one recv_packet, and these wrappers enforce that only
+one end can send and only one end can receive. The structs also
+include a destructor that marks packets are terminated if the sender
+or receiver destroys the object before sending or receiving a value.
+
+The *_packet_buffered structs take two type parameters. The first is
+the message type for the current packet (or state). The second
+represents the type of the whole buffer. For bounded protocols, the
+protocol compiler generates a struct with a field for each protocol
+state. This generated struct is used as the buffer type parameter. For
+unbounded protocols, the buffer is simply one packet, so there is a
+shorthand struct called send_packet and recv_packet, where the buffer
+type is just `packet<T>`. Using the same underlying structure for both
+bounded and unbounded protocols allows for less code duplication.
+
+*/
+
+use container::Container;
+use cast::{forget, transmute, transmute_copy};
+use either::{Either, Left, Right};
+use kinds::Owned;
+use libc;
+use ops::Drop;
+use option::{None, Option, Some};
+use unstable::finally::Finally;
+use unstable::intrinsics;
+use ptr;
+use ptr::Ptr;
+use task;
+use vec;
+use vec::OwnedVector;
+use util::replace;
+
+static SPIN_COUNT: uint = 0;
+
+macro_rules! move_it (
+    { $x:expr } => ( unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } )
+)
+
+#[deriving(Eq)]
+enum State {
+    Empty,
+    Full,
+    Blocked,
+    Terminated
+}
+
+pub struct BufferHeader {
+    // Tracks whether this buffer needs to be freed. We can probably
+    // get away with restricting it to 0 or 1, if we're careful.
+    ref_count: int,
+
+    // We may want a drop, and to be careful about stringing this
+    // thing along.
+}
+
+pub fn BufferHeader() -> BufferHeader {
+    BufferHeader {
+        ref_count: 0
+    }
+}
+
+// This is for protocols to associate extra data to thread around.
+pub struct Buffer<T> {
+    header: BufferHeader,
+    data: T,
+}
+
+pub struct PacketHeader {
+    state: State,
+    blocked_task: *rust_task,
+
+    // This is a transmute_copy of a ~buffer, that can also be cast
+    // to a buffer_header if need be.
+    buffer: *libc::c_void,
+}
+
+pub fn PacketHeader() -> PacketHeader {
+    PacketHeader {
+        state: Empty,
+        blocked_task: ptr::null(),
+        buffer: ptr::null()
+    }
+}
+
+pub impl PacketHeader {
+    // Returns the old state.
+    unsafe fn mark_blocked(&mut self, this: *rust_task) -> State {
+        rustrt::rust_task_ref(this);
+        let old_task = swap_task(&mut self.blocked_task, this);
+        assert!(old_task.is_null());
+        swap_state_acq(&mut self.state, Blocked)
+    }
+
+    unsafe fn unblock(&mut self) {
+        let old_task = swap_task(&mut self.blocked_task, ptr::null());
+        if !old_task.is_null() {
+            rustrt::rust_task_deref(old_task)
+        }
+        match swap_state_acq(&mut self.state, Empty) {
+          Empty | Blocked => (),
+          Terminated => self.state = Terminated,
+          Full => self.state = Full
+        }
+    }
+
+    // unsafe because this can do weird things to the space/time
+    // continuum. It ends making multiple unique pointers to the same
+    // thing. You'll probably want to forget them when you're done.
+    unsafe fn buf_header(&mut self) -> ~BufferHeader {
+        assert!(self.buffer.is_not_null());
+        transmute_copy(&self.buffer)
+    }
+
+    fn set_buffer<T:Owned>(&mut self, b: ~Buffer<T>) {
+        unsafe {
+            self.buffer = transmute_copy(&b);
+        }
+    }
+}
+
+pub struct Packet<T> {
+    header: PacketHeader,
+    payload: Option<T>,
+}
+
+pub trait HasBuffer {
+    fn set_buffer(&mut self, b: *libc::c_void);
+}
+
+impl<T:Owned> HasBuffer for Packet<T> {
+    fn set_buffer(&mut self, b: *libc::c_void) {
+        self.header.buffer = b;
+    }
+}
+
+pub fn mk_packet<T:Owned>() -> Packet<T> {
+    Packet {
+        header: PacketHeader(),
+        payload: None,
+    }
+}
+fn unibuffer<T>() -> ~Buffer<Packet<T>> {
+    let mut b = ~Buffer {
+        header: BufferHeader(),
+        data: Packet {
+            header: PacketHeader(),
+            payload: None,
+        }
+    };
+
+    unsafe {
+        b.data.header.buffer = transmute_copy(&b);
+    }
+    b
+}
+
+pub fn packet<T>() -> *mut Packet<T> {
+    let mut b = unibuffer();
+    let p = ptr::to_mut_unsafe_ptr(&mut b.data);
+    // We'll take over memory management from here.
+    unsafe {
+        forget(b);
+    }
+    p
+}
+
+pub fn entangle_buffer<T:Owned,Tstart:Owned>(
+    mut buffer: ~Buffer<T>,
+    init: &fn(*libc::c_void, x: &mut T) -> *mut Packet<Tstart>)
+    -> (SendPacketBuffered<Tstart, T>, RecvPacketBuffered<Tstart, T>) {
+    unsafe {
+        let p = init(transmute_copy(&buffer), &mut buffer.data);
+        forget(buffer);
+        (SendPacketBuffered(p), RecvPacketBuffered(p))
+    }
+}
+
+pub fn swap_task(dst: &mut *rust_task, src: *rust_task) -> *rust_task {
+    // It might be worth making both acquire and release versions of
+    // this.
+    unsafe {
+        transmute(intrinsics::atomic_xchg(transmute(dst), src as int))
+    }
+}
+
+#[allow(non_camel_case_types)]
+pub type rust_task = libc::c_void;
+
+pub mod rustrt {
+    use libc;
+    use super::rust_task;
+
+    pub extern {
+        #[rust_stack]
+        unsafe fn rust_get_task() -> *rust_task;
+        #[rust_stack]
+        unsafe fn rust_task_ref(task: *rust_task);
+        unsafe fn rust_task_deref(task: *rust_task);
+
+        #[rust_stack]
+        unsafe fn task_clear_event_reject(task: *rust_task);
+
+        unsafe fn task_wait_event(this: *rust_task,
+                                  killed: &mut *libc::c_void)
+                               -> bool;
+        unsafe fn task_signal_event(target: *rust_task, event: *libc::c_void);
+    }
+}
+
+fn wait_event(this: *rust_task) -> *libc::c_void {
+    unsafe {
+        let mut event = ptr::null();
+
+        let killed = rustrt::task_wait_event(this, &mut event);
+        if killed && !task::failing() {
+            fail!("killed")
+        }
+        event
+    }
+}
+
+fn swap_state_acq(dst: &mut State, src: State) -> State {
+    unsafe {
+        transmute(intrinsics::atomic_xchg_acq(transmute(dst), src as int))
+    }
+}
+
+fn swap_state_rel(dst: &mut State, src: State) -> State {
+    unsafe {
+        transmute(intrinsics::atomic_xchg_rel(transmute(dst), src as int))
+    }
+}
+
+pub unsafe fn get_buffer<T>(p: *mut PacketHeader) -> ~Buffer<T> {
+    transmute((*p).buf_header())
+}
+
+// This could probably be done with SharedMutableState to avoid move_it!().
+struct BufferResource<T> {
+    buffer: ~Buffer<T>,
+
+}
+
+#[unsafe_destructor]
+impl<T> Drop for BufferResource<T> {
+    fn finalize(&self) {
+        unsafe {
+            let this: &mut BufferResource<T> = transmute(self);
+
+            let mut b = move_it!(this.buffer);
+            //let p = ptr::to_unsafe_ptr(*b);
+            //error!("drop %?", p);
+            let old_count = intrinsics::atomic_xsub_rel(
+                &mut b.header.ref_count,
+                1);
+            //let old_count = atomic_xchng_rel(b.header.ref_count, 0);
+            if old_count == 1 {
+                // The new count is 0.
+
+                // go go gadget drop glue
+            }
+            else {
+                forget(b)
+            }
+        }
+    }
+}
+
+fn BufferResource<T>(mut b: ~Buffer<T>) -> BufferResource<T> {
+    //let p = ptr::to_unsafe_ptr(*b);
+    //error!("take %?", p);
+    unsafe {
+        intrinsics::atomic_xadd_acq(&mut b.header.ref_count, 1);
+    }
+
+    BufferResource {
+        // tjc: ????
+        buffer: b
+    }
+}
+
+pub fn send<T,Tbuffer>(mut p: SendPacketBuffered<T,Tbuffer>,
+                       payload: T)
+                       -> bool {
+    let header = p.header();
+    let p_ = p.unwrap();
+    let p = unsafe { &mut *p_ };
+    assert_eq!(ptr::to_unsafe_ptr(&(p.header)), header);
+    assert!(p.payload.is_none());
+    p.payload = Some(payload);
+    let old_state = swap_state_rel(&mut p.header.state, Full);
+    match old_state {
+        Empty => {
+            // Yay, fastpath.
+
+            // The receiver will eventually clean this up.
+            //unsafe { forget(p); }
+            return true;
+        }
+        Full => fail!("duplicate send"),
+        Blocked => {
+            debug!("waking up task for %?", p_);
+            let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
+            if !old_task.is_null() {
+                unsafe {
+                    rustrt::task_signal_event(
+                        old_task,
+                        ptr::to_unsafe_ptr(&(p.header)) as *libc::c_void);
+                    rustrt::rust_task_deref(old_task);
+                }
+            }
+
+            // The receiver will eventually clean this up.
+            //unsafe { forget(p); }
+            return true;
+        }
+        Terminated => {
+            // The receiver will never receive this. Rely on drop_glue
+            // to clean everything up.
+            return false;
+        }
+    }
+}
+
+/** Receives a message from a pipe.
+
+Fails if the sender closes the connection.
+
+*/
+pub fn recv<T:Owned,Tbuffer:Owned>(
+    p: RecvPacketBuffered<T, Tbuffer>) -> T {
+    try_recv(p).expect("connection closed")
+}
+
+/** Attempts to receive a message from a pipe.
+
+Returns `None` if the sender has closed the connection without sending
+a message, or `Some(T)` if a message was received.
+
+*/
+pub fn try_recv<T:Owned,Tbuffer:Owned>(mut p: RecvPacketBuffered<T, Tbuffer>)
+                                       -> Option<T> {
+    let p_ = p.unwrap();
+    let p = unsafe { &mut *p_ };
+
+    do (|| {
+        try_recv_(p)
+    }).finally {
+        unsafe {
+            if task::failing() {
+                p.header.state = Terminated;
+                let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
+                if !old_task.is_null() {
+                    rustrt::rust_task_deref(old_task);
+                }
+            }
+        }
+    }
+}
+
+fn try_recv_<T:Owned>(p: &mut Packet<T>) -> Option<T> {
+    // optimistic path
+    match p.header.state {
+      Full => {
+        let payload = replace(&mut p.payload, None);
+        p.header.state = Empty;
+        return Some(payload.unwrap())
+      },
+      Terminated => return None,
+      _ => {}
+    }
+
+    // regular path
+    let this = unsafe { rustrt::rust_get_task() };
+    unsafe {
+        rustrt::task_clear_event_reject(this);
+        rustrt::rust_task_ref(this);
+    };
+    debug!("blocked = %x this = %x", p.header.blocked_task as uint,
+           this as uint);
+    let old_task = swap_task(&mut p.header.blocked_task, this);
+    debug!("blocked = %x this = %x old_task = %x",
+           p.header.blocked_task as uint,
+           this as uint, old_task as uint);
+    assert!(old_task.is_null());
+    let mut first = true;
+    let mut count = SPIN_COUNT;
+    loop {
+        unsafe {
+            rustrt::task_clear_event_reject(this);
+        }
+
+        let old_state = swap_state_acq(&mut p.header.state,
+                                       Blocked);
+        match old_state {
+          Empty => {
+            debug!("no data available on %?, going to sleep.", p);
+            if count == 0 {
+                wait_event(this);
+            }
+            else {
+                count -= 1;
+                // FIXME (#524): Putting the yield here destroys a lot
+                // of the benefit of spinning, since we still go into
+                // the scheduler at every iteration. However, without
+                // this everything spins too much because we end up
+                // sometimes blocking the thing we are waiting on.
+                task::yield();
+            }
+            debug!("woke up, p.state = %?", copy p.header.state);
+          }
+          Blocked => if first {
+            fail!("blocking on already blocked packet")
+          },
+          Full => {
+            let payload = replace(&mut p.payload, None);
+            let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
+            if !old_task.is_null() {
+                unsafe {
+                    rustrt::rust_task_deref(old_task);
+                }
+            }
+            p.header.state = Empty;
+            return Some(payload.unwrap())
+          }
+          Terminated => {
+            // This assert detects when we've accidentally unsafely
+            // casted too big of a number to a state.
+            assert_eq!(old_state, Terminated);
+
+            let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
+            if !old_task.is_null() {
+                unsafe {
+                    rustrt::rust_task_deref(old_task);
+                }
+            }
+            return None;
+          }
+        }
+        first = false;
+    }
+}
+
+/// Returns true if messages are available.
+pub fn peek<T:Owned,Tb:Owned>(p: &mut RecvPacketBuffered<T, Tb>) -> bool {
+    unsafe {
+        match (*p.header()).state {
+            Empty | Terminated => false,
+            Blocked => fail!("peeking on blocked packet"),
+            Full => true
+        }
+    }
+}
+
+fn sender_terminate<T:Owned>(p: *mut Packet<T>) {
+    let p = unsafe {
+        &mut *p
+    };
+    match swap_state_rel(&mut p.header.state, Terminated) {
+      Empty => {
+        // The receiver will eventually clean up.
+      }
+      Blocked => {
+        // wake up the target
+        let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
+        if !old_task.is_null() {
+            unsafe {
+                rustrt::task_signal_event(
+                    old_task,
+                    ptr::to_unsafe_ptr(&(p.header)) as *libc::c_void);
+                rustrt::rust_task_deref(old_task);
+            }
+        }
+        // The receiver will eventually clean up.
+      }
+      Full => {
+        // This is impossible
+        fail!("you dun goofed")
+      }
+      Terminated => {
+        assert!(p.header.blocked_task.is_null());
+        // I have to clean up, use drop_glue
+      }
+    }
+}
+
+fn receiver_terminate<T:Owned>(p: *mut Packet<T>) {
+    let p = unsafe {
+        &mut *p
+    };
+    match swap_state_rel(&mut p.header.state, Terminated) {
+      Empty => {
+        assert!(p.header.blocked_task.is_null());
+        // the sender will clean up
+      }
+      Blocked => {
+        let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
+        if !old_task.is_null() {
+            unsafe {
+                rustrt::rust_task_deref(old_task);
+                assert_eq!(old_task, rustrt::rust_get_task());
+            }
+        }
+      }
+      Terminated | Full => {
+        assert!(p.header.blocked_task.is_null());
+        // I have to clean up, use drop_glue
+      }
+    }
+}
+
+/** Returns when one of the packet headers reports data is available.
+
+This function is primarily intended for building higher level waiting
+functions, such as `select`, `select2`, etc.
+
+It takes a vector slice of packet_headers and returns an index into
+that vector. The index points to an endpoint that has either been
+closed by the sender or has a message waiting to be received.
+
+*/
+pub fn wait_many<T: Selectable>(pkts: &mut [T]) -> uint {
+    let this = unsafe {
+        rustrt::rust_get_task()
+    };
+
+    unsafe {
+        rustrt::task_clear_event_reject(this);
+    }
+
+    let mut data_avail = false;
+    let mut ready_packet = pkts.len();
+    for vec::eachi_mut(pkts) |i, p| {
+        unsafe {
+            let p = &mut *p.header();
+            let old = p.mark_blocked(this);
+            match old {
+                Full | Terminated => {
+                    data_avail = true;
+                    ready_packet = i;
+                    (*p).state = old;
+                    break;
+                }
+                Blocked => fail!("blocking on blocked packet"),
+                Empty => ()
+            }
+        }
+    }
+
+    while !data_avail {
+        debug!("sleeping on %? packets", pkts.len());
+        let event = wait_event(this) as *PacketHeader;
+
+        let mut pos = None;
+        for vec::eachi_mut(pkts) |i, p| {
+            if p.header() == event {
+                pos = Some(i);
+                break;
+            }
+        };
+
+        match pos {
+          Some(i) => {
+            ready_packet = i;
+            data_avail = true;
+          }
+          None => debug!("ignoring spurious event, %?", event)
+        }
+    }
+
+    debug!("%?", &mut pkts[ready_packet]);
+
+    for vec::each_mut(pkts) |p| {
+        unsafe {
+            (*p.header()).unblock()
+        }
+    }
+
+    debug!("%?, %?", ready_packet, &mut pkts[ready_packet]);
+
+    unsafe {
+        assert!((*pkts[ready_packet].header()).state == Full
+                     || (*pkts[ready_packet].header()).state == Terminated);
+    }
+
+    ready_packet
+}
+
+/** The sending end of a pipe. It can be used to send exactly one
+message.
+
+*/
+pub type SendPacket<T> = SendPacketBuffered<T, Packet<T>>;
+
+pub fn SendPacket<T>(p: *mut Packet<T>) -> SendPacket<T> {
+    SendPacketBuffered(p)
+}
+
+pub struct SendPacketBuffered<T, Tbuffer> {
+    p: Option<*mut Packet<T>>,
+    buffer: Option<BufferResource<Tbuffer>>,
+}
+
+#[unsafe_destructor]
+impl<T:Owned,Tbuffer:Owned> Drop for SendPacketBuffered<T,Tbuffer> {
+    fn finalize(&self) {
+        unsafe {
+            let this: &mut SendPacketBuffered<T,Tbuffer> = transmute(self);
+            if this.p != None {
+                let p = replace(&mut this.p, None);
+                sender_terminate(p.unwrap())
+            }
+        }
+    }
+}
+
+pub fn SendPacketBuffered<T,Tbuffer>(p: *mut Packet<T>)
+                                     -> SendPacketBuffered<T,Tbuffer> {
+    SendPacketBuffered {
+        p: Some(p),
+        buffer: unsafe {
+            Some(BufferResource(get_buffer(&mut (*p).header)))
+        }
+    }
+}
+
+pub impl<T,Tbuffer> SendPacketBuffered<T,Tbuffer> {
+    fn unwrap(&mut self) -> *mut Packet<T> {
+        replace(&mut self.p, None).unwrap()
+    }
+
+    fn header(&mut self) -> *mut PacketHeader {
+        match self.p {
+            Some(packet) => unsafe {
+                let packet = &mut *packet;
+                let header = ptr::to_mut_unsafe_ptr(&mut packet.header);
+                header
+            },
+            None => fail!("packet already consumed")
+        }
+    }
+
+    fn reuse_buffer(&mut self) -> BufferResource<Tbuffer> {
+        //error!("send reuse_buffer");
+        replace(&mut self.buffer, None).unwrap()
+    }
+}
+
+/// Represents the receive end of a pipe. It can receive exactly one
+/// message.
+pub type RecvPacket<T> = RecvPacketBuffered<T, Packet<T>>;
+
+pub fn RecvPacket<T>(p: *mut Packet<T>) -> RecvPacket<T> {
+    RecvPacketBuffered(p)
+}
+
+pub struct RecvPacketBuffered<T, Tbuffer> {
+    p: Option<*mut Packet<T>>,
+    buffer: Option<BufferResource<Tbuffer>>,
+}
+
+#[unsafe_destructor]
+impl<T:Owned,Tbuffer:Owned> Drop for RecvPacketBuffered<T,Tbuffer> {
+    fn finalize(&self) {
+        unsafe {
+            let this: &mut RecvPacketBuffered<T,Tbuffer> = transmute(self);
+            if this.p != None {
+                let p = replace(&mut this.p, None);
+                receiver_terminate(p.unwrap())
+            }
+        }
+    }
+}
+
+pub impl<T:Owned,Tbuffer:Owned> RecvPacketBuffered<T, Tbuffer> {
+    fn unwrap(&mut self) -> *mut Packet<T> {
+        replace(&mut self.p, None).unwrap()
+    }
+
+    fn reuse_buffer(&mut self) -> BufferResource<Tbuffer> {
+        replace(&mut self.buffer, None).unwrap()
+    }
+}
+
+impl<T:Owned,Tbuffer:Owned> Selectable for RecvPacketBuffered<T, Tbuffer> {
+    fn header(&mut self) -> *mut PacketHeader {
+        match self.p {
+            Some(packet) => unsafe {
+                let packet = &mut *packet;
+                let header = ptr::to_mut_unsafe_ptr(&mut packet.header);
+                header
+            },
+            None => fail!("packet already consumed")
+        }
+    }
+}
+
+pub fn RecvPacketBuffered<T,Tbuffer>(p: *mut Packet<T>)
+                                     -> RecvPacketBuffered<T,Tbuffer> {
+    RecvPacketBuffered {
+        p: Some(p),
+        buffer: unsafe {
+            Some(BufferResource(get_buffer(&mut (*p).header)))
+        }
+    }
+}
+
+pub fn entangle<T>() -> (SendPacket<T>, RecvPacket<T>) {
+    let p = packet();
+    (SendPacket(p), RecvPacket(p))
+}
+
+/** Receives a message from one of two endpoints.
+
+The return value is `left` if the first endpoint received something,
+or `right` if the second endpoint receives something. In each case,
+the result includes the other endpoint as well so it can be used
+again. Below is an example of using `select2`.
+
+~~~
+match select2(a, b) {
+  left((none, b)) {
+    // endpoint a was closed.
+  }
+  right((a, none)) {
+    // endpoint b was closed.
+  }
+  left((Some(_), b)) {
+    // endpoint a received a message
+  }
+  right(a, Some(_)) {
+    // endpoint b received a message.
+  }
+}
+~~~
+
+Sometimes messages will be available on both endpoints at once. In
+this case, `select2` may return either `left` or `right`.
+
+*/
+pub fn select2<A:Owned,Ab:Owned,B:Owned,Bb:Owned>(
+    mut a: RecvPacketBuffered<A, Ab>,
+    mut b: RecvPacketBuffered<B, Bb>)
+    -> Either<(Option<A>, RecvPacketBuffered<B, Bb>),
+              (RecvPacketBuffered<A, Ab>, Option<B>)> {
+    let mut endpoints = [ a.header(), b.header() ];
+    let i = wait_many(endpoints);
+    match i {
+        0 => Left((try_recv(a), b)),
+        1 => Right((a, try_recv(b))),
+        _ => fail!("select2 return an invalid packet")
+    }
+}
+
+pub trait Selectable {
+    fn header(&mut self) -> *mut PacketHeader;
+}
+
+impl Selectable for *mut PacketHeader {
+    fn header(&mut self) -> *mut PacketHeader { *self }
+}
+
+/// Returns the index of an endpoint that is ready to receive.
+pub fn selecti<T:Selectable>(endpoints: &mut [T]) -> uint {
+    wait_many(endpoints)
+}
+
+/// Returns 0 or 1 depending on which endpoint is ready to receive
+pub fn select2i<A:Selectable,B:Selectable>(a: &mut A, b: &mut B)
+                                           -> Either<(), ()> {
+    let mut endpoints = [ a.header(), b.header() ];
+    match wait_many(endpoints) {
+        0 => Left(()),
+        1 => Right(()),
+        _ => fail!("wait returned unexpected index")
+    }
+}
+
+/// Waits on a set of endpoints. Returns a message, its index, and a
+/// list of the remaining endpoints.
+pub fn select<T:Owned,Tb:Owned>(mut endpoints: ~[RecvPacketBuffered<T, Tb>])
+                                -> (uint,
+                                    Option<T>,
+                                    ~[RecvPacketBuffered<T, Tb>]) {
+    let mut endpoint_headers = ~[];
+    for vec::each_mut(endpoints) |endpoint| {
+        endpoint_headers.push(endpoint.header());
+    }
+
+    let ready = wait_many(endpoint_headers);
+    let mut remaining = endpoints;
+    let port = remaining.swap_remove(ready);
+    let result = try_recv(port);
+    (ready, result, remaining)
+}
+
+pub mod rt {
+    use option::{None, Option, Some};
+
+    // These are used to hide the option constructors from the
+    // compiler because their names are changing
+    pub fn make_some<T>(val: T) -> Option<T> { Some(val) }
+    pub fn make_none<T>() -> Option<T> { None }
+}
+
+#[cfg(test)]
+mod test {
+    use either::Right;
+    use comm::{Chan, Port, oneshot, recv_one, stream, Select2,
+               GenericChan, Peekable};
+
+    #[test]
+    fn test_select2() {
+        let (p1, c1) = stream();
+        let (p2, c2) = stream();
+
+        c1.send(~"abc");
+
+        let mut tuple = (p1, p2);
+        match tuple.select() {
+            Right(_) => fail!(),
+            _ => (),
+        }
+
+        c2.send(123);
+    }
+
+    #[test]
+    fn test_oneshot() {
+        let (p, c) = oneshot();
+
+        c.send(());
+
+        recv_one(p)
+    }
+
+    #[test]
+    fn test_peek_terminated() {
+        let (port, chan): (Port<int>, Chan<int>) = stream();
+
+        {
+            // Destroy the channel
+            let _chan = chan;
+        }
+
+        assert!(!port.peek());
+    }
+}
diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs
new file mode 100644
index 00000000000..58d0c40efa0
--- /dev/null
+++ b/src/libstd/prelude.rs
@@ -0,0 +1,111 @@
+// 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.
+
+//! The Rust prelude. Imported into every module by default.
+
+/* Reexported core operators */
+
+pub use either::{Either, Left, Right};
+pub use kinds::{Const, Copy, Owned};
+pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
+pub use ops::{BitAnd, BitOr, BitXor};
+pub use ops::{Drop};
+pub use ops::{Shl, Shr, Index};
+pub use option::{Option, Some, None};
+pub use result::{Result, Ok, Err};
+
+/* Reexported functions */
+
+pub use io::{print, println};
+
+/* Reexported types and traits */
+
+pub use clone::{Clone, DeepClone};
+pub use cmp::{Eq, ApproxEq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater, Equiv};
+pub use char::Char;
+pub use container::{Container, Mutable, Map, Set};
+pub use hash::Hash;
+pub use old_iter::{BaseIter, ReverseIter, MutableIter, ExtendedIter, EqIter};
+pub use old_iter::{CopyableIter, CopyableOrderedIter, CopyableNonstrictIter};
+pub use old_iter::{ExtendedMutableIter};
+pub use iter::Times;
+pub use num::{Num, NumCast};
+pub use num::{Orderable, Signed, Unsigned, Round};
+pub use num::{Algebraic, Trigonometric, Exponential, Hyperbolic};
+pub use num::{Integer, Fractional, Real, RealExt};
+pub use num::{Bitwise, BitCount, Bounded};
+pub use num::{Primitive, Int, Float};
+pub use path::GenericPath;
+pub use path::Path;
+pub use path::PosixPath;
+pub use path::WindowsPath;
+pub use ptr::Ptr;
+pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
+pub use str::{StrSlice, OwnedStr};
+pub use from_str::{FromStr};
+pub use to_bytes::IterBytes;
+pub use to_str::{ToStr, ToStrConsume};
+pub use tuple::{CopyableTuple, ImmutableTuple, ExtendedTupleOps};
+pub use tuple::{CloneableTuple2, CloneableTuple3, CloneableTuple4, CloneableTuple5};
+pub use tuple::{CloneableTuple6, CloneableTuple7, CloneableTuple8, CloneableTuple9};
+pub use tuple::{CloneableTuple10, CloneableTuple11, CloneableTuple12};
+pub use tuple::{ImmutableTuple2, ImmutableTuple3, ImmutableTuple4, ImmutableTuple5};
+pub use tuple::{ImmutableTuple6, ImmutableTuple7, ImmutableTuple8, ImmutableTuple9};
+pub use tuple::{ImmutableTuple10, ImmutableTuple11, ImmutableTuple12};
+pub use vec::{CopyableVector, ImmutableVector};
+pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
+pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector};
+pub use io::{Reader, ReaderUtil, Writer, WriterUtil};
+
+/* Reexported runtime types */
+pub use comm::{stream, Port, Chan, GenericChan, GenericSmartChan, GenericPort, Peekable};
+pub use task::spawn;
+
+/* Reexported modules */
+
+pub use at_vec;
+pub use bool;
+pub use cast;
+pub use char;
+pub use cmp;
+pub use either;
+pub use f32;
+pub use f64;
+pub use float;
+pub use i16;
+pub use i32;
+pub use i64;
+pub use i8;
+pub use int;
+pub use io;
+pub use iter;
+pub use old_iter;
+pub use libc;
+pub use local_data;
+pub use num;
+pub use ops;
+pub use option;
+pub use os;
+pub use path;
+pub use comm;
+pub use unstable;
+pub use ptr;
+pub use rand;
+pub use result;
+pub use str;
+pub use sys;
+pub use task;
+pub use to_str;
+pub use u16;
+pub use u32;
+pub use u64;
+pub use u8;
+pub use uint;
+pub use vec;
diff --git a/src/libstd/priority_queue.rs b/src/libstd/priority_queue.rs
deleted file mode 100644
index f1e0027146c..00000000000
--- a/src/libstd/priority_queue.rs
+++ /dev/null
@@ -1,320 +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.
-
-//! A priority queue implemented with a binary heap
-
-use core::old_iter::BaseIter;
-use core::unstable::intrinsics::{move_val_init, init};
-use core::unstable::intrinsics::uninit;
-use core::util::{replace, swap};
-
-pub struct PriorityQueue<T> {
-    priv data: ~[T],
-}
-
-impl<T:Ord> BaseIter<T> for PriorityQueue<T> {
-    /// Visit all values in the underlying vector.
-    ///
-    /// The values are **not** visited in order.
-    fn each(&self, f: &fn(&T) -> bool) -> bool { self.data.each(f) }
-
-    fn size_hint(&self) -> Option<uint> { self.data.size_hint() }
-}
-
-impl<T:Ord> Container for PriorityQueue<T> {
-    /// Returns the length of the queue
-    fn len(&const self) -> uint { vec::uniq_len(&const self.data) }
-
-    /// Returns true if a queue contains no elements
-    fn is_empty(&const self) -> bool { self.len() == 0 }
-}
-
-impl<T:Ord> Mutable for PriorityQueue<T> {
-    /// Drop all items from the queue
-    fn clear(&mut self) { self.data.truncate(0) }
-}
-
-pub impl <T:Ord> PriorityQueue<T> {
-    /// Returns the greatest item in the queue - fails if empty
-    fn top<'a>(&'a self) -> &'a T { &self.data[0] }
-
-    /// Returns the greatest item in the queue - None if empty
-    fn maybe_top<'a>(&'a self) -> Option<&'a T> {
-        if self.is_empty() { None } else { Some(self.top()) }
-    }
-
-    /// Returns the number of elements the queue can hold without reallocating
-    fn capacity(&self) -> uint { vec::capacity(&self.data) }
-
-    fn reserve(&mut self, n: uint) { vec::reserve(&mut self.data, n) }
-
-    fn reserve_at_least(&mut self, n: uint) {
-        vec::reserve_at_least(&mut self.data, n)
-    }
-
-    /// Pop the greatest item from the queue - fails if empty
-    fn pop(&mut self) -> T {
-        let mut item = self.data.pop();
-        if !self.is_empty() {
-            swap(&mut item, &mut self.data[0]);
-            self.siftdown(0);
-        }
-        item
-    }
-
-    /// Pop the greatest item from the queue - None if empty
-    fn maybe_pop(&mut self) -> Option<T> {
-        if self.is_empty() { None } else { Some(self.pop()) }
-    }
-
-    /// Push an item onto the queue
-    fn push(&mut self, item: T) {
-        self.data.push(item);
-        let new_len = self.len() - 1;
-        self.siftup(0, new_len);
-    }
-
-    /// Optimized version of a push followed by a pop
-    fn push_pop(&mut self, mut item: T) -> T {
-        if !self.is_empty() && self.data[0] > item {
-            swap(&mut item, &mut self.data[0]);
-            self.siftdown(0);
-        }
-        item
-    }
-
-    /// Optimized version of a pop followed by a push - fails if empty
-    fn replace(&mut self, mut item: T) -> T {
-        swap(&mut item, &mut self.data[0]);
-        self.siftdown(0);
-        item
-    }
-
-    /// Consume the PriorityQueue and return the underlying vector
-    fn to_vec(self) -> ~[T] { let PriorityQueue{data: v} = self; v }
-
-    /// Consume the PriorityQueue and return a vector in sorted
-    /// (ascending) order
-    fn to_sorted_vec(self) -> ~[T] {
-        let mut q = self;
-        let mut end = q.len();
-        while end > 1 {
-            end -= 1;
-            vec::swap(q.data, 0, end);
-            q.siftdown_range(0, end)
-        }
-        q.to_vec()
-    }
-
-    /// Create an empty PriorityQueue
-    fn new() -> PriorityQueue<T> { PriorityQueue{data: ~[],} }
-
-    /// Create a PriorityQueue from a vector (heapify)
-    fn from_vec(xs: ~[T]) -> PriorityQueue<T> {
-        let mut q = PriorityQueue{data: xs,};
-        let mut n = q.len() / 2;
-        while n > 0 {
-            n -= 1;
-            q.siftdown(n)
-        }
-        q
-    }
-
-    // The implementations of siftup and siftdown use unsafe blocks in
-    // order to move an element out of the vector (leaving behind a
-    // zeroed element), shift along the others and move it back into the
-    // vector over the junk element.  This reduces the constant factor
-    // compared to using swaps, which involves twice as many moves.
-
-    priv fn siftup(&mut self, start: uint, mut pos: uint) {
-        unsafe {
-            let new = replace(&mut self.data[pos], init());
-
-            while pos > start {
-                let parent = (pos - 1) >> 1;
-                if new > self.data[parent] {
-                    let x = replace(&mut self.data[parent], init());
-                    move_val_init(&mut self.data[pos], x);
-                    pos = parent;
-                    loop
-                }
-                break
-            }
-            move_val_init(&mut self.data[pos], new);
-        }
-    }
-
-    priv fn siftdown_range(&mut self, mut pos: uint, end: uint) {
-        unsafe {
-            let start = pos;
-            let new = replace(&mut self.data[pos], init());
-
-            let mut child = 2 * pos + 1;
-            while child < end {
-                let right = child + 1;
-                if right < end && !(self.data[child] > self.data[right]) {
-                    child = right;
-                }
-                let x = replace(&mut self.data[child], init());
-                move_val_init(&mut self.data[pos], x);
-                pos = child;
-                child = 2 * pos + 1;
-            }
-
-            move_val_init(&mut self.data[pos], new);
-            self.siftup(start, pos);
-        }
-    }
-
-    priv fn siftdown(&mut self, pos: uint) {
-        let len = self.len();
-        self.siftdown_range(pos, len);
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use sort::merge_sort;
-    use core::cmp::le;
-    use priority_queue::PriorityQueue::{from_vec, new};
-
-    #[test]
-    fn test_top_and_pop() {
-        let data = ~[2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
-        let mut sorted = merge_sort(data, le);
-        let mut heap = from_vec(data);
-        while !heap.is_empty() {
-            assert_eq!(heap.top(), sorted.last());
-            assert_eq!(heap.pop(), sorted.pop());
-        }
-    }
-
-    #[test]
-    fn test_push() {
-        let mut heap = from_vec(~[2, 4, 9]);
-        assert_eq!(heap.len(), 3);
-        assert!(*heap.top() == 9);
-        heap.push(11);
-        assert_eq!(heap.len(), 4);
-        assert!(*heap.top() == 11);
-        heap.push(5);
-        assert_eq!(heap.len(), 5);
-        assert!(*heap.top() == 11);
-        heap.push(27);
-        assert_eq!(heap.len(), 6);
-        assert!(*heap.top() == 27);
-        heap.push(3);
-        assert_eq!(heap.len(), 7);
-        assert!(*heap.top() == 27);
-        heap.push(103);
-        assert_eq!(heap.len(), 8);
-        assert!(*heap.top() == 103);
-    }
-
-    #[test]
-    fn test_push_unique() {
-        let mut heap = from_vec(~[~2, ~4, ~9]);
-        assert_eq!(heap.len(), 3);
-        assert!(*heap.top() == ~9);
-        heap.push(~11);
-        assert_eq!(heap.len(), 4);
-        assert!(*heap.top() == ~11);
-        heap.push(~5);
-        assert_eq!(heap.len(), 5);
-        assert!(*heap.top() == ~11);
-        heap.push(~27);
-        assert_eq!(heap.len(), 6);
-        assert!(*heap.top() == ~27);
-        heap.push(~3);
-        assert_eq!(heap.len(), 7);
-        assert!(*heap.top() == ~27);
-        heap.push(~103);
-        assert_eq!(heap.len(), 8);
-        assert!(*heap.top() == ~103);
-    }
-
-    #[test]
-    fn test_push_pop() {
-        let mut heap = from_vec(~[5, 5, 2, 1, 3]);
-        assert_eq!(heap.len(), 5);
-        assert_eq!(heap.push_pop(6), 6);
-        assert_eq!(heap.len(), 5);
-        assert_eq!(heap.push_pop(0), 5);
-        assert_eq!(heap.len(), 5);
-        assert_eq!(heap.push_pop(4), 5);
-        assert_eq!(heap.len(), 5);
-        assert_eq!(heap.push_pop(1), 4);
-        assert_eq!(heap.len(), 5);
-    }
-
-    #[test]
-    fn test_replace() {
-        let mut heap = from_vec(~[5, 5, 2, 1, 3]);
-        assert_eq!(heap.len(), 5);
-        assert_eq!(heap.replace(6), 5);
-        assert_eq!(heap.len(), 5);
-        assert_eq!(heap.replace(0), 6);
-        assert_eq!(heap.len(), 5);
-        assert_eq!(heap.replace(4), 5);
-        assert_eq!(heap.len(), 5);
-        assert_eq!(heap.replace(1), 4);
-        assert_eq!(heap.len(), 5);
-    }
-
-    fn check_to_vec(data: ~[int]) {
-        let heap = from_vec(copy data);
-        assert_eq!(merge_sort((copy heap).to_vec(), le), merge_sort(data, le));
-        assert_eq!(heap.to_sorted_vec(), merge_sort(data, le));
-    }
-
-    #[test]
-    fn test_to_vec() {
-        check_to_vec(~[]);
-        check_to_vec(~[5]);
-        check_to_vec(~[3, 2]);
-        check_to_vec(~[2, 3]);
-        check_to_vec(~[5, 1, 2]);
-        check_to_vec(~[1, 100, 2, 3]);
-        check_to_vec(~[1, 3, 5, 7, 9, 2, 4, 6, 8, 0]);
-        check_to_vec(~[2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
-        check_to_vec(~[9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]);
-        check_to_vec(~[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
-        check_to_vec(~[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]);
-        check_to_vec(~[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]);
-        check_to_vec(~[5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]);
-    }
-
-    #[test]
-    #[should_fail]
-    #[ignore(cfg(windows))]
-    fn test_empty_pop() { let mut heap = new::<int>(); heap.pop(); }
-
-    #[test]
-    fn test_empty_maybe_pop() {
-        let mut heap = new::<int>();
-        assert!(heap.maybe_pop().is_none());
-    }
-
-    #[test]
-    #[should_fail]
-    #[ignore(cfg(windows))]
-    fn test_empty_top() { let empty = new::<int>(); empty.top(); }
-
-    #[test]
-    fn test_empty_maybe_top() {
-        let empty = new::<int>();
-        assert!(empty.maybe_top().is_none());
-    }
-
-    #[test]
-    #[should_fail]
-    #[ignore(cfg(windows))]
-    fn test_empty_replace() { let mut heap = new(); heap.replace(5); }
-}
diff --git a/src/libstd/ptr.rs b/src/libstd/ptr.rs
new file mode 100644
index 00000000000..f6cc00ccc86
--- /dev/null
+++ b/src/libstd/ptr.rs
@@ -0,0 +1,561 @@
+// 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.
+
+//! Unsafe pointer utility functions
+
+use cast;
+use libc;
+use libc::{c_void, size_t};
+use option::{Option, Some, None};
+use sys;
+
+#[cfg(not(test))] use cmp::{Eq, Ord};
+use uint;
+
+pub mod libc_ {
+    use libc::c_void;
+    use libc;
+
+    #[nolink]
+    #[abi = "cdecl"]
+    pub extern {
+        #[rust_stack]
+        unsafe fn memmove(dest: *mut c_void,
+                          src: *const c_void,
+                          n: libc::size_t)
+                       -> *c_void;
+
+        #[rust_stack]
+        unsafe fn memset(dest: *mut c_void,
+                         c: libc::c_int,
+                         len: libc::size_t)
+                      -> *c_void;
+    }
+}
+
+/// Calculate the offset from a pointer
+#[inline(always)]
+pub fn offset<T>(ptr: *T, count: uint) -> *T {
+    (ptr as uint + count * sys::size_of::<T>()) as *T
+}
+
+/// Calculate the offset from a const pointer
+#[inline(always)]
+pub fn const_offset<T>(ptr: *const T, count: uint) -> *const T {
+    (ptr as uint + count * sys::size_of::<T>()) as *T
+}
+
+/// Calculate the offset from a mut pointer
+#[inline(always)]
+pub fn mut_offset<T>(ptr: *mut T, count: uint) -> *mut T {
+    (ptr as uint + count * sys::size_of::<T>()) as *mut T
+}
+
+/// Return the offset of the first null pointer in `buf`.
+#[inline(always)]
+pub unsafe fn buf_len<T>(buf: **T) -> uint {
+    position(buf, |i| *i == null())
+}
+
+/// Return the first offset `i` such that `f(buf[i]) == true`.
+#[inline(always)]
+pub unsafe fn position<T>(buf: *T, f: &fn(&T) -> bool) -> uint {
+    let mut i = 0;
+    loop {
+        if f(&(*offset(buf, i))) { return i; }
+        else { i += 1; }
+    }
+}
+
+/// Create an unsafe null pointer
+#[inline(always)]
+pub fn null<T>() -> *T { unsafe { cast::transmute(0u) } }
+
+/// Create an unsafe mutable null pointer
+#[inline(always)]
+pub fn mut_null<T>() -> *mut T { unsafe { cast::transmute(0u) } }
+
+/// Returns true if the pointer is equal to the null pointer.
+#[inline(always)]
+pub fn is_null<T>(ptr: *const T) -> bool { ptr == null() }
+
+/// Returns true if the pointer is not equal to the null pointer.
+#[inline(always)]
+pub fn is_not_null<T>(ptr: *const T) -> bool { !is_null(ptr) }
+
+/**
+ * Copies data from one location to another
+ *
+ * Copies `count` elements (not bytes) from `src` to `dst`. The source
+ * and destination may overlap.
+ */
+#[inline(always)]
+#[cfg(target_word_size = "32")]
+pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
+    use unstable::intrinsics::memmove32;
+    let n = count * sys::size_of::<T>();
+    memmove32(dst as *mut u8, src as *u8, n as u32);
+}
+#[inline(always)]
+#[cfg(target_word_size = "64")]
+pub unsafe fn copy_memory<T>(dst: *mut T, src: *const T, count: uint) {
+    use unstable::intrinsics::memmove64;
+    let n = count * sys::size_of::<T>();
+    memmove64(dst as *mut u8, src as *u8, n as u64);
+}
+
+#[inline(always)]
+pub unsafe fn set_memory<T>(dst: *mut T, c: int, count: uint) {
+    let n = count * sys::size_of::<T>();
+    libc_::memset(dst as *mut c_void, c as libc::c_int, n as size_t);
+}
+
+/**
+  Transform a region pointer - &T - to an unsafe pointer - *T.
+  This is safe, but is implemented with an unsafe block due to
+  transmute.
+*/
+#[inline(always)]
+pub fn to_unsafe_ptr<T>(thing: &T) -> *T {
+    unsafe { cast::transmute(thing) }
+}
+
+/**
+  Transform a const region pointer - &const T - to a const unsafe pointer -
+  *const T. This is safe, but is implemented with an unsafe block due to
+  transmute.
+*/
+#[inline(always)]
+pub fn to_const_unsafe_ptr<T>(thing: &const T) -> *const T {
+    unsafe { cast::transmute(thing) }
+}
+
+/**
+  Transform a mutable region pointer - &mut T - to a mutable unsafe pointer -
+  *mut T. This is safe, but is implemented with an unsafe block due to
+  transmute.
+*/
+#[inline(always)]
+pub fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T {
+    unsafe { cast::transmute(thing) }
+}
+
+/**
+  Cast a region pointer - &T - to a uint.
+  This is safe, but is implemented with an unsafe block due to
+  transmute.
+
+  (I couldn't think of a cutesy name for this one.)
+*/
+#[inline(always)]
+pub fn to_uint<T>(thing: &T) -> uint {
+    unsafe {
+        cast::transmute(thing)
+    }
+}
+
+/// Determine if two borrowed pointers point to the same thing.
+#[inline(always)]
+pub fn ref_eq<'a,'b,T>(thing: &'a T, other: &'b T) -> bool {
+    to_uint(thing) == to_uint(other)
+}
+
+/**
+  Given a **T (pointer to an array of pointers),
+  iterate through each *T, up to the provided `len`,
+  passing to the provided callback function
+
+  SAFETY NOTE: Pointer-arithmetic. Dragons be here.
+*/
+pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: &fn(*T)) {
+    debug!("array_each_with_len: before iterate");
+    if (arr as uint == 0) {
+        fail!("ptr::array_each_with_len failure: arr input is null pointer");
+    }
+    //let start_ptr = *arr;
+    uint::iterate(0, len, |e| {
+        let n = offset(arr, e);
+        cb(*n);
+        true
+    });
+    debug!("array_each_with_len: after iterate");
+}
+
+/**
+  Given a null-pointer-terminated **T (pointer to
+  an array of pointers), iterate through each *T,
+  passing to the provided callback function
+
+  SAFETY NOTE: This will only work with a null-terminated
+  pointer array. Barely less-dodgey Pointer Arithmetic.
+  Dragons be here.
+*/
+pub unsafe fn array_each<T>(arr: **T, cb: &fn(*T)) {
+    if (arr as uint == 0) {
+        fail!("ptr::array_each_with_len failure: arr input is null pointer");
+    }
+    let len = buf_len(arr);
+    debug!("array_each inferred len: %u",
+                    len);
+    array_each_with_len(arr, len, cb);
+}
+
+pub trait Ptr<T> {
+    fn is_null(&const self) -> bool;
+    fn is_not_null(&const self) -> bool;
+    unsafe fn to_option(&const self) -> Option<&T>;
+    fn offset(&self, count: uint) -> Self;
+}
+
+/// Extension methods for immutable pointers
+impl<T> Ptr<T> for *T {
+    /// Returns true if the pointer is equal to the null pointer.
+    #[inline(always)]
+    fn is_null(&const self) -> bool { is_null(*self) }
+
+    /// Returns true if the pointer is not equal to the null pointer.
+    #[inline(always)]
+    fn is_not_null(&const self) -> bool { is_not_null(*self) }
+
+    ///
+    /// Returns `None` if the pointer is null, or else returns the value wrapped
+    /// in `Some`.
+    ///
+    /// # Safety Notes
+    ///
+    /// While this method is useful for null-safety, it is important to note
+    /// that this is still an unsafe operation because the returned value could
+    /// be pointing to invalid memory.
+    ///
+    #[inline(always)]
+    unsafe fn to_option(&const self) -> Option<&T> {
+        if self.is_null() { None } else {
+            Some(cast::transmute(*self))
+        }
+    }
+
+    /// Calculates the offset from a pointer.
+    #[inline(always)]
+    fn offset(&self, count: uint) -> *T { offset(*self, count) }
+}
+
+/// Extension methods for mutable pointers
+impl<T> Ptr<T> for *mut T {
+    /// Returns true if the pointer is equal to the null pointer.
+    #[inline(always)]
+    fn is_null(&const self) -> bool { is_null(*self) }
+
+    /// Returns true if the pointer is not equal to the null pointer.
+    #[inline(always)]
+    fn is_not_null(&const self) -> bool { is_not_null(*self) }
+
+    ///
+    /// Returns `None` if the pointer is null, or else returns the value wrapped
+    /// in `Some`.
+    ///
+    /// # Safety Notes
+    ///
+    /// While this method is useful for null-safety, it is important to note
+    /// that this is still an unsafe operation because the returned value could
+    /// be pointing to invalid memory.
+    ///
+    #[inline(always)]
+    unsafe fn to_option(&const self) -> Option<&T> {
+        if self.is_null() { None } else {
+            Some(cast::transmute(*self))
+        }
+    }
+
+    /// Calculates the offset from a mutable pointer.
+    #[inline(always)]
+    fn offset(&self, count: uint) -> *mut T { mut_offset(*self, count) }
+}
+
+// Equality for pointers
+#[cfg(not(test))]
+impl<T> Eq for *const T {
+    #[inline(always)]
+    fn eq(&self, other: &*const T) -> bool {
+        unsafe {
+            let a: uint = cast::transmute(*self);
+            let b: uint = cast::transmute(*other);
+            return a == b;
+        }
+    }
+    #[inline(always)]
+    fn ne(&self, other: &*const T) -> bool { !(*self).eq(other) }
+}
+
+// Comparison for pointers
+#[cfg(not(test))]
+impl<T> Ord for *const T {
+    #[inline(always)]
+    fn lt(&self, other: &*const T) -> bool {
+        unsafe {
+            let a: uint = cast::transmute(*self);
+            let b: uint = cast::transmute(*other);
+            return a < b;
+        }
+    }
+    #[inline(always)]
+    fn le(&self, other: &*const T) -> bool {
+        unsafe {
+            let a: uint = cast::transmute(*self);
+            let b: uint = cast::transmute(*other);
+            return a <= b;
+        }
+    }
+    #[inline(always)]
+    fn ge(&self, other: &*const T) -> bool {
+        unsafe {
+            let a: uint = cast::transmute(*self);
+            let b: uint = cast::transmute(*other);
+            return a >= b;
+        }
+    }
+    #[inline(always)]
+    fn gt(&self, other: &*const T) -> bool {
+        unsafe {
+            let a: uint = cast::transmute(*self);
+            let b: uint = cast::transmute(*other);
+            return a > b;
+        }
+    }
+}
+
+// Equality for region pointers
+#[cfg(not(test))]
+impl<'self,T:Eq> Eq for &'self T {
+    #[inline(always)]
+    fn eq(&self, other: & &'self T) -> bool {
+        return *(*self) == *(*other);
+    }
+    #[inline(always)]
+    fn ne(&self, other: & &'self T) -> bool {
+        return *(*self) != *(*other);
+    }
+}
+
+// Comparison for region pointers
+#[cfg(not(test))]
+impl<'self,T:Ord> Ord for &'self T {
+    #[inline(always)]
+    fn lt(&self, other: & &'self T) -> bool {
+        *(*self) < *(*other)
+    }
+    #[inline(always)]
+    fn le(&self, other: & &'self T) -> bool {
+        *(*self) <= *(*other)
+    }
+    #[inline(always)]
+    fn ge(&self, other: & &'self T) -> bool {
+        *(*self) >= *(*other)
+    }
+    #[inline(always)]
+    fn gt(&self, other: & &'self T) -> bool {
+        *(*self) > *(*other)
+    }
+}
+
+#[cfg(test)]
+pub mod ptr_tests {
+    use super::*;
+    use prelude::*;
+
+    #[test]
+    fn test() {
+        unsafe {
+            struct Pair {
+                fst: int,
+                snd: int
+            };
+            let mut p = Pair {fst: 10, snd: 20};
+            let pptr: *mut Pair = &mut p;
+            let iptr: *mut int = cast::transmute(pptr);
+            assert_eq!(*iptr, 10);
+            *iptr = 30;
+            assert_eq!(*iptr, 30);
+            assert_eq!(p.fst, 30);
+
+            *pptr = Pair {fst: 50, snd: 60};
+            assert_eq!(*iptr, 50);
+            assert_eq!(p.fst, 50);
+            assert_eq!(p.snd, 60);
+
+            let v0 = ~[32000u16, 32001u16, 32002u16];
+            let mut v1 = ~[0u16, 0u16, 0u16];
+
+            copy_memory(mut_offset(vec::raw::to_mut_ptr(v1), 1u),
+                        offset(vec::raw::to_ptr(v0), 1u), 1u);
+            assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16));
+            copy_memory(vec::raw::to_mut_ptr(v1),
+                        offset(vec::raw::to_ptr(v0), 2u), 1u);
+            assert!((v1[0] == 32002u16 && v1[1] == 32001u16 &&
+                     v1[2] == 0u16));
+            copy_memory(mut_offset(vec::raw::to_mut_ptr(v1), 2u),
+                        vec::raw::to_ptr(v0), 1u);
+            assert!((v1[0] == 32002u16 && v1[1] == 32001u16 &&
+                     v1[2] == 32000u16));
+        }
+    }
+
+    #[test]
+    fn test_position() {
+        use str::as_c_str;
+        use libc::c_char;
+
+        let s = ~"hello";
+        unsafe {
+            assert!(2u == as_c_str(s, |p| position(p,
+                                                   |c| *c == 'l' as c_char)));
+            assert!(4u == as_c_str(s, |p| position(p,
+                                                   |c| *c == 'o' as c_char)));
+            assert!(5u == as_c_str(s, |p| position(p,
+                                                   |c| *c == 0 as c_char)));
+        }
+    }
+
+    #[test]
+    fn test_buf_len() {
+        let s0 = ~"hello";
+        let s1 = ~"there";
+        let s2 = ~"thing";
+        do str::as_c_str(s0) |p0| {
+            do str::as_c_str(s1) |p1| {
+                do str::as_c_str(s2) |p2| {
+                    let v = ~[p0, p1, p2, null()];
+                    do vec::as_imm_buf(v) |vp, len| {
+                        assert_eq!(unsafe { buf_len(vp) }, 3u);
+                        assert_eq!(len, 4u);
+                    }
+                }
+            }
+        }
+    }
+
+    #[test]
+    fn test_is_null() {
+        let p: *int = null();
+        assert!(p.is_null());
+        assert!(!p.is_not_null());
+
+        let q = offset(p, 1u);
+        assert!(!q.is_null());
+        assert!(q.is_not_null());
+
+        let mp: *mut int = mut_null();
+        assert!(mp.is_null());
+        assert!(!mp.is_not_null());
+
+        let mq = mp.offset(1u);
+        assert!(!mq.is_null());
+        assert!(mq.is_not_null());
+    }
+
+    #[test]
+    fn test_to_option() {
+        let p: *int = null();
+        // FIXME (#6641): Usage of unsafe methods in safe code doesn't cause an error.
+        assert_eq!(p.to_option(), None);
+
+        let q: *int = &2;
+        assert_eq!(q.to_option().unwrap(), &2);     // FIXME (#6641)
+
+        let p: *mut int = mut_null();
+        assert_eq!(p.to_option(), None);            // FIXME (#6641)
+
+        let q: *mut int = &mut 2;
+        assert_eq!(q.to_option().unwrap(), &2);     // FIXME (#6641)
+    }
+
+    #[test]
+    fn test_ptr_array_each_with_len() {
+        unsafe {
+            let one = ~"oneOne";
+            let two = ~"twoTwo";
+            let three = ~"threeThree";
+            let arr: ~[*i8] = ~[
+                ::cast::transmute(&one[0]),
+                ::cast::transmute(&two[0]),
+                ::cast::transmute(&three[0]),
+            ];
+            let expected_arr = [
+                one, two, three
+            ];
+            let arr_ptr = &arr[0];
+            let mut ctr = 0;
+            let mut iteration_count = 0;
+            array_each_with_len(arr_ptr, arr.len(),
+                                |e| {
+                                         let actual = str::raw::from_c_str(e);
+                                         let expected = copy expected_arr[ctr];
+                                         debug!(
+                                             "test_ptr_array_each e: %s, a: %s",
+                                             expected, actual);
+                                         assert_eq!(actual, expected);
+                                         ctr += 1;
+                                         iteration_count += 1;
+                                     });
+            assert_eq!(iteration_count, 3u);
+        }
+    }
+    #[test]
+    fn test_ptr_array_each() {
+        unsafe {
+            let one = ~"oneOne";
+            let two = ~"twoTwo";
+            let three = ~"threeThree";
+            let arr: ~[*i8] = ~[
+                ::cast::transmute(&one[0]),
+                ::cast::transmute(&two[0]),
+                ::cast::transmute(&three[0]),
+                // fake a null terminator
+                0 as *i8
+            ];
+            let expected_arr = [
+                one, two, three
+            ];
+            let arr_ptr = &arr[0];
+            let mut ctr = 0;
+            let mut iteration_count = 0;
+            array_each(arr_ptr, |e| {
+                let actual = str::raw::from_c_str(e);
+                let expected = copy expected_arr[ctr];
+                debug!(
+                    "test_ptr_array_each e: %s, a: %s",
+                    expected, actual);
+                assert_eq!(actual, expected);
+                ctr += 1;
+                iteration_count += 1;
+            });
+            assert_eq!(iteration_count, 3);
+        }
+    }
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_ptr_array_each_with_len_null_ptr() {
+        unsafe {
+            array_each_with_len(0 as **libc::c_char, 1, |e| {
+                str::raw::from_c_str(e);
+            });
+        }
+    }
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_ptr_array_each_null_ptr() {
+        unsafe {
+            array_each(0 as **libc::c_char, |e| {
+                str::raw::from_c_str(e);
+            });
+        }
+    }
+}
diff --git a/src/libstd/rand.rs b/src/libstd/rand.rs
new file mode 100644
index 00000000000..84dd7d187e4
--- /dev/null
+++ b/src/libstd/rand.rs
@@ -0,0 +1,1092 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+Random number generation.
+
+The key functions are `random()` and `RngUtil::gen()`. These are polymorphic
+and so can be used to generate any type that implements `Rand`. Type inference
+means that often a simple call to `rand::random()` or `rng.gen()` will
+suffice, but sometimes an annotation is required, e.g. `rand::random::<float>()`.
+
+See the `distributions` submodule for sampling random numbers from
+distributions like normal and exponential.
+
+# Examples
+~~~
+use core::rand::RngUtil;
+
+fn main() {
+    let rng = rand::rng();
+    if rng.gen() { // bool
+        println(fmt!("int: %d, uint: %u", rng.gen(), rng.gen()))
+    }
+}
+~~~
+
+~~~
+fn main () {
+    let tuple_ptr = rand::random::<~(f64, char)>();
+    println(fmt!("%?", tuple_ptr))
+}
+~~~
+*/
+
+
+use int;
+use prelude::*;
+use str;
+use u32;
+use uint;
+use util;
+use vec;
+use libc::size_t;
+
+#[path="rand/distributions.rs"]
+pub mod distributions;
+
+/// A type that can be randomly generated using an Rng
+pub trait Rand {
+    fn rand<R: Rng>(rng: &mut R) -> Self;
+}
+
+impl Rand for int {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> int {
+        if int::bits == 32 {
+            rng.next() as int
+        } else {
+            rng.gen::<i64>() as int
+        }
+    }
+}
+
+impl Rand for i8 {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> i8 {
+        rng.next() as i8
+    }
+}
+
+impl Rand for i16 {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> i16 {
+        rng.next() as i16
+    }
+}
+
+impl Rand for i32 {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> i32 {
+        rng.next() as i32
+    }
+}
+
+impl Rand for i64 {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> i64 {
+        (rng.next() as i64 << 32) | rng.next() as i64
+    }
+}
+
+impl Rand for uint {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> uint {
+        if uint::bits == 32 {
+            rng.next() as uint
+        } else {
+            rng.gen::<u64>() as uint
+        }
+    }
+}
+
+impl Rand for u8 {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> u8 {
+        rng.next() as u8
+    }
+}
+
+impl Rand for u16 {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> u16 {
+        rng.next() as u16
+    }
+}
+
+impl Rand for u32 {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> u32 {
+        rng.next()
+    }
+}
+
+impl Rand for u64 {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> u64 {
+        (rng.next() as u64 << 32) | rng.next() as u64
+    }
+}
+
+impl Rand for float {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> float {
+        rng.gen::<f64>() as float
+    }
+}
+
+impl Rand for f32 {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> f32 {
+        rng.gen::<f64>() as f32
+    }
+}
+
+static scale : f64 = (u32::max_value as f64) + 1.0f64;
+impl Rand for f64 {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> f64 {
+        let u1 = rng.next() as f64;
+        let u2 = rng.next() as f64;
+        let u3 = rng.next() as f64;
+
+        ((u1 / scale + u2) / scale + u3) / scale
+    }
+}
+
+impl Rand for char {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> char {
+        rng.next() as char
+    }
+}
+
+impl Rand for bool {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> bool {
+        rng.next() & 1u32 == 1u32
+    }
+}
+
+macro_rules! tuple_impl {
+    // use variables to indicate the arity of the tuple
+    ($($tyvar:ident),* ) => {
+        // the trailing commas are for the 1 tuple
+        impl<
+            $( $tyvar : Rand ),*
+            > Rand for ( $( $tyvar ),* , ) {
+
+            #[inline]
+            fn rand<R: Rng>(_rng: &mut R) -> ( $( $tyvar ),* , ) {
+                (
+                    // use the $tyvar's to get the appropriate number of
+                    // repeats (they're not actually needed)
+                    $(
+                        _rng.gen::<$tyvar>()
+                    ),*
+                    ,
+                )
+            }
+        }
+    }
+}
+
+impl Rand for () {
+    #[inline]
+    fn rand<R: Rng>(_: &mut R) -> () { () }
+}
+tuple_impl!{A}
+tuple_impl!{A, B}
+tuple_impl!{A, B, C}
+tuple_impl!{A, B, C, D}
+tuple_impl!{A, B, C, D, E}
+tuple_impl!{A, B, C, D, E, F}
+tuple_impl!{A, B, C, D, E, F, G}
+tuple_impl!{A, B, C, D, E, F, G, H}
+tuple_impl!{A, B, C, D, E, F, G, H, I}
+tuple_impl!{A, B, C, D, E, F, G, H, I, J}
+
+impl<T:Rand> Rand for Option<T> {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> Option<T> {
+        if rng.gen() {
+            Some(rng.gen())
+        } else {
+            None
+        }
+    }
+}
+
+impl<T: Rand> Rand for ~T {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> ~T { ~rng.gen() }
+}
+
+impl<T: Rand> Rand for @T {
+    #[inline]
+    fn rand<R: Rng>(rng: &mut R) -> @T { @rng.gen() }
+}
+
+#[abi = "cdecl"]
+pub mod rustrt {
+    use libc::size_t;
+
+    pub extern {
+        unsafe fn rand_seed_size() -> size_t;
+        unsafe fn rand_gen_seed(buf: *mut u8, sz: size_t);
+    }
+}
+
+/// A random number generator
+pub trait Rng {
+    /// Return the next random integer
+    pub fn next(&mut self) -> u32;
+}
+
+/// A value with a particular weight compared to other values
+pub struct Weighted<T> {
+    weight: uint,
+    item: T,
+}
+
+pub trait RngUtil {
+    /// Return a random value of a Rand type
+    fn gen<T:Rand>(&mut self) -> T;
+    /**
+     * Return a int randomly chosen from the range [start, end),
+     * failing if start >= end
+     */
+    fn gen_int_range(&mut self, start: int, end: int) -> int;
+    /**
+     * Return a uint randomly chosen from the range [start, end),
+     * failing if start >= end
+     */
+    fn gen_uint_range(&mut self, start: uint, end: uint) -> uint;
+    /**
+     * Return a char randomly chosen from chars, failing if chars is empty
+     */
+    fn gen_char_from(&mut self, chars: &str) -> char;
+    /**
+     * Return a bool with a 1 in n chance of true
+     *
+     * *Example*
+     *
+     * ~~~
+     *
+     * use core::rand::RngUtil;
+     *
+     * fn main() {
+     *     rng = rand::rng();
+     *     println(fmt!("%b",rng.gen_weighted_bool(3)));
+     * }
+     * ~~~
+     */
+    fn gen_weighted_bool(&mut self, n: uint) -> bool;
+    /**
+     * Return a random string of the specified length composed of A-Z,a-z,0-9
+     *
+     * *Example*
+     *
+     * ~~~
+     *
+     * use core::rand::RngUtil;
+     *
+     * fn main() {
+     *     rng = rand::rng();
+     *     println(rng.gen_str(8));
+     * }
+     * ~~~
+     */
+    fn gen_str(&mut self, len: uint) -> ~str;
+    /**
+     * Return a random byte string of the specified length
+     *
+     * *Example*
+     *
+     * ~~~
+     *
+     * use core::rand::RngUtil;
+     *
+     * fn main() {
+     *     rng = rand::rng();
+     *     println(fmt!("%?",rng.gen_bytes(8)));
+     * }
+     * ~~~
+     */
+    fn gen_bytes(&mut self, len: uint) -> ~[u8];
+    /**
+     * Choose an item randomly, failing if values is empty
+     *
+     * *Example*
+     *
+     * ~~~
+     *
+     * use core::rand::RngUtil;
+     *
+     * fn main() {
+     *     rng = rand::rng();
+     *     println(fmt!("%d",rng.choose([1,2,4,8,16,32])));
+     * }
+     * ~~~
+     */
+    fn choose<T:Copy>(&mut self, values: &[T]) -> T;
+    /// Choose Some(item) randomly, returning None if values is empty
+    fn choose_option<T:Copy>(&mut self, values: &[T]) -> Option<T>;
+    /**
+     * Choose an item respecting the relative weights, failing if the sum of
+     * the weights is 0
+     *
+     * *Example*
+     *
+     * ~~~
+     *
+     * use core::rand::RngUtil;
+     *
+     * fn main() {
+     *     rng = rand::rng();
+     *     let x = [rand::Weighted {weight: 4, item: 'a'},
+     *              rand::Weighted {weight: 2, item: 'b'},
+     *              rand::Weighted {weight: 2, item: 'c'}];
+     *     println(fmt!("%c",rng.choose_weighted(x)));
+     * }
+     * ~~~
+     */
+    fn choose_weighted<T:Copy>(&mut self, v : &[Weighted<T>]) -> T;
+    /**
+     * Choose Some(item) respecting the relative weights, returning none if
+     * the sum of the weights is 0
+     *
+     * *Example*
+     *
+     * ~~~
+     *
+     * use core::rand::RngUtil;
+     *
+     * fn main() {
+     *     rng = rand::rng();
+     *     let x = [rand::Weighted {weight: 4, item: 'a'},
+     *              rand::Weighted {weight: 2, item: 'b'},
+     *              rand::Weighted {weight: 2, item: 'c'}];
+     *     println(fmt!("%?",rng.choose_weighted_option(x)));
+     * }
+     * ~~~
+     */
+    fn choose_weighted_option<T:Copy>(&mut self, v: &[Weighted<T>])
+                                     -> Option<T>;
+    /**
+     * Return a vec containing copies of the items, in order, where
+     * the weight of the item determines how many copies there are
+     *
+     * *Example*
+     *
+     * ~~~
+     *
+     * use core::rand::RngUtil;
+     *
+     * fn main() {
+     *     rng = rand::rng();
+     *     let x = [rand::Weighted {weight: 4, item: 'a'},
+     *              rand::Weighted {weight: 2, item: 'b'},
+     *              rand::Weighted {weight: 2, item: 'c'}];
+     *     println(fmt!("%?",rng.weighted_vec(x)));
+     * }
+     * ~~~
+     */
+    fn weighted_vec<T:Copy>(&mut self, v: &[Weighted<T>]) -> ~[T];
+    /**
+     * Shuffle a vec
+     *
+     * *Example*
+     *
+     * ~~~
+     *
+     * use core::rand::RngUtil;
+     *
+     * fn main() {
+     *     rng = rand::rng();
+     *     println(fmt!("%?",rng.shuffle([1,2,3])));
+     * }
+     * ~~~
+     */
+    fn shuffle<T:Copy>(&mut self, values: &[T]) -> ~[T];
+    /**
+     * Shuffle a mutable vec in place
+     *
+     * *Example*
+     *
+     * ~~~
+     *
+     * use core::rand::RngUtil;
+     *
+     * fn main() {
+     *     rng = rand::rng();
+     *     let mut y = [1,2,3];
+     *     rng.shuffle_mut(y);
+     *     println(fmt!("%?",y));
+     *     rng.shuffle_mut(y);
+     *     println(fmt!("%?",y));
+     * }
+     * ~~~
+     */
+    fn shuffle_mut<T>(&mut self, values: &mut [T]);
+}
+
+/// Extension methods for random number generators
+impl<R: Rng> RngUtil for R {
+    /// Return a random value for a Rand type
+    #[inline(always)]
+    fn gen<T: Rand>(&mut self) -> T {
+        Rand::rand(self)
+    }
+
+    /**
+     * Return an int randomly chosen from the range [start, end),
+     * failing if start >= end
+     */
+    fn gen_int_range(&mut self, start: int, end: int) -> int {
+        assert!(start < end);
+        start + int::abs(self.gen::<int>() % (end - start))
+    }
+
+    /**
+     * Return a uint randomly chosen from the range [start, end),
+     * failing if start >= end
+     */
+    fn gen_uint_range(&mut self, start: uint, end: uint) -> uint {
+        assert!(start < end);
+        start + (self.gen::<uint>() % (end - start))
+    }
+
+    /**
+     * Return a char randomly chosen from chars, failing if chars is empty
+     */
+    fn gen_char_from(&mut self, chars: &str) -> char {
+        assert!(!chars.is_empty());
+        let mut cs = ~[];
+        for str::each_char(chars) |c| { cs.push(c) }
+        self.choose(cs)
+    }
+
+    /// Return a bool with a 1-in-n chance of true
+    fn gen_weighted_bool(&mut self, n: uint) -> bool {
+        if n == 0u {
+            true
+        } else {
+            self.gen_uint_range(1u, n + 1u) == 1u
+        }
+    }
+
+    /**
+     * Return a random string of the specified length composed of A-Z,a-z,0-9
+     */
+    fn gen_str(&mut self, len: uint) -> ~str {
+        let charset = ~"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
+                       abcdefghijklmnopqrstuvwxyz\
+                       0123456789";
+        let mut s = ~"";
+        let mut i = 0u;
+        while (i < len) {
+            s = s + str::from_char(self.gen_char_from(charset));
+            i += 1u;
+        }
+        s
+    }
+
+    /// Return a random byte string of the specified length
+    fn gen_bytes(&mut self, len: uint) -> ~[u8] {
+        do vec::from_fn(len) |_i| {
+            self.gen()
+        }
+    }
+
+    /// Choose an item randomly, failing if values is empty
+    fn choose<T:Copy>(&mut self, values: &[T]) -> T {
+        self.choose_option(values).get()
+    }
+
+    /// Choose Some(item) randomly, returning None if values is empty
+    fn choose_option<T:Copy>(&mut self, values: &[T]) -> Option<T> {
+        if values.is_empty() {
+            None
+        } else {
+            Some(values[self.gen_uint_range(0u, values.len())])
+        }
+    }
+    /**
+     * Choose an item respecting the relative weights, failing if the sum of
+     * the weights is 0
+     */
+    fn choose_weighted<T:Copy>(&mut self, v: &[Weighted<T>]) -> T {
+        self.choose_weighted_option(v).get()
+    }
+
+    /**
+     * Choose Some(item) respecting the relative weights, returning none if
+     * the sum of the weights is 0
+     */
+    fn choose_weighted_option<T:Copy>(&mut self, v: &[Weighted<T>])
+                                     -> Option<T> {
+        let mut total = 0u;
+        for v.each |item| {
+            total += item.weight;
+        }
+        if total == 0u {
+            return None;
+        }
+        let chosen = self.gen_uint_range(0u, total);
+        let mut so_far = 0u;
+        for v.each |item| {
+            so_far += item.weight;
+            if so_far > chosen {
+                return Some(item.item);
+            }
+        }
+        util::unreachable();
+    }
+
+    /**
+     * Return a vec containing copies of the items, in order, where
+     * the weight of the item determines how many copies there are
+     */
+    fn weighted_vec<T:Copy>(&mut self, v: &[Weighted<T>]) -> ~[T] {
+        let mut r = ~[];
+        for v.each |item| {
+            for uint::range(0u, item.weight) |_i| {
+                r.push(item.item);
+            }
+        }
+        r
+    }
+
+    /// Shuffle a vec
+    fn shuffle<T:Copy>(&mut self, values: &[T]) -> ~[T] {
+        let mut m = vec::to_owned(values);
+        self.shuffle_mut(m);
+        m
+    }
+
+    /// Shuffle a mutable vec in place
+    fn shuffle_mut<T>(&mut self, values: &mut [T]) {
+        let mut i = values.len();
+        while i >= 2u {
+            // invariant: elements with index >= i have been locked in place.
+            i -= 1u;
+            // lock element i in place.
+            vec::swap(values, i, self.gen_uint_range(0u, i + 1u));
+        }
+    }
+}
+
+/// Create a random number generator with a default algorithm and seed.
+pub fn rng() -> IsaacRng {
+    IsaacRng::new()
+}
+
+static RAND_SIZE_LEN: u32 = 8;
+static RAND_SIZE: u32 = 1 << RAND_SIZE_LEN;
+
+/// A random number generator that uses the [ISAAC
+/// algorithm](http://en.wikipedia.org/wiki/ISAAC_%28cipher%29).
+pub struct IsaacRng {
+    priv cnt: u32,
+    priv rsl: [u32, .. RAND_SIZE],
+    priv mem: [u32, .. RAND_SIZE],
+    priv a: u32,
+    priv b: u32,
+    priv c: u32
+}
+
+pub impl IsaacRng {
+    /// Create an ISAAC random number generator with a random seed.
+    fn new() -> IsaacRng {
+        IsaacRng::new_seeded(seed())
+    }
+
+    /// Create an ISAAC random number generator with a seed. This can be any
+    /// length, although the maximum number of bytes used is 1024 and any more
+    /// will be silently ignored. A generator constructed with a given seed
+    /// will generate the same sequence of values as all other generators
+    /// constructed with the same seed.
+    fn new_seeded(seed: &[u8]) -> IsaacRng {
+        let mut rng = IsaacRng {
+            cnt: 0,
+            rsl: [0, .. RAND_SIZE],
+            mem: [0, .. RAND_SIZE],
+            a: 0, b: 0, c: 0
+        };
+
+        let array_size = sys::size_of_val(&rng.rsl);
+        let copy_length = cmp::min(array_size, seed.len());
+
+        // manually create a &mut [u8] slice of randrsl to copy into.
+        let dest = unsafe { cast::transmute((&mut rng.rsl, array_size)) };
+        vec::bytes::copy_memory(dest, seed, copy_length);
+        rng.init(true);
+        rng
+    }
+
+    /// Create an ISAAC random number generator using the default
+    /// fixed seed.
+    fn new_unseeded() -> IsaacRng {
+        let mut rng = IsaacRng {
+            cnt: 0,
+            rsl: [0, .. RAND_SIZE],
+            mem: [0, .. RAND_SIZE],
+            a: 0, b: 0, c: 0
+        };
+        rng.init(false);
+        rng
+    }
+
+    /// Initialises `self`. If `use_rsl` is true, then use the current value
+    /// of `rsl` as a seed, otherwise construct one algorithmically (not
+    /// randomly).
+    priv fn init(&mut self, use_rsl: bool) {
+        macro_rules! init_mut_many (
+            ($( $var:ident ),* = $val:expr ) => {
+                let mut $( $var = $val ),*;
+            }
+        );
+        init_mut_many!(a, b, c, d, e, f, g, h = 0x9e3779b9);
+
+
+        macro_rules! mix(
+            () => {{
+                a^=b<<11; d+=a; b+=c;
+                b^=c>>2;  e+=b; c+=d;
+                c^=d<<8;  f+=c; d+=e;
+                d^=e>>16; g+=d; e+=f;
+                e^=f<<10; h+=e; f+=g;
+                f^=g>>4;  a+=f; g+=h;
+                g^=h<<8;  b+=g; h+=a;
+                h^=a>>9;  c+=h; a+=b;
+            }}
+        );
+
+        for 4.times { mix!(); }
+
+        if use_rsl {
+            macro_rules! memloop (
+                ($arr:expr) => {{
+                    for u32::range_step(0, RAND_SIZE, 8) |i| {
+                        a+=$arr[i  ]; b+=$arr[i+1];
+                        c+=$arr[i+2]; d+=$arr[i+3];
+                        e+=$arr[i+4]; f+=$arr[i+5];
+                        g+=$arr[i+6]; h+=$arr[i+7];
+                        mix!();
+                        self.mem[i  ]=a; self.mem[i+1]=b;
+                        self.mem[i+2]=c; self.mem[i+3]=d;
+                        self.mem[i+4]=e; self.mem[i+5]=f;
+                        self.mem[i+6]=g; self.mem[i+7]=h;
+                    }
+                }}
+            );
+
+            memloop!(self.rsl);
+            memloop!(self.mem);
+        } else {
+            for u32::range_step(0, RAND_SIZE, 8) |i| {
+                mix!();
+                self.mem[i  ]=a; self.mem[i+1]=b;
+                self.mem[i+2]=c; self.mem[i+3]=d;
+                self.mem[i+4]=e; self.mem[i+5]=f;
+                self.mem[i+6]=g; self.mem[i+7]=h;
+            }
+        }
+
+        self.isaac();
+    }
+
+    /// Refills the output buffer (`self.rsl`)
+    #[inline]
+    priv fn isaac(&mut self) {
+        self.c += 1;
+        // abbreviations
+        let mut a = self.a, b = self.b + self.c;
+
+        static midpoint: uint =  RAND_SIZE as uint / 2;
+
+        macro_rules! ind (($x:expr) => {
+            self.mem[($x >> 2) & (RAND_SIZE - 1)]
+        });
+        macro_rules! rngstep(
+            ($j:expr, $shift:expr) => {{
+                let base = base + $j;
+                let mix = if $shift < 0 {
+                    a >> -$shift as uint
+                } else {
+                    a << $shift as uint
+                };
+
+                let x = self.mem[base  + mr_offset];
+                a = (a ^ mix) + self.mem[base + m2_offset];
+                let y = ind!(x) + a + b;
+                self.mem[base + mr_offset] = y;
+
+                b = ind!(y >> RAND_SIZE_LEN) + x;
+                self.rsl[base + mr_offset] = b;
+            }}
+        );
+
+        for [(0, midpoint), (midpoint, 0)].each |&(mr_offset, m2_offset)| {
+            for uint::range_step(0, midpoint, 4) |base| {
+                rngstep!(0, 13);
+                rngstep!(1, -6);
+                rngstep!(2, 2);
+                rngstep!(3, -16);
+            }
+        }
+
+        self.a = a;
+        self.b = b;
+        self.cnt = RAND_SIZE;
+    }
+}
+
+impl Rng for IsaacRng {
+    #[inline(always)]
+    fn next(&mut self) -> u32 {
+        if self.cnt == 0 {
+            // make some more numbers
+            self.isaac();
+        }
+        self.cnt -= 1;
+        self.rsl[self.cnt]
+    }
+}
+
+/// An [Xorshift random number
+/// generator](http://en.wikipedia.org/wiki/Xorshift). Not suitable for
+/// cryptographic purposes.
+pub struct XorShiftRng {
+    priv x: u32,
+    priv y: u32,
+    priv z: u32,
+    priv w: u32,
+}
+
+impl Rng for XorShiftRng {
+    #[inline]
+    pub fn next(&mut self) -> u32 {
+        let x = self.x;
+        let t = x ^ (x << 11);
+        self.x = self.y;
+        self.y = self.z;
+        self.z = self.w;
+        let w = self.w;
+        self.w = w ^ (w >> 19) ^ (t ^ (t >> 8));
+        self.w
+    }
+}
+
+pub impl XorShiftRng {
+    /// Create an xor shift random number generator with a default seed.
+    fn new() -> XorShiftRng {
+        // constants taken from http://en.wikipedia.org/wiki/Xorshift
+        XorShiftRng::new_seeded(123456789u32,
+                                362436069u32,
+                                521288629u32,
+                                88675123u32)
+    }
+
+    /**
+     * Create a random number generator using the specified seed. A generator
+     * constructed with a given seed will generate the same sequence of values as
+     * all other generators constructed with the same seed.
+     */
+    fn new_seeded(x: u32, y: u32, z: u32, w: u32) -> XorShiftRng {
+        XorShiftRng {
+            x: x,
+            y: y,
+            z: z,
+            w: w,
+        }
+    }
+}
+
+/// Create a new random seed.
+pub fn seed() -> ~[u8] {
+    unsafe {
+        let n = rustrt::rand_seed_size() as uint;
+        let mut s = vec::from_elem(n, 0_u8);
+        do vec::as_mut_buf(s) |p, sz| {
+            rustrt::rand_gen_seed(p, sz as size_t)
+        }
+        s
+    }
+}
+
+// used to make space in TLS for a random number generator
+fn tls_rng_state(_v: @@mut IsaacRng) {}
+
+/**
+ * Gives back a lazily initialized task-local random number generator,
+ * seeded by the system. Intended to be used in method chaining style, ie
+ * `task_rng().gen::<int>()`.
+ */
+#[inline]
+pub fn task_rng() -> @@mut IsaacRng {
+    let r : Option<@@mut IsaacRng>;
+    unsafe {
+        r = local_data::local_data_get(tls_rng_state);
+    }
+    match r {
+        None => {
+            unsafe {
+                let rng = @@mut IsaacRng::new_seeded(seed());
+                local_data::local_data_set(tls_rng_state, rng);
+                rng
+            }
+        }
+        Some(rng) => rng
+    }
+}
+
+// Allow direct chaining with `task_rng`
+impl<R: Rng> Rng for @@mut R {
+    #[inline(always)]
+    fn next(&mut self) -> u32 {
+        match *self {
+            @@ref mut r => r.next()
+        }
+    }
+}
+
+/**
+ * Returns a random value of a Rand type, using the task's random number
+ * generator.
+ */
+#[inline]
+pub fn random<T: Rand>() -> T {
+    match *task_rng() {
+        @ref mut r => r.gen()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use option::{Option, Some};
+    use super::*;
+
+    #[test]
+    fn test_rng_seeded() {
+        let seed = seed();
+        let mut ra = IsaacRng::new_seeded(seed);
+        let mut rb = IsaacRng::new_seeded(seed);
+        assert_eq!(ra.gen_str(100u), rb.gen_str(100u));
+    }
+
+    #[test]
+    fn test_rng_seeded_custom_seed() {
+        // much shorter than generated seeds which are 1024 bytes
+        let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
+        let mut ra = IsaacRng::new_seeded(seed);
+        let mut rb = IsaacRng::new_seeded(seed);
+        assert_eq!(ra.gen_str(100u), rb.gen_str(100u));
+    }
+
+    #[test]
+    fn test_rng_seeded_custom_seed2() {
+        let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
+        let mut ra = IsaacRng::new_seeded(seed);
+        // Regression test that isaac is actually using the above vector
+        let r = ra.next();
+        error!("%?", r);
+        assert!(r == 890007737u32 // on x86_64
+                     || r == 2935188040u32); // on x86
+    }
+
+    #[test]
+    fn test_gen_int_range() {
+        let mut r = rng();
+        let a = r.gen_int_range(-3, 42);
+        assert!(a >= -3 && a < 42);
+        assert_eq!(r.gen_int_range(0, 1), 0);
+        assert_eq!(r.gen_int_range(-12, -11), -12);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_gen_int_from_fail() {
+        let mut r = rng();
+        r.gen_int_range(5, -2);
+    }
+
+    #[test]
+    fn test_gen_uint_range() {
+        let mut r = rng();
+        let a = r.gen_uint_range(3u, 42u);
+        assert!(a >= 3u && a < 42u);
+        assert_eq!(r.gen_uint_range(0u, 1u), 0u);
+        assert_eq!(r.gen_uint_range(12u, 13u), 12u);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_gen_uint_range_fail() {
+        let mut r = rng();
+        r.gen_uint_range(5u, 2u);
+    }
+
+    #[test]
+    fn test_gen_float() {
+        let mut r = rng();
+        let a = r.gen::<float>();
+        let b = r.gen::<float>();
+        debug!((a, b));
+    }
+
+    #[test]
+    fn test_gen_weighted_bool() {
+        let mut r = rng();
+        assert_eq!(r.gen_weighted_bool(0u), true);
+        assert_eq!(r.gen_weighted_bool(1u), true);
+    }
+
+    #[test]
+    fn test_gen_str() {
+        let mut r = rng();
+        debug!(r.gen_str(10u));
+        debug!(r.gen_str(10u));
+        debug!(r.gen_str(10u));
+        assert_eq!(r.gen_str(0u).len(), 0u);
+        assert_eq!(r.gen_str(10u).len(), 10u);
+        assert_eq!(r.gen_str(16u).len(), 16u);
+    }
+
+    #[test]
+    fn test_gen_bytes() {
+        let mut r = rng();
+        assert_eq!(r.gen_bytes(0u).len(), 0u);
+        assert_eq!(r.gen_bytes(10u).len(), 10u);
+        assert_eq!(r.gen_bytes(16u).len(), 16u);
+    }
+
+    #[test]
+    fn test_choose() {
+        let mut r = rng();
+        assert_eq!(r.choose([1, 1, 1]), 1);
+    }
+
+    #[test]
+    fn test_choose_option() {
+        let mut r = rng();
+        let x: Option<int> = r.choose_option([]);
+        assert!(x.is_none());
+        assert_eq!(r.choose_option([1, 1, 1]), Some(1));
+    }
+
+    #[test]
+    fn test_choose_weighted() {
+        let mut r = rng();
+        assert!(r.choose_weighted(~[
+            Weighted { weight: 1u, item: 42 },
+        ]) == 42);
+        assert!(r.choose_weighted(~[
+            Weighted { weight: 0u, item: 42 },
+            Weighted { weight: 1u, item: 43 },
+        ]) == 43);
+    }
+
+    #[test]
+    fn test_choose_weighted_option() {
+        let mut r = rng();
+        assert!(r.choose_weighted_option(~[
+            Weighted { weight: 1u, item: 42 },
+        ]) == Some(42));
+        assert!(r.choose_weighted_option(~[
+            Weighted { weight: 0u, item: 42 },
+            Weighted { weight: 1u, item: 43 },
+        ]) == Some(43));
+        let v: Option<int> = r.choose_weighted_option([]);
+        assert!(v.is_none());
+    }
+
+    #[test]
+    fn test_weighted_vec() {
+        let mut r = rng();
+        let empty: ~[int] = ~[];
+        assert_eq!(r.weighted_vec(~[]), empty);
+        assert!(r.weighted_vec(~[
+            Weighted { weight: 0u, item: 3u },
+            Weighted { weight: 1u, item: 2u },
+            Weighted { weight: 2u, item: 1u },
+        ]) == ~[2u, 1u, 1u]);
+    }
+
+    #[test]
+    fn test_shuffle() {
+        let mut r = rng();
+        let empty: ~[int] = ~[];
+        assert_eq!(r.shuffle(~[]), empty);
+        assert_eq!(r.shuffle(~[1, 1, 1]), ~[1, 1, 1]);
+    }
+
+    #[test]
+    fn test_task_rng() {
+        let mut r = task_rng();
+        r.gen::<int>();
+        assert_eq!(r.shuffle(~[1, 1, 1]), ~[1, 1, 1]);
+        assert_eq!(r.gen_uint_range(0u, 1u), 0u);
+    }
+
+    #[test]
+    fn test_random() {
+        // not sure how to test this aside from just getting some values
+        let _n : uint = random();
+        let _f : f32 = random();
+        let _o : Option<Option<i8>> = random();
+        let _many : ((),
+                     (~uint, @int, ~Option<~(@char, ~(@bool,))>),
+                     (u8, i8, u16, i16, u32, i32, u64, i64),
+                     (f32, (f64, (float,)))) = random();
+    }
+
+    #[test]
+    fn compare_isaac_implementation() {
+        // This is to verify that the implementation of the ISAAC rng is
+        // correct (i.e. matches the output of the upstream implementation,
+        // which is in the runtime)
+        use vec;
+        use libc::size_t;
+
+        #[abi = "cdecl"]
+        mod rustrt {
+            use libc::size_t;
+
+            #[allow(non_camel_case_types)] // runtime type
+            pub enum rust_rng {}
+
+            pub extern {
+                unsafe fn rand_new_seeded(buf: *u8, sz: size_t) -> *rust_rng;
+                unsafe fn rand_next(rng: *rust_rng) -> u32;
+                unsafe fn rand_free(rng: *rust_rng);
+            }
+        }
+
+        // run against several seeds
+        for 10.times {
+            unsafe {
+                let seed = super::seed();
+                let rt_rng = do vec::as_imm_buf(seed) |p, sz| {
+                    rustrt::rand_new_seeded(p, sz as size_t)
+                };
+                let mut rng = IsaacRng::new_seeded(seed);
+
+                for 10000.times {
+                    assert_eq!(rng.next(), rustrt::rand_next(rt_rng));
+                }
+                rustrt::rand_free(rt_rng);
+            }
+        }
+    }
+}
diff --git a/src/libstd/rand/distributions.rs b/src/libstd/rand/distributions.rs
new file mode 100644
index 00000000000..72cff5111e7
--- /dev/null
+++ b/src/libstd/rand/distributions.rs
@@ -0,0 +1,148 @@
+// 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.
+
+//! Sampling from random distributions
+
+// Some implementations use the Ziggurat method
+// https://en.wikipedia.org/wiki/Ziggurat_algorithm
+//
+// The version used here is ZIGNOR [Doornik 2005, "An Improved
+// Ziggurat Method to Generate Normal Random Samples"] which is slower
+// (about double, it generates an extra random number) than the
+// canonical version [Marsaglia & Tsang 2000, "The Ziggurat Method for
+// Generating Random Variables"], but more robust. If one wanted, one
+// could implement VIZIGNOR the ZIGNOR paper for more speed.
+
+use prelude::*;
+use rand::{Rng,Rand};
+
+mod ziggurat_tables;
+
+// inlining should mean there is no performance penalty for this
+#[inline(always)]
+fn ziggurat<R:Rng>(rng: &mut R,
+                   center_u: bool,
+                   X: ziggurat_tables::ZigTable,
+                   F: ziggurat_tables::ZigTable,
+                   F_DIFF: ziggurat_tables::ZigTable,
+                   pdf: &'static fn(f64) -> f64, // probability density function
+                   zero_case: &'static fn(&mut R, f64) -> f64) -> f64 {
+    loop {
+        let u = if center_u {2.0 * rng.gen() - 1.0} else {rng.gen()};
+        let i: uint = rng.gen::<uint>() & 0xff;
+        let x = u * X[i];
+
+        let test_x = if center_u {f64::abs(x)} else {x};
+
+        // algebraically equivalent to |u| < X[i+1]/X[i] (or u < X[i+1]/X[i])
+        if test_x < X[i + 1] {
+            return x;
+        }
+        if i == 0 {
+            return zero_case(rng, u);
+        }
+        // algebraically equivalent to f1 + DRanU()*(f0 - f1) < 1
+        if F[i+1] + F_DIFF[i+1] * rng.gen() < pdf(x) {
+            return x;
+        }
+    }
+}
+
+/// A wrapper around an `f64` to generate N(0, 1) random numbers (a.k.a.  a
+/// standard normal, or Gaussian). Multiplying the generated values by the
+/// desired standard deviation `sigma` then adding the desired mean `mu` will
+/// give N(mu, sigma^2) distributed random numbers.
+///
+/// Note that this has to be unwrapped before use as an `f64` (using either
+/// `*` or `cast::transmute` is safe).
+///
+/// # Example
+///
+/// ~~~
+/// use core::rand::distributions::StandardNormal;
+///
+/// fn main() {
+///     let normal = 2.0 + (*rand::random::<StandardNormal>()) * 3.0;
+///     println(fmt!("%f is from a N(2, 9) distribution", normal))
+/// }
+/// ~~~
+pub struct StandardNormal(f64);
+
+impl Rand for StandardNormal {
+    fn rand<R:Rng>(rng: &mut R) -> StandardNormal {
+        #[inline(always)]
+        fn pdf(x: f64) -> f64 {
+            f64::exp((-x*x/2.0) as f64) as f64
+        }
+        #[inline(always)]
+        fn zero_case<R:Rng>(rng: &mut R, u: f64) -> f64 {
+            // compute a random number in the tail by hand
+
+            // strange initial conditions, because the loop is not
+            // do-while, so the condition should be true on the first
+            // run, they get overwritten anyway (0 < 1, so these are
+            // good).
+            let mut x = 1.0, y = 0.0;
+
+            // XXX infinities?
+            while -2.0*y < x * x {
+                x = f64::ln(rng.gen()) / ziggurat_tables::ZIG_NORM_R;
+                y = f64::ln(rng.gen());
+            }
+            if u < 0.0 {x-ziggurat_tables::ZIG_NORM_R} else {ziggurat_tables::ZIG_NORM_R-x}
+        }
+
+        StandardNormal(ziggurat(
+            rng,
+            true, // this is symmetric
+            &ziggurat_tables::ZIG_NORM_X,
+            &ziggurat_tables::ZIG_NORM_F, &ziggurat_tables::ZIG_NORM_F_DIFF,
+            pdf, zero_case))
+    }
+}
+
+/// A wrapper around an `f64` to generate Exp(1) random numbers. Dividing by
+/// the desired rate `lambda` will give Exp(lambda) distributed random
+/// numbers.
+///
+/// Note that this has to be unwrapped before use as an `f64` (using either
+/// `*` or `cast::transmute` is safe).
+///
+/// # Example
+///
+/// ~~~
+/// use core::rand::distributions::Exp1;
+///
+/// fn main() {
+///     let exp2 = (*rand::random::<Exp1>()) * 0.5;
+///     println(fmt!("%f is from a Exp(2) distribution", exp2));
+/// }
+/// ~~~
+pub struct Exp1(f64);
+
+// This could be done via `-f64::ln(rng.gen::<f64>())` but that is slower.
+impl Rand for Exp1 {
+    #[inline]
+    fn rand<R:Rng>(rng: &mut R) -> Exp1 {
+        #[inline(always)]
+        fn pdf(x: f64) -> f64 {
+            f64::exp(-x)
+        }
+        #[inline(always)]
+        fn zero_case<R:Rng>(rng: &mut R, _u: f64) -> f64 {
+            ziggurat_tables::ZIG_EXP_R - f64::ln(rng.gen())
+        }
+
+        Exp1(ziggurat(rng, false,
+                      &ziggurat_tables::ZIG_EXP_X,
+                      &ziggurat_tables::ZIG_EXP_F, &ziggurat_tables::ZIG_EXP_F_DIFF,
+                      pdf, zero_case))
+    }
+}
diff --git a/src/libstd/rand/ziggurat_tables.rs b/src/libstd/rand/ziggurat_tables.rs
new file mode 100644
index 00000000000..aca2457cac4
--- /dev/null
+++ b/src/libstd/rand/ziggurat_tables.rs
@@ -0,0 +1,412 @@
+// 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.
+
+// Tables for distributions which are sampled using the ziggurat
+// algorithm. Autogenerated by `ziggurat_tables.py`.
+
+pub type ZigTable = &'static [f64, .. 257];
+pub static ZIG_NORM_R: f64 = 3.654152885361008796;
+pub static ZIG_NORM_X: [f64, .. 257] =
+    [3.910757959537090045, 3.654152885361008796, 3.449278298560964462, 3.320244733839166074,
+     3.224575052047029100, 3.147889289517149969, 3.083526132001233044, 3.027837791768635434,
+     2.978603279880844834, 2.934366867207854224, 2.894121053612348060, 2.857138730872132548,
+     2.822877396825325125, 2.790921174000785765, 2.760944005278822555, 2.732685359042827056,
+     2.705933656121858100, 2.680514643284522158, 2.656283037575502437, 2.633116393630324570,
+     2.610910518487548515, 2.589575986706995181, 2.569035452680536569, 2.549221550323460761,
+     2.530075232158516929, 2.511544441625342294, 2.493583041269680667, 2.476149939669143318,
+     2.459208374333311298, 2.442725318198956774, 2.426670984935725972, 2.411018413899685520,
+     2.395743119780480601, 2.380822795170626005, 2.366237056715818632, 2.351967227377659952,
+     2.337996148795031370, 2.324308018869623016, 2.310888250599850036, 2.297723348901329565,
+     2.284800802722946056, 2.272108990226823888, 2.259637095172217780, 2.247375032945807760,
+     2.235313384928327984, 2.223443340090905718, 2.211756642882544366, 2.200245546609647995,
+     2.188902771624720689, 2.177721467738641614, 2.166695180352645966, 2.155817819875063268,
+     2.145083634046203613, 2.134487182844320152, 2.124023315687815661, 2.113687150684933957,
+     2.103474055713146829, 2.093379631137050279, 2.083399693996551783, 2.073530263516978778,
+     2.063767547809956415, 2.054107931648864849, 2.044547965215732788, 2.035084353727808715,
+     2.025713947862032960, 2.016433734904371722, 2.007240830558684852, 1.998132471356564244,
+     1.989106007615571325, 1.980158896898598364, 1.971288697931769640, 1.962493064942461896,
+     1.953769742382734043, 1.945116560006753925, 1.936531428273758904, 1.928012334050718257,
+     1.919557336591228847, 1.911164563769282232, 1.902832208548446369, 1.894558525668710081,
+     1.886341828534776388, 1.878180486290977669, 1.870072921069236838, 1.862017605397632281,
+     1.854013059758148119, 1.846057850283119750, 1.838150586580728607, 1.830289919680666566,
+     1.822474540091783224, 1.814703175964167636, 1.806974591348693426, 1.799287584547580199,
+     1.791640986550010028, 1.784033659547276329, 1.776464495522344977, 1.768932414909077933,
+     1.761436365316706665, 1.753975320315455111, 1.746548278279492994, 1.739154261283669012,
+     1.731792314050707216, 1.724461502945775715, 1.717160915015540690, 1.709889657069006086,
+     1.702646854797613907, 1.695431651932238548, 1.688243209434858727, 1.681080704722823338,
+     1.673943330923760353, 1.666830296159286684, 1.659740822855789499, 1.652674147080648526,
+     1.645629517902360339, 1.638606196773111146, 1.631603456932422036, 1.624620582830568427,
+     1.617656869570534228, 1.610711622367333673, 1.603784156023583041, 1.596873794420261339,
+     1.589979870021648534, 1.583101723393471438, 1.576238702733332886, 1.569390163412534456,
+     1.562555467528439657, 1.555733983466554893, 1.548925085471535512, 1.542128153226347553,
+     1.535342571438843118, 1.528567729435024614, 1.521803020758293101, 1.515047842773992404,
+     1.508301596278571965, 1.501563685112706548, 1.494833515777718391, 1.488110497054654369,
+     1.481394039625375747, 1.474683555695025516, 1.467978458615230908, 1.461278162507407830,
+     1.454582081885523293, 1.447889631277669675, 1.441200224845798017, 1.434513276002946425,
+     1.427828197027290358, 1.421144398672323117, 1.414461289772464658, 1.407778276843371534,
+     1.401094763676202559, 1.394410150925071257, 1.387723835686884621, 1.381035211072741964,
+     1.374343665770030531, 1.367648583594317957, 1.360949343030101844, 1.354245316759430606,
+     1.347535871177359290, 1.340820365893152122, 1.334098153216083604, 1.327368577624624679,
+     1.320630975217730096, 1.313884673146868964, 1.307128989027353860, 1.300363230327433728,
+     1.293586693733517645, 1.286798664489786415, 1.279998415710333237, 1.273185207661843732,
+     1.266358287014688333, 1.259516886060144225, 1.252660221891297887, 1.245787495544997903,
+     1.238897891102027415, 1.231990574742445110, 1.225064693752808020, 1.218119375481726552,
+     1.211153726239911244, 1.204166830140560140, 1.197157747875585931, 1.190125515422801650,
+     1.183069142678760732, 1.175987612011489825, 1.168879876726833800, 1.161744859441574240,
+     1.154581450355851802, 1.147388505416733873, 1.140164844363995789, 1.132909248648336975,
+     1.125620459211294389, 1.118297174115062909, 1.110938046009249502, 1.103541679420268151,
+     1.096106627847603487, 1.088631390649514197, 1.081114409698889389, 1.073554065787871714,
+     1.065948674757506653, 1.058296483326006454, 1.050595664586207123, 1.042844313139370538,
+     1.035040439828605274, 1.027181966030751292, 1.019266717460529215, 1.011292417434978441,
+     1.003256679539591412, 0.995156999629943084, 0.986990747093846266, 0.978755155288937750,
+     0.970447311058864615, 0.962064143217605250, 0.953602409875572654, 0.945058684462571130,
+     0.936429340280896860, 0.927710533396234771, 0.918898183643734989, 0.909987953490768997,
+     0.900975224455174528, 0.891855070726792376, 0.882622229578910122, 0.873271068082494550,
+     0.863795545546826915, 0.854189171001560554, 0.844444954902423661, 0.834555354079518752,
+     0.824512208745288633, 0.814306670128064347, 0.803929116982664893, 0.793369058833152785,
+     0.782615023299588763, 0.771654424216739354, 0.760473406422083165, 0.749056662009581653,
+     0.737387211425838629, 0.725446140901303549, 0.713212285182022732, 0.700661841097584448,
+     0.687767892786257717, 0.674499822827436479, 0.660822574234205984, 0.646695714884388928,
+     0.632072236375024632, 0.616896989996235545, 0.601104617743940417, 0.584616766093722262,
+     0.567338257040473026, 0.549151702313026790, 0.529909720646495108, 0.509423329585933393,
+     0.487443966121754335, 0.463634336771763245, 0.437518402186662658, 0.408389134588000746,
+     0.375121332850465727, 0.335737519180459465, 0.286174591747260509, 0.215241895913273806,
+     0.000000000000000000];
+pub static ZIG_NORM_F: [f64, .. 257] =
+    [0.000477467764586655, 0.001260285930498598, 0.002609072746106363, 0.004037972593371872,
+     0.005522403299264754, 0.007050875471392110, 0.008616582769422917, 0.010214971439731100,
+     0.011842757857943104, 0.013497450601780807, 0.015177088307982072, 0.016880083152595839,
+     0.018605121275783350, 0.020351096230109354, 0.022117062707379922, 0.023902203305873237,
+     0.025705804008632656, 0.027527235669693315, 0.029365939758230111, 0.031221417192023690,
+     0.033093219458688698, 0.034980941461833073, 0.036884215688691151, 0.038802707404656918,
+     0.040736110656078753, 0.042684144916619378, 0.044646552251446536, 0.046623094902089664,
+     0.048613553216035145, 0.050617723861121788, 0.052635418276973649, 0.054666461325077916,
+     0.056710690106399467, 0.058767952921137984, 0.060838108349751806, 0.062921024437977854,
+     0.065016577971470438, 0.067124653828023989, 0.069245144397250269, 0.071377949059141965,
+     0.073522973714240991, 0.075680130359194964, 0.077849336702372207, 0.080030515814947509,
+     0.082223595813495684, 0.084428509570654661, 0.086645194450867782, 0.088873592068594229,
+     0.091113648066700734, 0.093365311913026619, 0.095628536713353335, 0.097903279039215627,
+     0.100189498769172020, 0.102487158942306270, 0.104796225622867056, 0.107116667775072880,
+     0.109448457147210021, 0.111791568164245583, 0.114145977828255210, 0.116511665626037014,
+     0.118888613443345698, 0.121276805485235437, 0.123676228202051403, 0.126086870220650349,
+     0.128508722280473636, 0.130941777174128166, 0.133386029692162844, 0.135841476571757352,
+     0.138308116449064322, 0.140785949814968309, 0.143274978974047118, 0.145775208006537926,
+     0.148286642733128721, 0.150809290682410169, 0.153343161060837674, 0.155888264725064563,
+     0.158444614156520225, 0.161012223438117663, 0.163591108232982951, 0.166181285765110071,
+     0.168782774801850333, 0.171395595638155623, 0.174019770082499359, 0.176655321444406654,
+     0.179302274523530397, 0.181960655600216487, 0.184630492427504539, 0.187311814224516926,
+     0.190004651671193070, 0.192709036904328807, 0.195425003514885592, 0.198152586546538112,
+     0.200891822495431333, 0.203642749311121501, 0.206405406398679298, 0.209179834621935651,
+     0.211966076307852941, 0.214764175252008499, 0.217574176725178370, 0.220396127481011589,
+     0.223230075764789593, 0.226076071323264877, 0.228934165415577484, 0.231804410825248525,
+     0.234686861873252689, 0.237581574432173676, 0.240488605941449107, 0.243408015423711988,
+     0.246339863502238771, 0.249284212419516704, 0.252241126056943765, 0.255210669955677150,
+     0.258192911338648023, 0.261187919133763713, 0.264195763998317568, 0.267216518344631837,
+     0.270250256366959984, 0.273297054069675804, 0.276356989296781264, 0.279430141762765316,
+     0.282516593084849388, 0.285616426816658109, 0.288729728483353931, 0.291856585618280984,
+     0.294997087801162572, 0.298151326697901342, 0.301319396102034120, 0.304501391977896274,
+     0.307697412505553769, 0.310907558127563710, 0.314131931597630143, 0.317370638031222396,
+     0.320623784958230129, 0.323891482377732021, 0.327173842814958593, 0.330470981380537099,
+     0.333783015832108509, 0.337110066638412809, 0.340452257045945450, 0.343809713148291340,
+     0.347182563958251478, 0.350570941482881204, 0.353974980801569250, 0.357394820147290515,
+     0.360830600991175754, 0.364282468130549597, 0.367750569780596226, 0.371235057669821344,
+     0.374736087139491414, 0.378253817247238111, 0.381788410875031348, 0.385340034841733958,
+     0.388908860020464597, 0.392495061461010764, 0.396098818517547080, 0.399720314981931668,
+     0.403359739222868885, 0.407017284331247953, 0.410693148271983222, 0.414387534042706784,
+     0.418100649839684591, 0.421832709231353298, 0.425583931339900579, 0.429354541031341519,
+     0.433144769114574058, 0.436954852549929273, 0.440785034667769915, 0.444635565397727750,
+     0.448506701509214067, 0.452398706863882505, 0.456311852680773566, 0.460246417814923481,
+     0.464202689050278838, 0.468180961407822172, 0.472181538469883255, 0.476204732721683788,
+     0.480250865911249714, 0.484320269428911598, 0.488413284707712059, 0.492530263646148658,
+     0.496671569054796314, 0.500837575128482149, 0.505028667945828791, 0.509245245998136142,
+     0.513487720749743026, 0.517756517232200619, 0.522052074674794864, 0.526374847174186700,
+     0.530725304406193921, 0.535103932383019565, 0.539511234259544614, 0.543947731192649941,
+     0.548413963257921133, 0.552910490428519918, 0.557437893621486324, 0.561996775817277916,
+     0.566587763258951771, 0.571211506738074970, 0.575868682975210544, 0.580559996103683473,
+     0.585286179266300333, 0.590047996335791969, 0.594846243770991268, 0.599681752622167719,
+     0.604555390700549533, 0.609468064928895381, 0.614420723892076803, 0.619414360609039205,
+     0.624450015550274240, 0.629528779928128279, 0.634651799290960050, 0.639820277456438991,
+     0.645035480824251883, 0.650298743114294586, 0.655611470583224665, 0.660975147780241357,
+     0.666391343912380640, 0.671861719900766374, 0.677388036222513090, 0.682972161648791376,
+     0.688616083008527058, 0.694321916130032579, 0.700091918140490099, 0.705928501336797409,
+     0.711834248882358467, 0.717811932634901395, 0.723864533472881599, 0.729995264565802437,
+     0.736207598131266683, 0.742505296344636245, 0.748892447223726720, 0.755373506511754500,
+     0.761953346841546475, 0.768637315803334831, 0.775431304986138326, 0.782341832659861902,
+     0.789376143571198563, 0.796542330428254619, 0.803849483176389490, 0.811307874318219935,
+     0.818929191609414797, 0.826726833952094231, 0.834716292992930375, 0.842915653118441077,
+     0.851346258465123684, 0.860033621203008636, 0.869008688043793165, 0.878309655816146839,
+     0.887984660763399880, 0.898095921906304051, 0.908726440060562912, 0.919991505048360247,
+     0.932060075968990209, 0.945198953453078028, 0.959879091812415930, 0.977101701282731328,
+     1.000000000000000000];
+pub static ZIG_NORM_F_DIFF: [f64, .. 257] =
+    [0.000000000000000000, 0.000782818165911943, 0.001348786815607765, 0.001428899847265509,
+     0.001484430705892882, 0.001528472172127356, 0.001565707298030807, 0.001598388670308183,
+     0.001627786418212004, 0.001654692743837703, 0.001679637706201265, 0.001702994844613767,
+     0.001725038123187510, 0.001745974954326004, 0.001765966477270568, 0.001785140598493315,
+     0.001803600702759419, 0.001821431661060659, 0.001838704088536796, 0.001855477433793579,
+     0.001871802266665008, 0.001887722003144375, 0.001903274226858077, 0.001918491715965767,
+     0.001933403251421835, 0.001948034260540625, 0.001962407334827158, 0.001976542650643127,
+     0.001990458313945481, 0.002004170645086643, 0.002017694415851860, 0.002031043048104267,
+     0.002044228781321551, 0.002057262814738517, 0.002070155428613822, 0.002082916088226049,
+     0.002095553533492583, 0.002108075856553551, 0.002120490569226280, 0.002132804661891696,
+     0.002145024655099026, 0.002157156644953973, 0.002169206343177243, 0.002181179112575302,
+     0.002193079998548175, 0.002204913757158977, 0.002216684880213121, 0.002228397617726446,
+     0.002240055998106505, 0.002251663846325885, 0.002263224800326716, 0.002274742325862292,
+     0.002286219729956393, 0.002297660173134250, 0.002309066680560787, 0.002320442152205823,
+     0.002331789372137141, 0.002343111017035562, 0.002354409664009627, 0.002365687797781804,
+     0.002376947817308683, 0.002388192041889739, 0.002399422716815966, 0.002410642018598946,
+     0.002421852059823287, 0.002433054893654529, 0.002444252518034679, 0.002455446879594508,
+     0.002466639877306970, 0.002477833365903986, 0.002489029159078809, 0.002500229032490808,
+     0.002511434726590794, 0.002522647949281448, 0.002533870378427505, 0.002545103664226889,
+     0.002556349431455662, 0.002567609281597438, 0.002578884794865288, 0.002590177532127119,
+     0.002601489036740262, 0.002612820836305291, 0.002624174444343735, 0.002635551361907296,
+     0.002646953079123743, 0.002658381076686089, 0.002669836827288052, 0.002681321797012387,
+     0.002692837446676144, 0.002704385233135737, 0.002715966610556786, 0.002727583031652520,
+     0.002739235948893221, 0.002750926815690169, 0.002762657087557796, 0.002774428223256353,
+     0.002786241685917290, 0.002798098944155558, 0.002810001473169871, 0.002821950755833219,
+     0.002833948283778004, 0.002845995558475284, 0.002858094092312607, 0.002870245409671041,
+     0.002882451048004164, 0.002894712558920987, 0.002907031509275432, 0.002919409482262880,
+     0.002931848078526783, 0.002944348917277934, 0.002956913637427061, 0.002969543898733384,
+     0.002982241382970874, 0.002995007795115689, 0.003007844864553855, 0.003020754346314269,
+     0.003033738022328147, 0.003046797702715820, 0.003059935227105459, 0.003073152465984053,
+     0.003086451322084072, 0.003099833731808721, 0.003113301666695822, 0.003126857134927052,
+     0.003140502182881588, 0.003154238896738770, 0.003168069404132778, 0.003181995875862154,
+     0.003196020527657495, 0.003210145622009941, 0.003224373470066433, 0.003238706433592253,
+     0.003253146927007733, 0.003267697419501892, 0.003282360437226572, 0.003297138565578506,
+     0.003312034451571411, 0.003327050806304299, 0.003342190407532641, 0.003357456102345890,
+     0.003372850809960137, 0.003388377524629727, 0.003404039318688046, 0.003419839345721265,
+     0.003435780843885239, 0.003451867139373843, 0.003468101650046629, 0.003484487889225119,
+     0.003501029469670069, 0.003517730107746697, 0.003534593627793237, 0.003551623966702611,
+     0.003568825178730639, 0.003586201440546166, 0.003603757056536316, 0.003621496464384588,
+     0.003639424240937217, 0.003657545108379068, 0.003675863940735269, 0.003694385770723563,
+     0.003713115796977806, 0.003732059391668707, 0.003751222108547281, 0.003770609691440940,
+     0.003790228083232539, 0.003810083435355216, 0.003830182117840641, 0.003850530729957835,
+     0.003871136111486317, 0.003892005354668437, 0.003913145816891062, 0.003934565134149914,
+     0.003956271235355358, 0.003978272357543333, 0.004000577062061084, 0.004023194251800533,
+     0.004046133189565926, 0.004069403517661885, 0.004093015278800460, 0.004116978938436600,
+     0.004141305408647655, 0.004166006073685835, 0.004191092817346642, 0.004216578052307351,
+     0.004242474751606884, 0.004268796482457593, 0.004295557442594244, 0.004322772499391836,
+     0.004350457232007221, 0.004378627976825644, 0.004407301876525049, 0.004436496933105327,
+     0.004466232065271192, 0.004496527170598785, 0.004527403192966406, 0.004558882195791591,
+     0.004590987441673855, 0.004623743479123199, 0.004657176237135574, 0.004691313128472929,
+     0.004726183162616859, 0.004761817069491636, 0.004798247435199299, 0.004835508851176451,
+     0.004873638078381815, 0.004912674228345848, 0.004952658963181422, 0.004993636716962402,
+     0.005035654941235035, 0.005078764377854039, 0.005123019362831771, 0.005168478165478940,
+     0.005215203367812893, 0.005263262290042703, 0.005312727468930079, 0.005363677197016692,
+     0.005416196132139284, 0.005470375988385734, 0.005526316321746716, 0.005584125426278286,
+     0.005643921359735682, 0.005705833121505521, 0.005770002010457520, 0.005836583196307310,
+     0.005905747545561058, 0.005977683752542928, 0.006052600837980204, 0.006130731092920838,
+     0.006212333565464245, 0.006297698213369562, 0.006387150879090475, 0.006481059288027780,
+     0.006579840329791975, 0.006683968961788356, 0.006793989182803495, 0.006910527673723577,
+     0.007034310911336661, 0.007166186857056056, 0.007307152748134871, 0.007458391141830445,
+     0.007621317291194862, 0.007797642342679434, 0.007989459040836144, 0.008199360125510702,
+     0.008430605346682607, 0.008687362737884952, 0.008975066840784529, 0.009300967772353674,
+     0.009675004947253041, 0.010111261142904171, 0.010630518154258861, 0.011265064987797335,
+     0.012068570920629962, 0.013138877484087819, 0.014680138359337902, 0.017222609470315398,
+     0.022898298717268672];
+pub static ZIG_EXP_R: f64 = 7.697117470131050077;
+pub static ZIG_EXP_X: [f64, .. 257] =
+    [8.697117470131052741, 7.697117470131050077, 6.941033629377212577, 6.478378493832569696,
+     6.144164665772472667, 5.882144315795399869, 5.666410167454033697, 5.482890627526062488,
+     5.323090505754398016, 5.181487281301500047, 5.054288489981304089, 4.938777085901250530,
+     4.832939741025112035, 4.735242996601741083, 4.644491885420085175, 4.559737061707351380,
+     4.480211746528421912, 4.405287693473573185, 4.334443680317273007, 4.267242480277365857,
+     4.203313713735184365, 4.142340865664051464, 4.084051310408297830, 4.028208544647936762,
+     3.974606066673788796, 3.923062500135489739, 3.873417670399509127, 3.825529418522336744,
+     3.779270992411667862, 3.734528894039797375, 3.691201090237418825, 3.649195515760853770,
+     3.608428813128909507, 3.568825265648337020, 3.530315889129343354, 3.492837654774059608,
+     3.456332821132760191, 3.420748357251119920, 3.386035442460300970, 3.352149030900109405,
+     3.319047470970748037, 3.286692171599068679, 3.255047308570449882, 3.224079565286264160,
+     3.193757903212240290, 3.164053358025972873, 3.134938858084440394, 3.106389062339824481,
+     3.078380215254090224, 3.050890016615455114, 3.023897504455676621, 2.997382949516130601,
+     2.971327759921089662, 2.945714394895045718, 2.920526286512740821, 2.895747768600141825,
+     2.871364012015536371, 2.847360965635188812, 2.823725302450035279, 2.800444370250737780,
+     2.777506146439756574, 2.754899196562344610, 2.732612636194700073, 2.710636095867928752,
+     2.688959688741803689, 2.667573980773266573, 2.646469963151809157, 2.625639026797788489,
+     2.605072938740835564, 2.584763820214140750, 2.564704126316905253, 2.544886627111869970,
+     2.525304390037828028, 2.505950763528594027, 2.486819361740209455, 2.467904050297364815,
+     2.449198932978249754, 2.430698339264419694, 2.412396812688870629, 2.394289099921457886,
+     2.376370140536140596, 2.358635057409337321, 2.341079147703034380, 2.323697874390196372,
+     2.306486858283579799, 2.289441870532269441, 2.272558825553154804, 2.255833774367219213,
+     2.239262898312909034, 2.222842503111036816, 2.206569013257663858, 2.190438966723220027,
+     2.174449009937774679, 2.158595893043885994, 2.142876465399842001, 2.127287671317368289,
+     2.111826546019042183, 2.096490211801715020, 2.081275874393225145, 2.066180819490575526,
+     2.051202409468584786, 2.036338080248769611, 2.021585338318926173, 2.006941757894518563,
+     1.992404978213576650, 1.977972700957360441, 1.963642687789548313, 1.949412758007184943,
+     1.935280786297051359, 1.921244700591528076, 1.907302480018387536, 1.893452152939308242,
+     1.879691795072211180, 1.866019527692827973, 1.852433515911175554, 1.838931967018879954,
+     1.825513128903519799, 1.812175288526390649, 1.798916770460290859, 1.785735935484126014,
+     1.772631179231305643, 1.759600930889074766, 1.746643651946074405, 1.733757834985571566,
+     1.720942002521935299, 1.708194705878057773, 1.695514524101537912, 1.682900062917553896,
+     1.670349953716452118, 1.657862852574172763, 1.645437439303723659, 1.633072416535991334,
+     1.620766508828257901, 1.608518461798858379, 1.596327041286483395, 1.584191032532688892,
+     1.572109239386229707, 1.560080483527888084, 1.548103603714513499, 1.536177455041032092,
+     1.524300908219226258, 1.512472848872117082, 1.500692176842816750, 1.488957805516746058,
+     1.477268661156133867, 1.465623682245745352, 1.454021818848793446, 1.442462031972012504,
+     1.430943292938879674, 1.419464582769983219, 1.408024891569535697, 1.396623217917042137,
+     1.385258568263121992, 1.373929956328490576, 1.362636402505086775, 1.351376933258335189,
+     1.340150580529504643, 1.328956381137116560, 1.317793376176324749, 1.306660610415174117,
+     1.295557131686601027, 1.284481990275012642, 1.273434238296241139, 1.262412929069615330,
+     1.251417116480852521, 1.240445854334406572, 1.229498195693849105, 1.218573192208790124,
+     1.207669893426761121, 1.196787346088403092, 1.185924593404202199, 1.175080674310911677,
+     1.164254622705678921, 1.153445466655774743, 1.142652227581672841, 1.131873919411078511,
+     1.121109547701330200, 1.110358108727411031, 1.099618588532597308, 1.088889961938546813,
+     1.078171191511372307, 1.067461226479967662, 1.056759001602551429, 1.046063435977044209,
+     1.035373431790528542, 1.024687873002617211, 1.014005623957096480, 1.003325527915696735,
+     0.992646405507275897, 0.981967053085062602, 0.971286240983903260, 0.960602711668666509,
+     0.949915177764075969, 0.939222319955262286, 0.928522784747210395, 0.917815182070044311,
+     0.907098082715690257, 0.896370015589889935, 0.885629464761751528, 0.874874866291025066,
+     0.864104604811004484, 0.853317009842373353, 0.842510351810368485, 0.831682837734273206,
+     0.820832606554411814, 0.809957724057418282, 0.799056177355487174, 0.788125868869492430,
+     0.777164609759129710, 0.766170112735434672, 0.755139984181982249, 0.744071715500508102,
+     0.732962673584365398, 0.721810090308756203, 0.710611050909655040, 0.699362481103231959,
+     0.688061132773747808, 0.676703568029522584, 0.665286141392677943, 0.653804979847664947,
+     0.642255960424536365, 0.630634684933490286, 0.618936451394876075, 0.607156221620300030,
+     0.595288584291502887, 0.583327712748769489, 0.571267316532588332, 0.559100585511540626,
+     0.546820125163310577, 0.534417881237165604, 0.521885051592135052, 0.509211982443654398,
+     0.496388045518671162, 0.483401491653461857, 0.470239275082169006, 0.456886840931420235,
+     0.443327866073552401, 0.429543940225410703, 0.415514169600356364, 0.401214678896277765,
+     0.386617977941119573, 0.371692145329917234, 0.356399760258393816, 0.340696481064849122,
+     0.324529117016909452, 0.307832954674932158, 0.290527955491230394, 0.272513185478464703,
+     0.253658363385912022, 0.233790483059674731, 0.212671510630966620, 0.189958689622431842,
+     0.165127622564187282, 0.137304980940012589, 0.104838507565818778, 0.063852163815001570,
+     0.000000000000000000];
+pub static ZIG_EXP_F: [f64, .. 257] =
+    [0.000167066692307963, 0.000454134353841497, 0.000967269282327174, 0.001536299780301573,
+     0.002145967743718907, 0.002788798793574076, 0.003460264777836904, 0.004157295120833797,
+     0.004877655983542396, 0.005619642207205489, 0.006381905937319183, 0.007163353183634991,
+     0.007963077438017043, 0.008780314985808977, 0.009614413642502212, 0.010464810181029981,
+     0.011331013597834600, 0.012212592426255378, 0.013109164931254991, 0.014020391403181943,
+     0.014945968011691148, 0.015885621839973156, 0.016839106826039941, 0.017806200410911355,
+     0.018786700744696024, 0.019780424338009740, 0.020787204072578114, 0.021806887504283581,
+     0.022839335406385240, 0.023884420511558174, 0.024942026419731787, 0.026012046645134221,
+     0.027094383780955803, 0.028188948763978646, 0.029295660224637411, 0.030414443910466622,
+     0.031545232172893622, 0.032687963508959555, 0.033842582150874358, 0.035009037697397431,
+     0.036187284781931443, 0.037377282772959382, 0.038578995503074871, 0.039792391023374139,
+     0.041017441380414840, 0.042254122413316254, 0.043502413568888197, 0.044762297732943289,
+     0.046033761076175184, 0.047316792913181561, 0.048611385573379504, 0.049917534282706379,
+     0.051235237055126281, 0.052564494593071685, 0.053905310196046080, 0.055257689676697030,
+     0.056621641283742870, 0.057997175631200659, 0.059384305633420280, 0.060783046445479660,
+     0.062193415408541036, 0.063615431999807376, 0.065049117786753805, 0.066494496385339816,
+     0.067951593421936643, 0.069420436498728783, 0.070901055162371843, 0.072393480875708752,
+     0.073897746992364746, 0.075413888734058410, 0.076941943170480517, 0.078481949201606435,
+     0.080033947542319905, 0.081597980709237419, 0.083174093009632397, 0.084762330532368146,
+     0.086362741140756927, 0.087975374467270231, 0.089600281910032886, 0.091237516631040197,
+     0.092887133556043569, 0.094549189376055873, 0.096223742550432825, 0.097910853311492213,
+     0.099610583670637132, 0.101322997425953631, 0.103048160171257702, 0.104786139306570145,
+     0.106537004050001632, 0.108300825451033755, 0.110077676405185357, 0.111867631670056283,
+     0.113670767882744286, 0.115487163578633506, 0.117316899211555525, 0.119160057175327641,
+     0.121016721826674792, 0.122886979509545108, 0.124770918580830933, 0.126668629437510671,
+     0.128580204545228199, 0.130505738468330773, 0.132445327901387494, 0.134399071702213602,
+     0.136367070926428829, 0.138349428863580176, 0.140346251074862399, 0.142357645432472146,
+     0.144383722160634720, 0.146424593878344889, 0.148480375643866735, 0.150551185001039839,
+     0.152637142027442801, 0.154738369384468027, 0.156854992369365148, 0.158987138969314129,
+     0.161134939917591952, 0.163298528751901734, 0.165478041874935922, 0.167673618617250081,
+     0.169885401302527550, 0.172113535315319977, 0.174358169171353411, 0.176619454590494829,
+     0.178897546572478278, 0.181192603475496261, 0.183504787097767436, 0.185834262762197083,
+     0.188181199404254262, 0.190545769663195363, 0.192928149976771296, 0.195328520679563189,
+     0.197747066105098818, 0.200183974691911210, 0.202639439093708962, 0.205113656293837654,
+     0.207606827724221982, 0.210119159388988230, 0.212650861992978224, 0.215202151075378628,
+     0.217773247148700472, 0.220364375843359439, 0.222975768058120111, 0.225607660116683956,
+     0.228260293930716618, 0.230933917169627356, 0.233628783437433291, 0.236345152457059560,
+     0.239083290262449094, 0.241843469398877131, 0.244625969131892024, 0.247431075665327543,
+     0.250259082368862240, 0.253110290015629402, 0.255985007030415324, 0.258883549749016173,
+     0.261806242689362922, 0.264753418835062149, 0.267725419932044739, 0.270722596799059967,
+     0.273745309652802915, 0.276793928448517301, 0.279868833236972869, 0.282970414538780746,
+     0.286099073737076826, 0.289255223489677693, 0.292439288161892630, 0.295651704281261252,
+     0.298892921015581847, 0.302163400675693528, 0.305463619244590256, 0.308794066934560185,
+     0.312155248774179606, 0.315547685227128949, 0.318971912844957239, 0.322428484956089223,
+     0.325917972393556354, 0.329440964264136438, 0.332998068761809096, 0.336589914028677717,
+     0.340217149066780189, 0.343880444704502575, 0.347580494621637148, 0.351318016437483449,
+     0.355093752866787626, 0.358908472948750001, 0.362762973354817997, 0.366658079781514379,
+     0.370594648435146223, 0.374573567615902381, 0.378595759409581067, 0.382662181496010056,
+     0.386773829084137932, 0.390931736984797384, 0.395136981833290435, 0.399390684475231350,
+     0.403694012530530555, 0.408048183152032673, 0.412454465997161457, 0.416914186433003209,
+     0.421428728997616908, 0.425999541143034677, 0.430628137288459167, 0.435316103215636907,
+     0.440065100842354173, 0.444876873414548846, 0.449753251162755330, 0.454696157474615836,
+     0.459707615642138023, 0.464789756250426511, 0.469944825283960310, 0.475175193037377708,
+     0.480483363930454543, 0.485871987341885248, 0.491343869594032867, 0.496901987241549881,
+     0.502549501841348056, 0.508289776410643213, 0.514126393814748894, 0.520063177368233931,
+     0.526104213983620062, 0.532253880263043655, 0.538516872002862246, 0.544898237672440056,
+     0.551403416540641733, 0.558038282262587892, 0.564809192912400615, 0.571723048664826150,
+     0.578787358602845359, 0.586010318477268366, 0.593400901691733762, 0.600968966365232560,
+     0.608725382079622346, 0.616682180915207878, 0.624852738703666200, 0.633251994214366398,
+     0.641896716427266423, 0.650805833414571433, 0.660000841079000145, 0.669506316731925177,
+     0.679350572264765806, 0.689566496117078431, 0.700192655082788606, 0.711274760805076456,
+     0.722867659593572465, 0.735038092431424039, 0.747868621985195658, 0.761463388849896838,
+     0.775956852040116218, 0.791527636972496285, 0.808421651523009044, 0.826993296643051101,
+     0.847785500623990496, 0.871704332381204705, 0.900469929925747703, 0.938143680862176477,
+     1.000000000000000000];
+pub static ZIG_EXP_F_DIFF: [f64, .. 257] =
+    [0.000000000000000000, 0.000287067661533533, 0.000513134928485678, 0.000569030497974398,
+     0.000609667963417335, 0.000642831049855169, 0.000671465984262828, 0.000697030342996893,
+     0.000720360862708599, 0.000741986223663093, 0.000762263730113694, 0.000781447246315807,
+     0.000799724254382053, 0.000817237547791934, 0.000834098656693235, 0.000850396538527769,
+     0.000866203416804620, 0.000881578828420777, 0.000896572504999613, 0.000911226471926952,
+     0.000925576608509206, 0.000939653828282008, 0.000953484986066785, 0.000967093584871414,
+     0.000980500333784669, 0.000993723593313716, 0.001006779734568374, 0.001019683431705467,
+     0.001032447902101660, 0.001045085105172934, 0.001057605908173612, 0.001070020225402434,
+     0.001082337135821582, 0.001094564983022843, 0.001106711460658764, 0.001118783685829211,
+     0.001130788262427001, 0.001142731336065933, 0.001154618641914802, 0.001166455546523074,
+     0.001178247084534012, 0.001189997991027938, 0.001201712730115490, 0.001213395520299268,
+     0.001225050357040701, 0.001236681032901414, 0.001248291155571943, 0.001259884164055092,
+     0.001271463343231895, 0.001283031837006378, 0.001294592660197942, 0.001306148709326875,
+     0.001317702772419903, 0.001329257537945404, 0.001340815602974395, 0.001352379480650950,
+     0.001363951607045839, 0.001375534347457789, 0.001387130002219621, 0.001398740812059381,
+     0.001410368963061376, 0.001422016591266340, 0.001433685786946429, 0.001445378598586011,
+     0.001457097036596827, 0.001468843076792140, 0.001480618663643060, 0.001492425713336909,
+     0.001504266116655995, 0.001516141741693663, 0.001528054436422108, 0.001540006031125918,
+     0.001551998340713470, 0.001564033166917514, 0.001576112300394977, 0.001588237522735750,
+     0.001600410608388780, 0.001612633326513305, 0.001624907442762655, 0.001637234721007311,
+     0.001649616925003372, 0.001662055820012304, 0.001674553174376953, 0.001687110761059388,
+     0.001699730359144919, 0.001712413755316500, 0.001725162745304071, 0.001737979135312442,
+     0.001750864743431488, 0.001763821401032123, 0.001776850954151601, 0.001789955264870927,
+     0.001803136212688003, 0.001816395695889220, 0.001829735632922019, 0.001843157963772116,
+     0.001856664651347151, 0.001870257682870316, 0.001883939071285826, 0.001897710856679738,
+     0.001911575107717528, 0.001925533923102574, 0.001939589433056721, 0.001953743800826108,
+     0.001967999224215228, 0.001982357937151347, 0.001996822211282223, 0.002011394357609747,
+     0.002026076728162574, 0.002040871717710169, 0.002055781765521847, 0.002070809357173103,
+     0.002085957026402963, 0.002101227357025226, 0.002116622984897121, 0.002132146599948981,
+     0.002147800948277823, 0.002163588834309782, 0.002179513123034188, 0.002195576742314159,
+     0.002211782685277469, 0.002228134012792427, 0.002244633856033434, 0.002261285419141418,
+     0.002278091981983449, 0.002295056903017983, 0.002312183622271174, 0.002329475664429648,
+     0.002346936642057179, 0.002364570258941101, 0.002382380313575932, 0.002400370702791893,
+     0.002418545425535629, 0.002436908586812392, 0.002455464401797752, 0.002474217200128692,
+     0.002493171430384328, 0.002512331664766249, 0.002531702603989994, 0.002551289082400404,
+     0.002571096073321844, 0.002591128694658967, 0.002611392214760672, 0.002631892058563845,
+     0.002652633814032662, 0.002673623238910738, 0.002694866267805934, 0.002716369019626269,
+     0.002738137805389534, 0.002760179136428037, 0.002782499733014893, 0.002805106533435520,
+     0.002828006703534697, 0.002851207646767162, 0.002874717014785921, 0.002898542718600849,
+     0.002922692940346749, 0.002947176145699226, 0.002972001096982591, 0.002997176867015228,
+     0.003022712853742948, 0.003048618795714386, 0.003074904788455568, 0.003101581301807876,
+     0.003128659198296080, 0.003156149752600867, 0.003184064672214937, 0.003212416119368622,
+     0.003241216734320596, 0.003270479660111680, 0.003300218568896729, 0.003330447689969929,
+     0.003361181839619420, 0.003392436452949343, 0.003424227617828290, 0.003456572111131984,
+     0.003489487437467131, 0.003522991870580083, 0.003557104497672658, 0.003591845266868621,
+     0.003627235038102472, 0.003663295637722386, 0.003700049917134574, 0.003737521815846301,
+     0.003775736429304177, 0.003814720081962375, 0.003854500406067995, 0.003895106426696382,
+     0.003936568653631844, 0.003978919180756157, 0.004022191793678687, 0.004066422086428989,
+     0.004111647588127876, 0.004157907900659452, 0.004205244848493050, 0.004253702641940915,
+     0.004303328055299205, 0.004354170621502118, 0.004406282845128784, 0.004459720435841752,
+     0.004514542564613699, 0.004570812145417769, 0.004628596145424491, 0.004687965927177740,
+     0.004748997626717266, 0.004811772572194672, 0.004876377748206484, 0.004942906311860507,
+     0.005011458167522187, 0.005082140608288488, 0.005155069033533799, 0.005230367753417398,
+     0.005308170893076836, 0.005388623411430704, 0.005471882252147620, 0.005558117647517014,
+     0.005647514599798176, 0.005740274569295156, 0.005836617404105682, 0.005936783553485037,
+     0.006041036615386131, 0.006149666279423593, 0.006262991739818591, 0.006381365669577810,
+     0.006505178868201678, 0.006634865721946159, 0.006770910649812723, 0.006913855752425535,
+     0.007064309938019209, 0.007222959874423007, 0.007390583214465396, 0.007568064673498798,
+     0.007756415714389786, 0.007956798835585532, 0.008170557788458321, 0.008399255510700199,
+     0.008644722212900025, 0.008909116987305010, 0.009195007664428712, 0.009505475652925033,
+     0.009844255532840629, 0.010215923852312625, 0.010626158965710175, 0.011082105722287849,
+     0.011592898788496009, 0.012170432837851575, 0.012830529553771619, 0.013594766864701180,
+     0.014493463190219380, 0.015570784932380066, 0.016894014550512759, 0.018571645120042057,
+     0.020792203980939394, 0.023918831757214210, 0.028765597544542998, 0.037673750936428774,
+     0.061856319137823523];
diff --git a/src/libstd/rc.rs b/src/libstd/rc.rs
deleted file mode 100644
index 02f824b9113..00000000000
--- a/src/libstd/rc.rs
+++ /dev/null
@@ -1,368 +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.
-
-/** Task-local reference counted smart pointers
-
-Task-local reference counted smart pointers are an alternative to managed boxes with deterministic
-destruction. They are restricted to containing types that are either `Owned` or `Const` (or both) to
-prevent cycles.
-
-Neither `Rc<T>` or `RcMut<T>` is ever `Owned` and `RcMut<T>` is never `Const`. If `T` is `Const`, a
-cycle cannot be created with `Rc<T>` because there is no way to modify it after creation.
-
-*/
-
-use core::libc::{c_void, size_t, malloc, free};
-use core::unstable::intrinsics;
-use core::util;
-
-struct RcBox<T> {
-    value: T,
-    count: uint
-}
-
-/// Immutable reference counted pointer type
-#[non_owned]
-pub struct Rc<T> {
-    priv ptr: *mut RcBox<T>,
-}
-
-priv impl<T> Rc<T> {
-    unsafe fn new(value: T) -> Rc<T> {
-        let ptr = malloc(sys::size_of::<RcBox<T>>() as size_t) as *mut RcBox<T>;
-        assert!(!ptr::is_null(ptr));
-        intrinsics::move_val_init(&mut *ptr, RcBox{value: value, count: 1});
-        Rc{ptr: ptr}
-    }
-}
-
-// FIXME: #6516: should be a static method
-pub fn rc_from_owned<T: Owned>(value: T) -> Rc<T> {
-    unsafe { Rc::new(value) }
-}
-
-// FIXME: #6516: should be a static method
-pub fn rc_from_const<T: Const>(value: T) -> Rc<T> {
-    unsafe { Rc::new(value) }
-}
-
-pub impl<T> Rc<T> {
-    #[inline(always)]
-    fn borrow<'r>(&'r self) -> &'r T {
-        unsafe { cast::copy_lifetime(self, &(*self.ptr).value) }
-    }
-}
-
-#[unsafe_destructor]
-impl<T> Drop for Rc<T> {
-    fn finalize(&self) {
-        unsafe {
-            (*self.ptr).count -= 1;
-            if (*self.ptr).count == 0 {
-                util::replace_ptr(self.ptr, intrinsics::uninit());
-                free(self.ptr as *c_void)
-            }
-        }
-    }
-}
-
-impl<T> Clone for Rc<T> {
-    /// Return a shallow copy of the reference counted pointer.
-    #[inline]
-    fn clone(&self) -> Rc<T> {
-        unsafe {
-            (*self.ptr).count += 1;
-            Rc{ptr: self.ptr}
-        }
-    }
-}
-
-impl<T: DeepClone> DeepClone for Rc<T> {
-    /// Return a deep copy of the reference counted pointer.
-    #[inline]
-    fn deep_clone(&self) -> Rc<T> {
-        unsafe { Rc::new(self.borrow().deep_clone()) }
-    }
-}
-
-#[cfg(test)]
-mod test_rc {
-    use super::*;
-    use core::cell::Cell;
-
-    #[test]
-    fn test_clone() {
-        let x = rc_from_owned(Cell(5));
-        let y = x.clone();
-        do x.borrow().with_mut_ref |inner| {
-            *inner = 20;
-        }
-        assert_eq!(y.borrow().take(), 20);
-    }
-
-    #[test]
-    fn test_deep_clone() {
-        let x = rc_from_owned(Cell(5));
-        let y = x.deep_clone();
-        do x.borrow().with_mut_ref |inner| {
-            *inner = 20;
-        }
-        assert_eq!(y.borrow().take(), 5);
-    }
-
-    #[test]
-    fn test_simple() {
-        let x = rc_from_const(5);
-        assert_eq!(*x.borrow(), 5);
-    }
-
-    #[test]
-    fn test_simple_clone() {
-        let x = rc_from_const(5);
-        let y = x.clone();
-        assert_eq!(*x.borrow(), 5);
-        assert_eq!(*y.borrow(), 5);
-    }
-
-    #[test]
-    fn test_destructor() {
-        let x = rc_from_owned(~5);
-        assert_eq!(**x.borrow(), 5);
-    }
-}
-
-#[abi = "rust-intrinsic"]
-extern "rust-intrinsic" {
-    fn init<T>() -> T;
-    fn uninit<T>() -> T;
-}
-
-#[deriving(Eq)]
-enum Borrow {
-    Mutable,
-    Immutable,
-    Nothing
-}
-
-struct RcMutBox<T> {
-    value: T,
-    count: uint,
-    borrow: Borrow
-}
-
-/// Mutable reference counted pointer type
-#[non_owned]
-#[mutable]
-pub struct RcMut<T> {
-    priv ptr: *mut RcMutBox<T>,
-}
-
-priv impl<T> RcMut<T> {
-    unsafe fn new(value: T) -> RcMut<T> {
-        let ptr = malloc(sys::size_of::<RcMutBox<T>>() as size_t) as *mut RcMutBox<T>;
-        assert!(!ptr::is_null(ptr));
-        intrinsics::move_val_init(&mut *ptr, RcMutBox{value: value, count: 1, borrow: Nothing});
-        RcMut{ptr: ptr}
-    }
-}
-
-// FIXME: #6516: should be a static method
-pub fn rc_mut_from_owned<T: Owned>(value: T) -> RcMut<T> {
-    unsafe { RcMut::new(value) }
-}
-
-// FIXME: #6516: should be a static method
-pub fn rc_mut_from_const<T: Const>(value: T) -> RcMut<T> {
-    unsafe { RcMut::new(value) }
-}
-
-pub impl<T> RcMut<T> {
-    /// Fails if there is already a mutable borrow of the box
-    #[inline]
-    fn with_borrow<U>(&self, f: &fn(&T) -> U) -> U {
-        unsafe {
-            assert!((*self.ptr).borrow != Mutable);
-            let previous = (*self.ptr).borrow;
-            (*self.ptr).borrow = Immutable;
-            let res = f(&(*self.ptr).value);
-            (*self.ptr).borrow = previous;
-            res
-        }
-    }
-
-    /// Fails if there is already a mutable or immutable borrow of the box
-    #[inline]
-    fn with_mut_borrow<U>(&self, f: &fn(&mut T) -> U) -> U {
-        unsafe {
-            assert_eq!((*self.ptr).borrow, Nothing);
-            (*self.ptr).borrow = Mutable;
-            let res = f(&mut (*self.ptr).value);
-            (*self.ptr).borrow = Nothing;
-            res
-        }
-    }
-}
-
-#[unsafe_destructor]
-impl<T> Drop for RcMut<T> {
-    fn finalize(&self) {
-        unsafe {
-            (*self.ptr).count -= 1;
-            if (*self.ptr).count == 0 {
-                util::replace_ptr(self.ptr, uninit());
-                free(self.ptr as *c_void)
-            }
-        }
-    }
-}
-
-impl<T> Clone for RcMut<T> {
-    /// Return a shallow copy of the reference counted pointer.
-    #[inline]
-    fn clone(&self) -> RcMut<T> {
-        unsafe {
-            (*self.ptr).count += 1;
-            RcMut{ptr: self.ptr}
-        }
-    }
-}
-
-impl<T: DeepClone> DeepClone for RcMut<T> {
-    /// Return a deep copy of the reference counted pointer.
-    #[inline]
-    fn deep_clone(&self) -> RcMut<T> {
-        do self.with_borrow |x| {
-            // FIXME: #6497: should avoid freeze (slow)
-            unsafe { RcMut::new(x.deep_clone()) }
-        }
-    }
-}
-
-#[cfg(test)]
-mod test_rc_mut {
-    use super::*;
-
-    #[test]
-    fn test_clone() {
-        let x = rc_mut_from_owned(5);
-        let y = x.clone();
-        do x.with_mut_borrow |value| {
-            *value = 20;
-        }
-        do y.with_borrow |value| {
-            assert_eq!(*value, 20);
-        }
-    }
-
-    #[test]
-    fn test_deep_clone() {
-        let x = rc_mut_from_const(5);
-        let y = x.deep_clone();
-        do x.with_mut_borrow |value| {
-            *value = 20;
-        }
-        do y.with_borrow |value| {
-            assert_eq!(*value, 5);
-        }
-    }
-
-    #[test]
-    fn borrow_many() {
-        let x = rc_mut_from_owned(5);
-        let y = x.clone();
-
-        do x.with_borrow |a| {
-            assert_eq!(*a, 5);
-            do y.with_borrow |b| {
-                assert_eq!(*b, 5);
-                do x.with_borrow |c| {
-                    assert_eq!(*c, 5);
-                }
-            }
-        }
-    }
-
-    #[test]
-    fn modify() {
-        let x = rc_mut_from_const(5);
-        let y = x.clone();
-
-        do y.with_mut_borrow |a| {
-            assert_eq!(*a, 5);
-            *a = 6;
-        }
-
-        do x.with_borrow |a| {
-            assert_eq!(*a, 6);
-        }
-    }
-
-    #[test]
-    fn release_immutable() {
-        let x = rc_mut_from_owned(5);
-        do x.with_borrow |_| {}
-        do x.with_mut_borrow |_| {}
-    }
-
-    #[test]
-    fn release_mutable() {
-        let x = rc_mut_from_const(5);
-        do x.with_mut_borrow |_| {}
-        do x.with_borrow |_| {}
-    }
-
-    #[test]
-    #[should_fail]
-    fn frozen() {
-        let x = rc_mut_from_owned(5);
-        let y = x.clone();
-
-        do x.with_borrow |_| {
-            do y.with_mut_borrow |_| {
-            }
-        }
-    }
-
-    #[test]
-    #[should_fail]
-    fn mutable_dupe() {
-        let x = rc_mut_from_const(5);
-        let y = x.clone();
-
-        do x.with_mut_borrow |_| {
-            do y.with_mut_borrow |_| {
-            }
-        }
-    }
-
-    #[test]
-    #[should_fail]
-    fn mutable_freeze() {
-        let x = rc_mut_from_owned(5);
-        let y = x.clone();
-
-        do x.with_mut_borrow |_| {
-            do y.with_borrow |_| {
-            }
-        }
-    }
-
-    #[test]
-    #[should_fail]
-    fn restore_freeze() {
-        let x = rc_mut_from_const(5);
-        let y = x.clone();
-
-        do x.with_borrow |_| {
-            do x.with_borrow |_| {}
-            do y.with_mut_borrow |_| {}
-        }
-    }
-}
diff --git a/src/libstd/reflect.rs b/src/libstd/reflect.rs
new file mode 100644
index 00000000000..30f60dce041
--- /dev/null
+++ b/src/libstd/reflect.rs
@@ -0,0 +1,500 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+Runtime type reflection
+
+*/
+
+use intrinsic::{TyDesc, TyVisitor};
+use intrinsic::Opaque;
+use libc::c_void;
+use sys;
+use vec;
+
+/**
+ * Trait for visitor that wishes to reflect on data. To use this, create a
+ * struct that encapsulates the set of pointers you wish to walk through a
+ * data structure, and implement both `MovePtr` for it as well as `TyVisitor`;
+ * then build a MovePtrAdaptor wrapped around your struct.
+ */
+pub trait MovePtr {
+    fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void);
+    fn push_ptr(&self);
+    fn pop_ptr(&self);
+}
+
+/// Helper function for alignment calculation.
+#[inline(always)]
+pub fn align(size: uint, align: uint) -> uint {
+    ((size + align) - 1u) & !(align - 1u)
+}
+
+/// Adaptor to wrap around visitors implementing MovePtr.
+pub struct MovePtrAdaptor<V> {
+    inner: V
+}
+pub fn MovePtrAdaptor<V:TyVisitor + MovePtr>(v: V) -> MovePtrAdaptor<V> {
+    MovePtrAdaptor { inner: v }
+}
+
+pub impl<V:TyVisitor + MovePtr> MovePtrAdaptor<V> {
+    #[inline(always)]
+    fn bump(&self, sz: uint) {
+      do self.inner.move_ptr() |p| {
+            ((p as uint) + sz) as *c_void
+      };
+    }
+
+    #[inline(always)]
+    fn align(&self, a: uint) {
+      do self.inner.move_ptr() |p| {
+            align(p as uint, a) as *c_void
+      };
+    }
+
+    #[inline(always)]
+    fn align_to<T>(&self) {
+        self.align(sys::min_align_of::<T>());
+    }
+
+    #[inline(always)]
+    fn bump_past<T>(&self) {
+        self.bump(sys::size_of::<T>());
+    }
+}
+
+/// Abstract type-directed pointer-movement using the MovePtr trait
+impl<V:TyVisitor + MovePtr> TyVisitor for MovePtrAdaptor<V> {
+    fn visit_bot(&self) -> bool {
+        self.align_to::<()>();
+        if ! self.inner.visit_bot() { return false; }
+        self.bump_past::<()>();
+        true
+    }
+
+    fn visit_nil(&self) -> bool {
+        self.align_to::<()>();
+        if ! self.inner.visit_nil() { return false; }
+        self.bump_past::<()>();
+        true
+    }
+
+    fn visit_bool(&self) -> bool {
+        self.align_to::<bool>();
+        if ! self.inner.visit_bool() { return false; }
+        self.bump_past::<bool>();
+        true
+    }
+
+    fn visit_int(&self) -> bool {
+        self.align_to::<int>();
+        if ! self.inner.visit_int() { return false; }
+        self.bump_past::<int>();
+        true
+    }
+
+    fn visit_i8(&self) -> bool {
+        self.align_to::<i8>();
+        if ! self.inner.visit_i8() { return false; }
+        self.bump_past::<i8>();
+        true
+    }
+
+    fn visit_i16(&self) -> bool {
+        self.align_to::<i16>();
+        if ! self.inner.visit_i16() { return false; }
+        self.bump_past::<i16>();
+        true
+    }
+
+    fn visit_i32(&self) -> bool {
+        self.align_to::<i32>();
+        if ! self.inner.visit_i32() { return false; }
+        self.bump_past::<i32>();
+        true
+    }
+
+    fn visit_i64(&self) -> bool {
+        self.align_to::<i64>();
+        if ! self.inner.visit_i64() { return false; }
+        self.bump_past::<i64>();
+        true
+    }
+
+    fn visit_uint(&self) -> bool {
+        self.align_to::<uint>();
+        if ! self.inner.visit_uint() { return false; }
+        self.bump_past::<uint>();
+        true
+    }
+
+    fn visit_u8(&self) -> bool {
+        self.align_to::<u8>();
+        if ! self.inner.visit_u8() { return false; }
+        self.bump_past::<u8>();
+        true
+    }
+
+    fn visit_u16(&self) -> bool {
+        self.align_to::<u16>();
+        if ! self.inner.visit_u16() { return false; }
+        self.bump_past::<u16>();
+        true
+    }
+
+    fn visit_u32(&self) -> bool {
+        self.align_to::<u32>();
+        if ! self.inner.visit_u32() { return false; }
+        self.bump_past::<u32>();
+        true
+    }
+
+    fn visit_u64(&self) -> bool {
+        self.align_to::<u64>();
+        if ! self.inner.visit_u64() { return false; }
+        self.bump_past::<u64>();
+        true
+    }
+
+    fn visit_float(&self) -> bool {
+        self.align_to::<float>();
+        if ! self.inner.visit_float() { return false; }
+        self.bump_past::<float>();
+        true
+    }
+
+    fn visit_f32(&self) -> bool {
+        self.align_to::<f32>();
+        if ! self.inner.visit_f32() { return false; }
+        self.bump_past::<f32>();
+        true
+    }
+
+    fn visit_f64(&self) -> bool {
+        self.align_to::<f64>();
+        if ! self.inner.visit_f64() { return false; }
+        self.bump_past::<f64>();
+        true
+    }
+
+    fn visit_char(&self) -> bool {
+        self.align_to::<char>();
+        if ! self.inner.visit_char() { return false; }
+        self.bump_past::<char>();
+        true
+    }
+
+    fn visit_str(&self) -> bool {
+        self.align_to::<~str>();
+        if ! self.inner.visit_str() { return false; }
+        self.bump_past::<~str>();
+        true
+    }
+
+    fn visit_estr_box(&self) -> bool {
+        self.align_to::<@str>();
+        if ! self.inner.visit_estr_box() { return false; }
+        self.bump_past::<@str>();
+        true
+    }
+
+    fn visit_estr_uniq(&self) -> bool {
+        self.align_to::<~str>();
+        if ! self.inner.visit_estr_uniq() { return false; }
+        self.bump_past::<~str>();
+        true
+    }
+
+    fn visit_estr_slice(&self) -> bool {
+        self.align_to::<&'static str>();
+        if ! self.inner.visit_estr_slice() { return false; }
+        self.bump_past::<&'static str>();
+        true
+    }
+
+    fn visit_estr_fixed(&self, n: uint,
+                        sz: uint,
+                        align: uint) -> bool {
+        self.align(align);
+        if ! self.inner.visit_estr_fixed(n, sz, align) { return false; }
+        self.bump(sz);
+        true
+    }
+
+    fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<@u8>();
+        if ! self.inner.visit_box(mtbl, inner) { return false; }
+        self.bump_past::<@u8>();
+        true
+    }
+
+    fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<~u8>();
+        if ! self.inner.visit_uniq(mtbl, inner) { return false; }
+        self.bump_past::<~u8>();
+        true
+    }
+
+    fn visit_ptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<*u8>();
+        if ! self.inner.visit_ptr(mtbl, inner) { return false; }
+        self.bump_past::<*u8>();
+        true
+    }
+
+    fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<&'static u8>();
+        if ! self.inner.visit_rptr(mtbl, inner) { return false; }
+        self.bump_past::<&'static u8>();
+        true
+    }
+
+    fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<vec::UnboxedVecRepr>();
+        if ! self.inner.visit_vec(mtbl, inner) { return false; }
+        true
+    }
+
+    fn visit_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<~[u8]>();
+        if ! self.inner.visit_vec(mtbl, inner) { return false; }
+        self.bump_past::<~[u8]>();
+        true
+    }
+
+    fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<@[u8]>();
+        if ! self.inner.visit_evec_box(mtbl, inner) { return false; }
+        self.bump_past::<@[u8]>();
+        true
+    }
+
+    fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<~[u8]>();
+        if ! self.inner.visit_evec_uniq(mtbl, inner) { return false; }
+        self.bump_past::<~[u8]>();
+        true
+    }
+
+    fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.align_to::<&'static [u8]>();
+        if ! self.inner.visit_evec_slice(mtbl, inner) { return false; }
+        self.bump_past::<&'static [u8]>();
+        true
+    }
+
+    fn visit_evec_fixed(&self, n: uint, sz: uint, align: uint,
+                        mtbl: uint, inner: *TyDesc) -> bool {
+        self.align(align);
+        if ! self.inner.visit_evec_fixed(n, sz, align, mtbl, inner) {
+            return false;
+        }
+        self.bump(sz);
+        true
+    }
+
+    fn visit_enter_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+        self.align(align);
+        if ! self.inner.visit_enter_rec(n_fields, sz, align) { return false; }
+        true
+    }
+
+    fn visit_rec_field(&self, i: uint, name: &str,
+                       mtbl: uint, inner: *TyDesc) -> bool {
+        unsafe { self.align((*inner).align); }
+        if ! self.inner.visit_rec_field(i, name, mtbl, inner) {
+            return false;
+        }
+        unsafe { self.bump((*inner).size); }
+        true
+    }
+
+    fn visit_leave_rec(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+        if ! self.inner.visit_leave_rec(n_fields, sz, align) { return false; }
+        true
+    }
+
+    fn visit_enter_class(&self, n_fields: uint, sz: uint, align: uint)
+                      -> bool {
+        self.align(align);
+        if ! self.inner.visit_enter_class(n_fields, sz, align) {
+            return false;
+        }
+        true
+    }
+
+    fn visit_class_field(&self, i: uint, name: &str,
+                         mtbl: uint, inner: *TyDesc) -> bool {
+        unsafe { self.align((*inner).align); }
+        if ! self.inner.visit_class_field(i, name, mtbl, inner) {
+            return false;
+        }
+        unsafe { self.bump((*inner).size); }
+        true
+    }
+
+    fn visit_leave_class(&self, n_fields: uint, sz: uint, align: uint)
+                      -> bool {
+        if ! self.inner.visit_leave_class(n_fields, sz, align) {
+            return false;
+        }
+        true
+    }
+
+    fn visit_enter_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+        self.align(align);
+        if ! self.inner.visit_enter_tup(n_fields, sz, align) { return false; }
+        true
+    }
+
+    fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool {
+        unsafe { self.align((*inner).align); }
+        if ! self.inner.visit_tup_field(i, inner) { return false; }
+        unsafe { self.bump((*inner).size); }
+        true
+    }
+
+    fn visit_leave_tup(&self, n_fields: uint, sz: uint, align: uint) -> bool {
+        if ! self.inner.visit_leave_tup(n_fields, sz, align) { return false; }
+        true
+    }
+
+    fn visit_enter_fn(&self, purity: uint, proto: uint,
+                      n_inputs: uint, retstyle: uint) -> bool {
+        if ! self.inner.visit_enter_fn(purity, proto, n_inputs, retstyle) {
+            return false
+        }
+        true
+    }
+
+    fn visit_fn_input(&self, i: uint, mode: uint, inner: *TyDesc) -> bool {
+        if ! self.inner.visit_fn_input(i, mode, inner) { return false; }
+        true
+    }
+
+    fn visit_fn_output(&self, retstyle: uint, inner: *TyDesc) -> bool {
+        if ! self.inner.visit_fn_output(retstyle, inner) { return false; }
+        true
+    }
+
+    fn visit_leave_fn(&self, purity: uint, proto: uint,
+                      n_inputs: uint, retstyle: uint) -> bool {
+        if ! self.inner.visit_leave_fn(purity, proto, n_inputs, retstyle) {
+            return false;
+        }
+        true
+    }
+
+    fn visit_enter_enum(&self, n_variants: uint,
+                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
+                        sz: uint, align: uint)
+                     -> bool {
+        self.align(align);
+        if ! self.inner.visit_enter_enum(n_variants, get_disr, sz, align) {
+            return false;
+        }
+        true
+    }
+
+    fn visit_enter_enum_variant(&self, variant: uint,
+                                disr_val: int,
+                                n_fields: uint,
+                                name: &str) -> bool {
+        if ! self.inner.visit_enter_enum_variant(variant, disr_val,
+                                                 n_fields, name) {
+            return false;
+        }
+        true
+    }
+
+    fn visit_enum_variant_field(&self, i: uint, offset: uint, inner: *TyDesc) -> bool {
+        self.inner.push_ptr();
+        self.bump(offset);
+        if ! self.inner.visit_enum_variant_field(i, offset, inner) { return false; }
+        self.inner.pop_ptr();
+        true
+    }
+
+    fn visit_leave_enum_variant(&self, variant: uint,
+                                disr_val: int,
+                                n_fields: uint,
+                                name: &str) -> bool {
+        if ! self.inner.visit_leave_enum_variant(variant, disr_val,
+                                                 n_fields, name) {
+            return false;
+        }
+        true
+    }
+
+    fn visit_leave_enum(&self, n_variants: uint,
+                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
+                        sz: uint, align: uint) -> bool {
+        if ! self.inner.visit_leave_enum(n_variants, get_disr, sz, align) {
+            return false;
+        }
+        self.bump(sz);
+        true
+    }
+
+    fn visit_trait(&self) -> bool {
+        self.align_to::<@TyVisitor>();
+        if ! self.inner.visit_trait() { return false; }
+        self.bump_past::<@TyVisitor>();
+        true
+    }
+
+    fn visit_var(&self) -> bool {
+        if ! self.inner.visit_var() { return false; }
+        true
+    }
+
+    fn visit_var_integral(&self) -> bool {
+        if ! self.inner.visit_var_integral() { return false; }
+        true
+    }
+
+    fn visit_param(&self, i: uint) -> bool {
+        if ! self.inner.visit_param(i) { return false; }
+        true
+    }
+
+    fn visit_self(&self) -> bool {
+        self.align_to::<&'static u8>();
+        if ! self.inner.visit_self() { return false; }
+        self.align_to::<&'static u8>();
+        true
+    }
+
+    fn visit_type(&self) -> bool {
+        if ! self.inner.visit_type() { return false; }
+        true
+    }
+
+    fn visit_opaque_box(&self) -> bool {
+        self.align_to::<@u8>();
+        if ! self.inner.visit_opaque_box() { return false; }
+        self.bump_past::<@u8>();
+        true
+    }
+
+    fn visit_constr(&self, inner: *TyDesc) -> bool {
+        if ! self.inner.visit_constr(inner) { return false; }
+        true
+    }
+
+    fn visit_closure_ptr(&self, ck: uint) -> bool {
+        self.align_to::<@fn()>();
+        if ! self.inner.visit_closure_ptr(ck) { return false; }
+        self.bump_past::<@fn()>();
+        true
+    }
+}
diff --git a/src/libstd/repr.rs b/src/libstd/repr.rs
new file mode 100644
index 00000000000..a05009e375c
--- /dev/null
+++ b/src/libstd/repr.rs
@@ -0,0 +1,639 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+More runtime type reflection
+
+*/
+
+use cast::transmute;
+use char;
+use intrinsic;
+use intrinsic::{TyDesc, TyVisitor, visit_tydesc};
+use intrinsic::Opaque;
+use io::{Writer, WriterUtil};
+use libc::c_void;
+use managed;
+use ptr;
+use reflect;
+use reflect::{MovePtr, align};
+use str::StrSlice;
+use to_str::ToStr;
+use vec::raw::{VecRepr, SliceRepr};
+use vec;
+use vec::{OwnedVector, UnboxedVecRepr};
+
+#[cfg(test)] use io;
+
+pub use managed::raw::BoxRepr;
+
+/// Helpers
+
+trait EscapedCharWriter {
+    fn write_escaped_char(&self, ch: char);
+}
+
+impl EscapedCharWriter for @Writer {
+    fn write_escaped_char(&self, ch: char) {
+        match ch {
+            '\t' => self.write_str("\\t"),
+            '\r' => self.write_str("\\r"),
+            '\n' => self.write_str("\\n"),
+            '\\' => self.write_str("\\\\"),
+            '\'' => self.write_str("\\'"),
+            '"' => self.write_str("\\\""),
+            '\x20'..'\x7e' => self.write_char(ch),
+            _ => {
+                // FIXME #4423: This is inefficient because it requires a
+                // malloc.
+                self.write_str(char::escape_unicode(ch))
+            }
+        }
+    }
+}
+
+/// Representations
+
+trait Repr {
+    fn write_repr(&self, writer: @Writer);
+}
+
+impl Repr for () {
+    fn write_repr(&self, writer: @Writer) { writer.write_str("()"); }
+}
+
+impl Repr for bool {
+    fn write_repr(&self, writer: @Writer) {
+        writer.write_str(if *self { "true" } else { "false" })
+    }
+}
+
+impl Repr for int {
+    fn write_repr(&self, writer: @Writer) { writer.write_int(*self); }
+}
+impl Repr for i8 {
+    fn write_repr(&self, writer: @Writer) { writer.write_int(*self as int); }
+}
+impl Repr for i16 {
+    fn write_repr(&self, writer: @Writer) { writer.write_int(*self as int); }
+}
+impl Repr for i32 {
+    fn write_repr(&self, writer: @Writer) { writer.write_int(*self as int); }
+}
+impl Repr for i64 {
+    // FIXME #4424: This can lose precision.
+    fn write_repr(&self, writer: @Writer) { writer.write_int(*self as int); }
+}
+
+impl Repr for uint {
+    fn write_repr(&self, writer: @Writer) { writer.write_uint(*self); }
+}
+impl Repr for u8 {
+    fn write_repr(&self, writer: @Writer) {
+        writer.write_uint(*self as uint);
+    }
+}
+impl Repr for u16 {
+    fn write_repr(&self, writer: @Writer) {
+        writer.write_uint(*self as uint);
+    }
+}
+impl Repr for u32 {
+    fn write_repr(&self, writer: @Writer) {
+        writer.write_uint(*self as uint);
+    }
+}
+impl Repr for u64 {
+    // FIXME #4424: This can lose precision.
+    fn write_repr(&self, writer: @Writer) {
+        writer.write_uint(*self as uint);
+    }
+}
+
+impl Repr for float {
+    // FIXME #4423: This mallocs.
+    fn write_repr(&self, writer: @Writer) { writer.write_str(self.to_str()); }
+}
+impl Repr for f32 {
+    // FIXME #4423 This mallocs.
+    fn write_repr(&self, writer: @Writer) { writer.write_str(self.to_str()); }
+}
+impl Repr for f64 {
+    // FIXME #4423: This mallocs.
+    fn write_repr(&self, writer: @Writer) { writer.write_str(self.to_str()); }
+}
+
+impl Repr for char {
+    fn write_repr(&self, writer: @Writer) { writer.write_char(*self); }
+}
+
+
+// New implementation using reflect::MovePtr
+
+enum VariantState {
+    SearchingFor(int),
+    Matched,
+    AlreadyFound
+}
+
+pub struct ReprVisitor {
+    ptr: @mut *c_void,
+    ptr_stk: @mut ~[*c_void],
+    var_stk: @mut ~[VariantState],
+    writer: @Writer
+}
+pub fn ReprVisitor(ptr: *c_void, writer: @Writer) -> ReprVisitor {
+    ReprVisitor {
+        ptr: @mut ptr,
+        ptr_stk: @mut ~[],
+        var_stk: @mut ~[],
+        writer: writer,
+    }
+}
+
+impl MovePtr for ReprVisitor {
+    #[inline(always)]
+    fn move_ptr(&self, adjustment: &fn(*c_void) -> *c_void) {
+        *self.ptr = adjustment(*self.ptr);
+    }
+    fn push_ptr(&self) {
+        self.ptr_stk.push(*self.ptr);
+    }
+    fn pop_ptr(&self) {
+        *self.ptr = self.ptr_stk.pop();
+    }
+}
+
+pub impl ReprVisitor {
+
+    // Various helpers for the TyVisitor impl
+
+    #[inline(always)]
+    fn get<T>(&self, f: &fn(&T)) -> bool {
+        unsafe {
+            f(transmute::<*c_void,&T>(*self.ptr));
+        }
+        true
+    }
+
+    #[inline(always)]
+    fn visit_inner(&self, inner: *TyDesc) -> bool {
+        self.visit_ptr_inner(*self.ptr, inner)
+    }
+
+    #[inline(always)]
+    fn visit_ptr_inner(&self, ptr: *c_void, inner: *TyDesc) -> bool {
+        unsafe {
+            let u = ReprVisitor(ptr, self.writer);
+            let v = reflect::MovePtrAdaptor(u);
+            visit_tydesc(inner, @v as @TyVisitor);
+            true
+        }
+    }
+
+    #[inline(always)]
+    fn write<T:Repr>(&self) -> bool {
+        do self.get |v:&T| {
+            v.write_repr(self.writer);
+        }
+    }
+
+    fn write_escaped_slice(&self, slice: &str) {
+        self.writer.write_char('"');
+        for slice.each_char |ch| {
+            self.writer.write_escaped_char(ch);
+        }
+        self.writer.write_char('"');
+    }
+
+    fn write_mut_qualifier(&self, mtbl: uint) {
+        if mtbl == 0 {
+            self.writer.write_str("mut ");
+        } else if mtbl == 1 {
+            // skip, this is ast::m_imm
+        } else {
+            assert_eq!(mtbl, 2);
+            self.writer.write_str("const ");
+        }
+    }
+
+    fn write_vec_range(&self, mtbl: uint, ptr: *u8, len: uint,
+                       inner: *TyDesc) -> bool {
+        let mut p = ptr;
+        let end = ptr::offset(p, len);
+        let (sz, al) = unsafe { ((*inner).size, (*inner).align) };
+        self.writer.write_char('[');
+        let mut first = true;
+        while (p as uint) < (end as uint) {
+            if first {
+                first = false;
+            } else {
+                self.writer.write_str(", ");
+            }
+            self.write_mut_qualifier(mtbl);
+            self.visit_ptr_inner(p as *c_void, inner);
+            p = align(ptr::offset(p, sz) as uint, al) as *u8;
+        }
+        self.writer.write_char(']');
+        true
+    }
+
+    fn write_unboxed_vec_repr(&self, mtbl: uint, v: &UnboxedVecRepr,
+                              inner: *TyDesc) -> bool {
+        self.write_vec_range(mtbl, ptr::to_unsafe_ptr(&v.data),
+                             v.fill, inner)
+    }
+
+
+}
+
+impl TyVisitor for ReprVisitor {
+    fn visit_bot(&self) -> bool {
+        self.writer.write_str("!");
+        true
+    }
+    fn visit_nil(&self) -> bool { self.write::<()>() }
+    fn visit_bool(&self) -> bool { self.write::<bool>() }
+    fn visit_int(&self) -> bool { self.write::<int>() }
+    fn visit_i8(&self) -> bool { self.write::<i8>() }
+    fn visit_i16(&self) -> bool { self.write::<i16>() }
+    fn visit_i32(&self) -> bool { self.write::<i32>()  }
+    fn visit_i64(&self) -> bool { self.write::<i64>() }
+
+    fn visit_uint(&self) -> bool { self.write::<uint>() }
+    fn visit_u8(&self) -> bool { self.write::<u8>() }
+    fn visit_u16(&self) -> bool { self.write::<u16>() }
+    fn visit_u32(&self) -> bool { self.write::<u32>() }
+    fn visit_u64(&self) -> bool { self.write::<u64>() }
+
+    fn visit_float(&self) -> bool { self.write::<float>() }
+    fn visit_f32(&self) -> bool { self.write::<f32>() }
+    fn visit_f64(&self) -> bool { self.write::<f64>() }
+
+    fn visit_char(&self) -> bool {
+        do self.get::<char> |&ch| {
+            self.writer.write_char('\'');
+            self.writer.write_escaped_char(ch);
+            self.writer.write_char('\'');
+        }
+    }
+
+    // Type no longer exists, vestigial function.
+    fn visit_str(&self) -> bool { fail!(); }
+
+    fn visit_estr_box(&self) -> bool {
+        do self.get::<@str> |s| {
+            self.writer.write_char('@');
+            self.write_escaped_slice(*s);
+        }
+    }
+    fn visit_estr_uniq(&self) -> bool {
+        do self.get::<~str> |s| {
+            self.writer.write_char('~');
+            self.write_escaped_slice(*s);
+        }
+    }
+    fn visit_estr_slice(&self) -> bool {
+        do self.get::<&str> |s| {
+            self.write_escaped_slice(*s);
+        }
+    }
+
+    // Type no longer exists, vestigial function.
+    fn visit_estr_fixed(&self, _n: uint, _sz: uint,
+                        _align: uint) -> bool { fail!(); }
+
+    fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.writer.write_char('@');
+        self.write_mut_qualifier(mtbl);
+        do self.get::<&managed::raw::BoxRepr> |b| {
+            let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
+            self.visit_ptr_inner(p, inner);
+        }
+    }
+
+    fn visit_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.writer.write_char('~');
+        self.write_mut_qualifier(mtbl);
+        do self.get::<&managed::raw::BoxRepr> |b| {
+            let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
+            self.visit_ptr_inner(p, inner);
+        }
+    }
+
+    fn visit_ptr(&self, _mtbl: uint, _inner: *TyDesc) -> bool {
+        do self.get::<*c_void> |p| {
+            self.writer.write_str(fmt!("(0x%x as *())",
+                                       *p as uint));
+        }
+    }
+
+    fn visit_rptr(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        self.writer.write_char('&');
+        self.write_mut_qualifier(mtbl);
+        do self.get::<*c_void> |p| {
+            self.visit_ptr_inner(*p, inner);
+        }
+    }
+
+    // Type no longer exists, vestigial function.
+    fn visit_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { fail!(); }
+
+
+    fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<vec::UnboxedVecRepr> |b| {
+            self.write_unboxed_vec_repr(mtbl, b, inner);
+        }
+    }
+
+    fn visit_evec_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<&VecRepr> |b| {
+            self.writer.write_char('@');
+            self.write_unboxed_vec_repr(mtbl, &b.unboxed, inner);
+        }
+    }
+
+    fn visit_evec_uniq(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<&VecRepr> |b| {
+            self.writer.write_char('~');
+            self.write_unboxed_vec_repr(mtbl, &b.unboxed, inner);
+        }
+    }
+
+    fn visit_evec_slice(&self, mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<SliceRepr> |s| {
+            self.writer.write_char('&');
+            self.write_vec_range(mtbl, s.data, s.len, inner);
+        }
+    }
+
+    fn visit_evec_fixed(&self, _n: uint, sz: uint, _align: uint,
+                        mtbl: uint, inner: *TyDesc) -> bool {
+        do self.get::<u8> |b| {
+            self.write_vec_range(mtbl, ptr::to_unsafe_ptr(b), sz, inner);
+        }
+    }
+
+    fn visit_enter_rec(&self, _n_fields: uint,
+                       _sz: uint, _align: uint) -> bool {
+        self.writer.write_char('{');
+        true
+    }
+
+    fn visit_rec_field(&self, i: uint, name: &str,
+                       mtbl: uint, inner: *TyDesc) -> bool {
+        if i != 0 {
+            self.writer.write_str(", ");
+        }
+        self.write_mut_qualifier(mtbl);
+        self.writer.write_str(name);
+        self.writer.write_str(": ");
+        self.visit_inner(inner);
+        true
+    }
+
+    fn visit_leave_rec(&self, _n_fields: uint,
+                       _sz: uint, _align: uint) -> bool {
+        self.writer.write_char('}');
+        true
+    }
+
+    fn visit_enter_class(&self, _n_fields: uint,
+                         _sz: uint, _align: uint) -> bool {
+        self.writer.write_char('{');
+        true
+    }
+    fn visit_class_field(&self, i: uint, name: &str,
+                         mtbl: uint, inner: *TyDesc) -> bool {
+        if i != 0 {
+            self.writer.write_str(", ");
+        }
+        self.write_mut_qualifier(mtbl);
+        self.writer.write_str(name);
+        self.writer.write_str(": ");
+        self.visit_inner(inner);
+        true
+    }
+    fn visit_leave_class(&self, _n_fields: uint,
+                         _sz: uint, _align: uint) -> bool {
+        self.writer.write_char('}');
+        true
+    }
+
+    fn visit_enter_tup(&self, _n_fields: uint,
+                       _sz: uint, _align: uint) -> bool {
+        self.writer.write_char('(');
+        true
+    }
+    fn visit_tup_field(&self, i: uint, inner: *TyDesc) -> bool {
+        if i != 0 {
+            self.writer.write_str(", ");
+        }
+        self.visit_inner(inner);
+        true
+    }
+    fn visit_leave_tup(&self, _n_fields: uint,
+                       _sz: uint, _align: uint) -> bool {
+        if _n_fields == 1 {
+            self.writer.write_char(',');
+        }
+        self.writer.write_char(')');
+        true
+    }
+
+    fn visit_enter_enum(&self,
+                        _n_variants: uint,
+                        get_disr: extern unsafe fn(ptr: *Opaque) -> int,
+                        _sz: uint,
+                        _align: uint) -> bool {
+        let var_stk: &mut ~[VariantState] = self.var_stk;
+        let disr = unsafe {
+            get_disr(transmute(*self.ptr))
+        };
+        var_stk.push(SearchingFor(disr));
+        true
+    }
+
+    fn visit_enter_enum_variant(&self, _variant: uint,
+                                disr_val: int,
+                                n_fields: uint,
+                                name: &str) -> bool {
+        let mut write = false;
+        match self.var_stk.pop() {
+            SearchingFor(sought) => {
+                if disr_val == sought {
+                    self.var_stk.push(Matched);
+                    write = true;
+                } else {
+                    self.var_stk.push(SearchingFor(sought));
+                }
+            }
+            Matched | AlreadyFound => {
+                self.var_stk.push(AlreadyFound);
+            }
+        }
+
+        if write {
+            self.writer.write_str(name);
+            if n_fields > 0 {
+                self.writer.write_char('(');
+            }
+        }
+        true
+    }
+
+    fn visit_enum_variant_field(&self,
+                                i: uint,
+                                _offset: uint,
+                                inner: *TyDesc)
+                                -> bool {
+        match self.var_stk[vec::uniq_len(&const *self.var_stk) - 1] {
+            Matched => {
+                if i != 0 {
+                    self.writer.write_str(", ");
+                }
+                if ! self.visit_inner(inner) {
+                    return false;
+                }
+            }
+            _ => ()
+        }
+        true
+    }
+
+    fn visit_leave_enum_variant(&self, _variant: uint,
+                                _disr_val: int,
+                                n_fields: uint,
+                                _name: &str) -> bool {
+        match self.var_stk[vec::uniq_len(&const *self.var_stk) - 1] {
+            Matched => {
+                if n_fields > 0 {
+                    self.writer.write_char(')');
+                }
+            }
+            _ => ()
+        }
+        true
+    }
+
+    fn visit_leave_enum(&self,
+                        _n_variants: uint,
+                        _get_disr: extern unsafe fn(ptr: *Opaque) -> int,
+                        _sz: uint,
+                        _align: uint)
+                        -> bool {
+        let var_stk: &mut ~[VariantState] = self.var_stk;
+        match var_stk.pop() {
+            SearchingFor(*) => fail!("enum value matched no variant"),
+            _ => true
+        }
+    }
+
+    fn visit_enter_fn(&self, _purity: uint, _proto: uint,
+                      _n_inputs: uint, _retstyle: uint) -> bool { true }
+    fn visit_fn_input(&self, _i: uint, _mode: uint, _inner: *TyDesc) -> bool {
+        true
+    }
+    fn visit_fn_output(&self, _retstyle: uint, _inner: *TyDesc) -> bool {
+        true
+    }
+    fn visit_leave_fn(&self, _purity: uint, _proto: uint,
+                      _n_inputs: uint, _retstyle: uint) -> bool { true }
+
+
+    fn visit_trait(&self) -> bool { true }
+    fn visit_var(&self) -> bool { true }
+    fn visit_var_integral(&self) -> bool { true }
+    fn visit_param(&self, _i: uint) -> bool { true }
+    fn visit_self(&self) -> bool { true }
+    fn visit_type(&self) -> bool { true }
+
+    fn visit_opaque_box(&self) -> bool {
+        self.writer.write_char('@');
+        do self.get::<&managed::raw::BoxRepr> |b| {
+            let p = ptr::to_unsafe_ptr(&b.data) as *c_void;
+            self.visit_ptr_inner(p, b.header.type_desc);
+        }
+    }
+
+    // Type no longer exists, vestigial function.
+    fn visit_constr(&self, _inner: *TyDesc) -> bool { fail!(); }
+
+    fn visit_closure_ptr(&self, _ck: uint) -> bool { true }
+}
+
+pub fn write_repr<T>(writer: @Writer, object: &T) {
+    unsafe {
+        let ptr = ptr::to_unsafe_ptr(object) as *c_void;
+        let tydesc = intrinsic::get_tydesc::<T>();
+        let u = ReprVisitor(ptr, writer);
+        let v = reflect::MovePtrAdaptor(u);
+        visit_tydesc(tydesc, @v as @TyVisitor)
+    }
+}
+
+#[cfg(test)]
+struct P {a: int, b: float}
+
+#[test]
+fn test_repr() {
+
+    fn exact_test<T>(t: &T, e:&str) {
+        let s : &str = io::with_str_writer(|w| write_repr(w, t));
+        if s != e {
+            error!("expected '%s', got '%s'",
+                   e, s);
+        }
+        assert_eq!(s, e);
+    }
+
+    exact_test(&10, "10");
+    exact_test(&true, "true");
+    exact_test(&false, "false");
+    exact_test(&1.234, "1.234");
+    exact_test(&(&"hello"), "\"hello\"");
+    exact_test(&(@"hello"), "@\"hello\"");
+    exact_test(&(~"he\u10f3llo"), "~\"he\\u10f3llo\"");
+
+    // FIXME #4210: the mut fields are a bit off here.
+    exact_test(&(@10), "@10");
+    exact_test(&(@mut 10), "@10");
+    exact_test(&(~10), "~10");
+    exact_test(&(&10), "&10");
+    let mut x = 10;
+    exact_test(&(&mut x), "&mut 10");
+
+    exact_test(&(1,), "(1,)");
+    exact_test(&(@[1,2,3,4,5,6,7,8]),
+               "@[1, 2, 3, 4, 5, 6, 7, 8]");
+    exact_test(&(@[1u8,2u8,3u8,4u8]),
+               "@[1, 2, 3, 4]");
+    exact_test(&(@["hi", "there"]),
+               "@[\"hi\", \"there\"]");
+    exact_test(&(~["hi", "there"]),
+               "~[\"hi\", \"there\"]");
+    exact_test(&(&["hi", "there"]),
+               "&[\"hi\", \"there\"]");
+    exact_test(&(P{a:10, b:1.234}),
+               "{a: 10, b: 1.234}");
+    exact_test(&(@P{a:10, b:1.234}),
+               "@{a: 10, b: 1.234}");
+    exact_test(&(~P{a:10, b:1.234}),
+               "~{a: 10, b: 1.234}");
+    exact_test(&(10_u8, ~"hello"),
+               "(10, ~\"hello\")");
+    exact_test(&(10_u16, ~"hello"),
+               "(10, ~\"hello\")");
+    exact_test(&(10_u32, ~"hello"),
+               "(10, ~\"hello\")");
+    exact_test(&(10_u64, ~"hello"),
+               "(10, ~\"hello\")");
+}
diff --git a/src/libstd/result.rs b/src/libstd/result.rs
new file mode 100644
index 00000000000..cda2fe13e37
--- /dev/null
+++ b/src/libstd/result.rs
@@ -0,0 +1,456 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! A type representing either success or failure
+
+// NB: transitionary, de-mode-ing.
+
+use cmp::Eq;
+use either;
+use either::Either;
+use kinds::Copy;
+use option::{None, Option, Some};
+use old_iter::BaseIter;
+use vec;
+use vec::OwnedVector;
+
+/// The result type
+#[deriving(Clone, Eq)]
+pub enum Result<T, U> {
+    /// Contains the successful result value
+    Ok(T),
+    /// Contains the error value
+    Err(U)
+}
+
+/**
+ * Get the value out of a successful result
+ *
+ * # Failure
+ *
+ * If the result is an error
+ */
+#[inline(always)]
+pub fn get<T:Copy,U>(res: &Result<T, U>) -> T {
+    match *res {
+      Ok(copy t) => t,
+      Err(ref the_err) =>
+        fail!("get called on error result: %?", *the_err)
+    }
+}
+
+/**
+ * Get a reference to the value out of a successful result
+ *
+ * # Failure
+ *
+ * If the result is an error
+ */
+#[inline(always)]
+pub fn get_ref<'a, T, U>(res: &'a Result<T, U>) -> &'a T {
+    match *res {
+        Ok(ref t) => t,
+        Err(ref the_err) =>
+            fail!("get_ref called on error result: %?", *the_err)
+    }
+}
+
+/**
+ * Get the value out of an error result
+ *
+ * # Failure
+ *
+ * If the result is not an error
+ */
+#[inline(always)]
+pub fn get_err<T, U: Copy>(res: &Result<T, U>) -> U {
+    match *res {
+      Err(copy u) => u,
+      Ok(_) => fail!("get_err called on ok result")
+    }
+}
+
+/// Returns true if the result is `ok`
+#[inline(always)]
+pub fn is_ok<T, U>(res: &Result<T, U>) -> bool {
+    match *res {
+      Ok(_) => true,
+      Err(_) => false
+    }
+}
+
+/// Returns true if the result is `err`
+#[inline(always)]
+pub fn is_err<T, U>(res: &Result<T, U>) -> bool {
+    !is_ok(res)
+}
+
+/**
+ * Convert to the `either` type
+ *
+ * `ok` result variants are converted to `either::right` variants, `err`
+ * result variants are converted to `either::left`.
+ */
+#[inline(always)]
+pub fn to_either<T:Copy,U:Copy>(res: &Result<U, T>)
+    -> Either<T, U> {
+    match *res {
+      Ok(copy res) => either::Right(res),
+      Err(copy fail_) => either::Left(fail_)
+    }
+}
+
+/**
+ * Call a function based on a previous result
+ *
+ * If `res` is `ok` then the value is extracted and passed to `op` whereupon
+ * `op`s result is returned. if `res` is `err` then it is immediately
+ * returned. This function can be used to compose the results of two
+ * functions.
+ *
+ * Example:
+ *
+ *     let res = chain(read_file(file)) { |buf|
+ *         ok(parse_bytes(buf))
+ *     }
+ */
+#[inline(always)]
+pub fn chain<T, U, V>(res: Result<T, V>, op: &fn(T)
+    -> Result<U, V>) -> Result<U, V> {
+    match res {
+        Ok(t) => op(t),
+        Err(e) => Err(e)
+    }
+}
+
+/**
+ * Call a function based on a previous result
+ *
+ * If `res` is `err` then the value is extracted and passed to `op`
+ * whereupon `op`s result is returned. if `res` is `ok` then it is
+ * immediately returned.  This function can be used to pass through a
+ * successful result while handling an error.
+ */
+#[inline(always)]
+pub fn chain_err<T, U, V>(
+    res: Result<T, V>,
+    op: &fn(t: V) -> Result<T, U>)
+    -> Result<T, U> {
+    match res {
+      Ok(t) => Ok(t),
+      Err(v) => op(v)
+    }
+}
+
+/**
+ * Call a function based on a previous result
+ *
+ * If `res` is `ok` then the value is extracted and passed to `op` whereupon
+ * `op`s result is returned. if `res` is `err` then it is immediately
+ * returned. This function can be used to compose the results of two
+ * functions.
+ *
+ * Example:
+ *
+ *     iter(read_file(file)) { |buf|
+ *         print_buf(buf)
+ *     }
+ */
+#[inline(always)]
+pub fn iter<T, E>(res: &Result<T, E>, f: &fn(&T)) {
+    match *res {
+      Ok(ref t) => f(t),
+      Err(_) => ()
+    }
+}
+
+/**
+ * Call a function based on a previous result
+ *
+ * If `res` is `err` then the value is extracted and passed to `op` whereupon
+ * `op`s result is returned. if `res` is `ok` then it is immediately returned.
+ * This function can be used to pass through a successful result while
+ * handling an error.
+ */
+#[inline(always)]
+pub fn iter_err<T, E>(res: &Result<T, E>, f: &fn(&E)) {
+    match *res {
+      Ok(_) => (),
+      Err(ref e) => f(e)
+    }
+}
+
+/**
+ * Call a function based on a previous result
+ *
+ * If `res` is `ok` then the value is extracted and passed to `op` whereupon
+ * `op`s result is wrapped in `ok` and returned. if `res` is `err` then it is
+ * immediately returned.  This function can be used to compose the results of
+ * two functions.
+ *
+ * Example:
+ *
+ *     let res = map(read_file(file)) { |buf|
+ *         parse_bytes(buf)
+ *     }
+ */
+#[inline(always)]
+pub fn map<T, E: Copy, U: Copy>(res: &Result<T, E>, op: &fn(&T) -> U)
+  -> Result<U, E> {
+    match *res {
+      Ok(ref t) => Ok(op(t)),
+      Err(copy e) => Err(e)
+    }
+}
+
+/**
+ * Call a function based on a previous result
+ *
+ * If `res` is `err` then the value is extracted and passed to `op` whereupon
+ * `op`s result is wrapped in an `err` and returned. if `res` is `ok` then it
+ * is immediately returned.  This function can be used to pass through a
+ * successful result while handling an error.
+ */
+#[inline(always)]
+pub fn map_err<T:Copy,E,F:Copy>(res: &Result<T, E>, op: &fn(&E) -> F)
+  -> Result<T, F> {
+    match *res {
+      Ok(copy t) => Ok(t),
+      Err(ref e) => Err(op(e))
+    }
+}
+
+pub impl<T, E> Result<T, E> {
+    #[inline(always)]
+    fn get_ref<'a>(&'a self) -> &'a T { get_ref(self) }
+
+    #[inline(always)]
+    fn is_ok(&self) -> bool { is_ok(self) }
+
+    #[inline(always)]
+    fn is_err(&self) -> bool { is_err(self) }
+
+    #[inline(always)]
+    fn iter(&self, f: &fn(&T)) { iter(self, f) }
+
+    #[inline(always)]
+    fn iter_err(&self, f: &fn(&E)) { iter_err(self, f) }
+
+    #[inline(always)]
+    fn unwrap(self) -> T { unwrap(self) }
+
+    #[inline(always)]
+    fn unwrap_err(self) -> E { unwrap_err(self) }
+
+    #[inline(always)]
+    fn chain<U>(self, op: &fn(T) -> Result<U,E>) -> Result<U,E> {
+        chain(self, op)
+    }
+
+    #[inline(always)]
+    fn chain_err<F>(self, op: &fn(E) -> Result<T,F>) -> Result<T,F> {
+        chain_err(self, op)
+    }
+}
+
+pub impl<T:Copy,E> Result<T, E> {
+    #[inline(always)]
+    fn get(&self) -> T { get(self) }
+
+    #[inline(always)]
+    fn map_err<F:Copy>(&self, op: &fn(&E) -> F) -> Result<T,F> {
+        map_err(self, op)
+    }
+}
+
+pub impl<T, E: Copy> Result<T, E> {
+    #[inline(always)]
+    fn get_err(&self) -> E { get_err(self) }
+
+    #[inline(always)]
+    fn map<U:Copy>(&self, op: &fn(&T) -> U) -> Result<U,E> {
+        map(self, op)
+    }
+}
+
+/**
+ * Maps each element in the vector `ts` using the operation `op`.  Should an
+ * error occur, no further mappings are performed and the error is returned.
+ * Should no error occur, a vector containing the result of each map is
+ * returned.
+ *
+ * Here is an example which increments every integer in a vector,
+ * checking for overflow:
+ *
+ *     fn inc_conditionally(x: uint) -> result<uint,str> {
+ *         if x == uint::max_value { return err("overflow"); }
+ *         else { return ok(x+1u); }
+ *     }
+ *     map(~[1u, 2u, 3u], inc_conditionally).chain {|incd|
+ *         assert!(incd == ~[2u, 3u, 4u]);
+ *     }
+ */
+#[inline(always)]
+pub fn map_vec<T,U:Copy,V:Copy>(
+    ts: &[T], op: &fn(&T) -> Result<V,U>) -> Result<~[V],U> {
+
+    let mut vs: ~[V] = vec::with_capacity(vec::len(ts));
+    for ts.each |t| {
+        match op(t) {
+          Ok(copy v) => vs.push(v),
+          Err(copy u) => return Err(u)
+        }
+    }
+    return Ok(vs);
+}
+
+#[inline(always)]
+pub fn map_opt<T,U:Copy,V:Copy>(
+    o_t: &Option<T>, op: &fn(&T) -> Result<V,U>) -> Result<Option<V>,U> {
+
+    match *o_t {
+      None => Ok(None),
+      Some(ref t) => match op(t) {
+        Ok(copy v) => Ok(Some(v)),
+        Err(copy e) => Err(e)
+      }
+    }
+}
+
+/**
+ * Same as map, but it operates over two parallel vectors.
+ *
+ * A precondition is used here to ensure that the vectors are the same
+ * length.  While we do not often use preconditions in the standard
+ * library, a precondition is used here because result::t is generally
+ * used in 'careful' code contexts where it is both appropriate and easy
+ * to accommodate an error like the vectors being of different lengths.
+ */
+#[inline(always)]
+pub fn map_vec2<S,T,U:Copy,V:Copy>(ss: &[S], ts: &[T],
+                op: &fn(&S,&T) -> Result<V,U>) -> Result<~[V],U> {
+
+    assert!(vec::same_length(ss, ts));
+    let n = vec::len(ts);
+    let mut vs = vec::with_capacity(n);
+    let mut i = 0u;
+    while i < n {
+        match op(&ss[i],&ts[i]) {
+          Ok(copy v) => vs.push(v),
+          Err(copy u) => return Err(u)
+        }
+        i += 1u;
+    }
+    return Ok(vs);
+}
+
+/**
+ * Applies op to the pairwise elements from `ss` and `ts`, aborting on
+ * error.  This could be implemented using `map_zip()` but it is more efficient
+ * on its own as no result vector is built.
+ */
+#[inline(always)]
+pub fn iter_vec2<S,T,U:Copy>(ss: &[S], ts: &[T],
+                         op: &fn(&S,&T) -> Result<(),U>) -> Result<(),U> {
+
+    assert!(vec::same_length(ss, ts));
+    let n = vec::len(ts);
+    let mut i = 0u;
+    while i < n {
+        match op(&ss[i],&ts[i]) {
+          Ok(()) => (),
+          Err(copy u) => return Err(u)
+        }
+        i += 1u;
+    }
+    return Ok(());
+}
+
+/// Unwraps a result, assuming it is an `ok(T)`
+#[inline(always)]
+pub fn unwrap<T, U>(res: Result<T, U>) -> T {
+    match res {
+      Ok(t) => t,
+      Err(_) => fail!("unwrap called on an err result")
+    }
+}
+
+/// Unwraps a result, assuming it is an `err(U)`
+#[inline(always)]
+pub fn unwrap_err<T, U>(res: Result<T, U>) -> U {
+    match res {
+      Err(u) => u,
+      Ok(_) => fail!("unwrap called on an ok result")
+    }
+}
+
+#[cfg(test)]
+#[allow(non_implicitly_copyable_typarams)]
+mod tests {
+    use result::{Err, Ok, Result, chain, get, get_err};
+    use result;
+
+    pub fn op1() -> result::Result<int, ~str> { result::Ok(666) }
+
+    pub fn op2(i: int) -> result::Result<uint, ~str> {
+        result::Ok(i as uint + 1u)
+    }
+
+    pub fn op3() -> result::Result<int, ~str> { result::Err(~"sadface") }
+
+    #[test]
+    pub fn chain_success() {
+        assert_eq!(get(&chain(op1(), op2)), 667u);
+    }
+
+    #[test]
+    pub fn chain_failure() {
+        assert_eq!(get_err(&chain(op3(), op2)), ~"sadface");
+    }
+
+    #[test]
+    pub fn test_impl_iter() {
+        let mut valid = false;
+        Ok::<~str, ~str>(~"a").iter(|_x| valid = true);
+        assert!(valid);
+
+        Err::<~str, ~str>(~"b").iter(|_x| valid = false);
+        assert!(valid);
+    }
+
+    #[test]
+    pub fn test_impl_iter_err() {
+        let mut valid = true;
+        Ok::<~str, ~str>(~"a").iter_err(|_x| valid = false);
+        assert!(valid);
+
+        valid = false;
+        Err::<~str, ~str>(~"b").iter_err(|_x| valid = true);
+        assert!(valid);
+    }
+
+    #[test]
+    pub fn test_impl_map() {
+        assert_eq!(Ok::<~str, ~str>(~"a").map(|_x| ~"b"), Ok(~"b"));
+        assert_eq!(Err::<~str, ~str>(~"a").map(|_x| ~"b"), Err(~"a"));
+    }
+
+    #[test]
+    pub fn test_impl_map_err() {
+        assert_eq!(Ok::<~str, ~str>(~"a").map_err(|_x| ~"b"), Ok(~"a"));
+        assert_eq!(Err::<~str, ~str>(~"a").map_err(|_x| ~"b"), Err(~"b"));
+    }
+
+    #[test]
+    pub fn test_get_ref_method() {
+        let foo: Result<int, ()> = Ok(100);
+        assert_eq!(*foo.get_ref(), 100);
+    }
+}
diff --git a/src/libstd/rl.rs b/src/libstd/rl.rs
deleted file mode 100644
index d15a8fc0136..00000000000
--- a/src/libstd/rl.rs
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// FIXME #3921. This is unsafe because linenoise uses global mutable
-// state without mutexes.
-
-use core::libc::{c_char, c_int};
-
-pub mod rustrt {
-    use core::libc::{c_char, c_int};
-
-    pub extern {
-        pub unsafe fn linenoise(prompt: *c_char) -> *c_char;
-        pub unsafe fn linenoiseHistoryAdd(line: *c_char) -> c_int;
-        pub unsafe fn linenoiseHistorySetMaxLen(len: c_int) -> c_int;
-        pub unsafe fn linenoiseHistorySave(file: *c_char) -> c_int;
-        pub unsafe fn linenoiseHistoryLoad(file: *c_char) -> c_int;
-        pub unsafe fn linenoiseSetCompletionCallback(callback: *u8);
-        pub unsafe fn linenoiseAddCompletion(completions: *(), line: *c_char);
-    }
-}
-
-/// Add a line to history
-pub unsafe fn add_history(line: &str) -> bool {
-    do str::as_c_str(line) |buf| {
-        rustrt::linenoiseHistoryAdd(buf) == 1 as c_int
-    }
-}
-
-/// Set the maximum amount of lines stored
-pub unsafe fn set_history_max_len(len: int) -> bool {
-    rustrt::linenoiseHistorySetMaxLen(len as c_int) == 1 as c_int
-}
-
-/// Save line history to a file
-pub unsafe fn save_history(file: &str) -> bool {
-    do str::as_c_str(file) |buf| {
-        rustrt::linenoiseHistorySave(buf) == 1 as c_int
-    }
-}
-
-/// Load line history from a file
-pub unsafe fn load_history(file: &str) -> bool {
-    do str::as_c_str(file) |buf| {
-        rustrt::linenoiseHistoryLoad(buf) == 1 as c_int
-    }
-}
-
-/// Print out a prompt and then wait for input and return it
-pub unsafe fn read(prompt: &str) -> Option<~str> {
-    do str::as_c_str(prompt) |buf| {
-        let line = rustrt::linenoise(buf);
-
-        if line.is_null() { None }
-        else { Some(str::raw::from_c_str(line)) }
-    }
-}
-
-pub type CompletionCb<'self> = @fn(~str, &'self fn(~str));
-
-fn complete_key(_v: @CompletionCb) {}
-
-/// Bind to the main completion callback
-pub unsafe fn complete(cb: CompletionCb) {
-    local_data::local_data_set(complete_key, @(cb));
-
-    extern fn callback(line: *c_char, completions: *()) {
-        unsafe {
-            let cb = *local_data::local_data_get(complete_key)
-                .get();
-
-            do cb(str::raw::from_c_str(line)) |suggestion| {
-                do str::as_c_str(suggestion) |buf| {
-                    rustrt::linenoiseAddCompletion(completions, buf);
-                }
-            }
-        }
-    }
-
-    rustrt::linenoiseSetCompletionCallback(callback);
-}
diff --git a/src/libstd/rope.rs b/src/libstd/rope.rs
deleted file mode 100644
index 04444789f82..00000000000
--- a/src/libstd/rope.rs
+++ /dev/null
@@ -1,1430 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
- * High-level text containers.
- *
- * Ropes are a high-level representation of text that offers
- * much better performance than strings for common operations,
- * and generally reduce memory allocations and copies, while only
- * entailing a small degradation of less common operations.
- *
- * More precisely, where a string is represented as a memory buffer,
- * a rope is a tree structure whose leaves are slices of immutable
- * strings. Therefore, concatenation, appending, prepending, substrings,
- * etc. are operations that require only trivial tree manipulation,
- * generally without having to copy memory. In addition, the tree
- * structure of ropes makes them suitable as a form of index to speed-up
- * access to Unicode characters by index in long chunks of text.
- *
- * The following operations are algorithmically faster in ropes:
- *
- * * extracting a subrope is logarithmic (linear in strings);
- * * appending/prepending is near-constant time (linear in strings);
- * * concatenation is near-constant time (linear in strings);
- * * char length is constant-time (linear in strings);
- * * access to a character by index is logarithmic (linear in strings);
- */
-
-/// The type of ropes.
-pub type Rope = node::Root;
-
-/*
- Section: Creating a rope
- */
-
-/// Create an empty rope
-pub fn empty() -> Rope {
-   return node::Empty;
-}
-
-/**
- * Adopt a string as a rope.
- *
- * # Arguments
- *
- * * str - A valid string.
- *
- * # Return value
- *
- * A rope representing the same string as `str`. Depending of the length
- * of `str`, this rope may be empty, flat or complex.
- *
- * # Performance notes
- *
- * * this operation does not copy the string;
- * * the function runs in linear time.
- */
-pub fn of_str(str: @~str) -> Rope {
-    return of_substr(str, 0u, str::len(*str));
-}
-
-/**
- * As `of_str` but for a substring.
- *
- * # Arguments
- * * byte_offset - The offset of `str` at which the rope starts.
- * * byte_len - The number of bytes of `str` to use.
- *
- * # Return value
- *
- * A rope representing the same string as `str::substr(str, byte_offset,
- * byte_len)`.  Depending on `byte_len`, this rope may be empty, flat or
- * complex.
- *
- * # Performance note
- *
- * This operation does not copy the substring.
- *
- * # Safety notes
- *
- * * this function does _not_ check the validity of the substring;
- * * this function fails if `byte_offset` or `byte_len` do not match `str`.
- */
-pub fn of_substr(str: @~str, byte_offset: uint, byte_len: uint) -> Rope {
-    if byte_len == 0u { return node::Empty; }
-    if byte_offset + byte_len  > str::len(*str) { fail!(); }
-    return node::Content(node::of_substr(str, byte_offset, byte_len));
-}
-
-/*
-Section: Adding things to a rope
- */
-
-/**
- * Add one char to the end of the rope
- *
- * # Performance note
- *
- * * this function executes in near-constant time
- */
-pub fn append_char(rope: Rope, char: char) -> Rope {
-    return append_str(rope, @str::from_chars([char]));
-}
-
-/**
- * Add one string to the end of the rope
- *
- * # Performance note
- *
- * * this function executes in near-linear time
- */
-pub fn append_str(rope: Rope, str: @~str) -> Rope {
-    return append_rope(rope, of_str(str))
-}
-
-/**
- * Add one char to the beginning of the rope
- *
- * # Performance note
- * * this function executes in near-constant time
- */
-pub fn prepend_char(rope: Rope, char: char) -> Rope {
-    return prepend_str(rope, @str::from_chars([char]));
-}
-
-/**
- * Add one string to the beginning of the rope
- *
- * # Performance note
- * * this function executes in near-linear time
- */
-pub fn prepend_str(rope: Rope, str: @~str) -> Rope {
-    return append_rope(of_str(str), rope)
-}
-
-/// Concatenate two ropes
-pub fn append_rope(left: Rope, right: Rope) -> Rope {
-   match (left) {
-     node::Empty => return right,
-     node::Content(left_content) => {
-       match (right) {
-         node::Empty => return left,
-         node::Content(right_content) => {
-           return node::Content(node::concat2(left_content, right_content));
-         }
-       }
-     }
-   }
-}
-
-/**
- * Concatenate many ropes.
- *
- * If the ropes are balanced initially and have the same height, the resulting
- * rope remains balanced. However, this function does not take any further
- * measure to ensure that the result is balanced.
- */
-pub fn concat(v: ~[Rope]) -> Rope {
-    //Copy `v` into a mut vector
-    let mut len = v.len();
-    if len == 0u { return node::Empty; }
-    let mut ropes = vec::from_elem(len, v[0]);
-    for uint::range(1u, len) |i| {
-       ropes[i] = v[i];
-    }
-
-    //Merge progresively
-    while len > 1u {
-        for uint::range(0u, len/2u) |i| {
-            ropes[i] = append_rope(ropes[2u*i], ropes[2u*i+1u]);
-        }
-        if len%2u != 0u {
-            ropes[len/2u] = ropes[len - 1u];
-            len = len/2u + 1u;
-        } else {
-            len = len/2u;
-        }
-    }
-
-    //Return final rope
-    return ropes[0];
-}
-
-
-/*
-Section: Keeping ropes healthy
- */
-
-
-/**
- * Balance a rope.
- *
- * # Return value
- *
- * A copy of the rope in which small nodes have been grouped in memory,
- * and with a reduced height.
- *
- * If you perform numerous rope concatenations, it is generally a good idea
- * to rebalance your rope at some point, before using it for other purposes.
- */
-pub fn bal(rope:Rope) -> Rope {
-    match (rope) {
-      node::Empty => return rope,
-      node::Content(x) => match (node::bal(x)) {
-        None    => rope,
-        Some(y) => node::Content(y)
-      }
-    }
-}
-
-/*
-Section: Transforming ropes
- */
-
-
-/**
- * Extract a subrope from a rope.
- *
- * # Performance note
- *
- * * on a balanced rope, this operation takes algorithmic time;
- * * this operation does not involve any copying
- *
- * # Safety note
- *
- * * this function fails if char_offset/char_len do not represent
- *   valid positions in rope
- */
-pub fn sub_chars(rope: Rope, char_offset: uint, char_len: uint) -> Rope {
-    if char_len == 0u { return node::Empty; }
-    match (rope) {
-      node::Empty => fail!(),
-      node::Content(node) => if char_len > node::char_len(node) {
-        fail!()
-      } else {
-        return node::Content(node::sub_chars(node, char_offset, char_len))
-      }
-    }
-}
-
-/**
- * Extract a subrope from a rope.
- *
- * # Performance note
- *
- * * on a balanced rope, this operation takes algorithmic time;
- * * this operation does not involve any copying
- *
- * # Safety note
- *
- * * this function fails if byte_offset/byte_len do not represent
- *   valid positions in rope
- */
-pub fn sub_bytes(rope: Rope, byte_offset: uint, byte_len: uint) -> Rope {
-    if byte_len == 0u { return node::Empty; }
-    match (rope) {
-      node::Empty => fail!(),
-      node::Content(node) =>if byte_len > node::byte_len(node) {
-        fail!()
-      } else {
-        return node::Content(node::sub_bytes(node, byte_offset, byte_len))
-      }
-    }
-}
-
-/*
-Section: Comparing ropes
- */
-
-/**
- * Compare two ropes by Unicode lexicographical order.
- *
- * This function compares only the contents of the rope, not their structure.
- *
- * # Return value
- *
- * A negative value if `left < right`, 0 if eq(left, right) or a positive
- * value if `left > right`
- */
-pub fn cmp(left: Rope, right: Rope) -> int {
-    match ((left, right)) {
-      (node::Empty, node::Empty) => return 0,
-      (node::Empty, _)     => return -1,
-      (_, node::Empty)     => return  1,
-      (node::Content(a), node::Content(b)) => {
-        return node::cmp(a, b);
-      }
-    }
-}
-
-/**
- * Returns `true` if both ropes have the same content (regardless of
- * their structure), `false` otherwise
- */
-pub fn eq(left: Rope, right: Rope) -> bool {
-    return cmp(left, right) == 0;
-}
-
-/**
- * # Arguments
- *
- * * left - an arbitrary rope
- * * right - an arbitrary rope
- *
- * # Return value
- *
- * `true` if `left <= right` in lexicographical order (regardless of their
- * structure), `false` otherwise
- */
-pub fn le(left: Rope, right: Rope) -> bool {
-    return cmp(left, right) <= 0;
-}
-
-/**
- * # Arguments
- *
- * * left - an arbitrary rope
- * * right - an arbitrary rope
- *
- * # Return value
- *
- * `true` if `left < right` in lexicographical order (regardless of their
- * structure), `false` otherwise
- */
-pub fn lt(left: Rope, right: Rope) -> bool {
-    return cmp(left, right) < 0;
-}
-
-/**
- * # Arguments
- *
- * * left - an arbitrary rope
- * * right - an arbitrary rope
- *
- * # Return value
- *
- *  `true` if `left >= right` in lexicographical order (regardless of their
- * structure), `false` otherwise
- */
-pub fn ge(left: Rope, right: Rope) -> bool {
-    return cmp(left, right) >= 0;
-}
-
-/**
- * # Arguments
- *
- * * left - an arbitrary rope
- * * right - an arbitrary rope
- *
- * # Return value
- *
- * `true` if `left > right` in lexicographical order (regardless of their
- * structure), `false` otherwise
- */
-pub fn gt(left: Rope, right: Rope) -> bool {
-    return cmp(left, right) > 0;
-}
-
-/*
-Section: Iterating
- */
-
-/**
- * Loop through a rope, char by char
- *
- * While other mechanisms are available, this is generally the best manner
- * of looping through the contents of a rope char by char. If you prefer a
- * loop that iterates through the contents string by string (e.g. to print
- * the contents of the rope or output it to the system), however,
- * you should rather use `traverse_components`.
- *
- * # Arguments
- *
- * * rope - A rope to traverse. It may be empty.
- * * it - A block to execute with each consecutive character of the rope.
- *        Return `true` to continue, `false` to stop.
- *
- * # Return value
- *
- * `true` If execution proceeded correctly, `false` if it was interrupted,
- * that is if `it` returned `false` at any point.
- */
-pub fn loop_chars(rope: Rope, it: &fn(c: char) -> bool) -> bool {
-   match (rope) {
-      node::Empty => return true,
-      node::Content(x) => return node::loop_chars(x, it)
-   }
-}
-
-/**
- * Loop through a rope, char by char, until the end.
- *
- * # Arguments
- * * rope - A rope to traverse. It may be empty
- * * it - A block to execute with each consecutive character of the rope.
- */
-pub fn iter_chars(rope: Rope, it: &fn(char)) {
-    do loop_chars(rope) |x| {
-        it(x);
-        true
-    };
-}
-
-/**
- * Loop through a rope, string by string
- *
- * While other mechanisms are available, this is generally the best manner of
- * looping through the contents of a rope string by string, which may be
- * useful e.g. to print strings as you see them (without having to copy their
- * contents into a new string), to send them to then network, to write them to
- * a file, etc.. If you prefer a loop that iterates through the contents
- * char by char (e.g. to search for a char), however, you should rather
- * use `traverse`.
- *
- * # Arguments
- *
- * * rope - A rope to traverse. It may be empty
- * * it - A block to execute with each consecutive string component of the
- *        rope. Return `true` to continue, `false` to stop
- *
- * # Return value
- *
- * `true` If execution proceeded correctly, `false` if it was interrupted,
- * that is if `it` returned `false` at any point.
- */
-pub fn loop_leaves(rope: Rope, it: &fn(node::Leaf) -> bool) -> bool{
-   match (rope) {
-      node::Empty => return true,
-      node::Content(x) => return node::loop_leaves(x, it)
-   }
-}
-
-pub mod iterator {
-    pub mod leaf {
-        use rope::{Rope, node};
-
-
-        pub fn start(rope: Rope) -> node::leaf_iterator::T {
-            match (rope) {
-              node::Empty      => return node::leaf_iterator::empty(),
-              node::Content(x) => return node::leaf_iterator::start(x)
-            }
-        }
-        pub fn next(it: &mut node::leaf_iterator::T) -> Option<node::Leaf> {
-            return node::leaf_iterator::next(it);
-        }
-    }
-    pub mod char {
-        use rope::{Rope, node};
-
-
-        pub fn start(rope: Rope) -> node::char_iterator::T {
-            match (rope) {
-              node::Empty      => return node::char_iterator::empty(),
-              node::Content(x) => return node::char_iterator::start(x)
-            }
-        }
-        pub fn next(it: &mut node::char_iterator::T) -> Option<char> {
-            return node::char_iterator::next(it)
-        }
-    }
-}
-
-/*
- Section: Rope properties
- */
-
-/**
- * Returns the height of the rope.
- *
- * The height of the rope is a bound on the number of operations which
- * must be performed during a character access before finding the leaf in
- * which a character is contained.
- *
- * # Performance note
- *
- * Constant time.
- */
-pub fn height(rope: Rope) -> uint {
-   match (rope) {
-      node::Empty      => return 0u,
-      node::Content(x) => return node::height(x)
-   }
-}
-
-
-
-/**
- * The number of character in the rope
- *
- * # Performance note
- *
- * Constant time.
- */
-pub fn char_len(rope: Rope) -> uint {
-   match (rope) {
-     node::Empty            => return 0u,
-     node::Content(x)       => return node::char_len(x)
-   }
-}
-
-/**
- * The number of bytes in the rope
- *
- * # Performance note
- *
- * Constant time.
- */
-pub fn byte_len(rope: Rope) -> uint {
-   match (rope) {
-     node::Empty            => return 0u,
-     node::Content(x)       => return node::byte_len(x)
-   }
-}
-
-/**
- * The character at position `pos`
- *
- * # Arguments
- *
- * * pos - A position in the rope
- *
- * # Safety notes
- *
- * The function will fail if `pos` is not a valid position in the rope.
- *
- * # Performance note
- *
- * This function executes in a time proportional to the height of the
- * rope + the (bounded) length of the largest leaf.
- */
-pub fn char_at(rope: Rope, pos: uint) -> char {
-   match (rope) {
-      node::Empty => fail!(),
-      node::Content(x) => return node::char_at(x, pos)
-   }
-}
-
-
-/*
- Section: Implementation
-*/
-pub mod node {
-    use rope::node;
-
-    /// Implementation of type `rope`
-    pub enum Root {
-        /// An empty rope
-        Empty,
-        /// A non-empty rope
-        Content(@Node),
-    }
-
-    /**
-     * A text component in a rope.
-     *
-     * This is actually a slice in a rope, so as to ensure maximal sharing.
-     *
-     * # Fields
-     *
-     * * byte_offset = The number of bytes skipped in `content`
-     * * byte_len - The number of bytes of `content` to use
-     * * char_len - The number of chars in the leaf.
-     * * content - Contents of the leaf.
-     *
-     *     Note that we can have `char_len < str::char_len(content)`, if
-     *     this leaf is only a subset of the string. Also note that the
-     *     string can be shared between several ropes, e.g. for indexing
-     *     purposes.
-     */
-    pub struct Leaf {
-        byte_offset: uint,
-        byte_len: uint,
-        char_len: uint,
-        content: @~str,
-    }
-
-    /**
-     * A node obtained from the concatenation of two other nodes
-     *
-     * # Fields
-     *
-     * * left - The node containing the beginning of the text.
-     * * right - The node containing the end of the text.
-     * * char_len - The number of chars contained in all leaves of this node.
-     * * byte_len - The number of bytes in the subrope.
-     *
-     *     Used to pre-allocate the correct amount of storage for
-     *     serialization.
-     *
-     * * height - Height of the subrope.
-     *
-     *     Used for rebalancing and to allocate stacks for traversals.
-     */
-    pub struct Concat {
-        //FIXME (#2744): Perhaps a `vec` instead of `left`/`right`
-        left: @Node,
-        right: @Node,
-        char_len: uint,
-        byte_len: uint,
-        height: uint,
-    }
-
-    pub enum Node {
-        /// A leaf consisting in a `str`
-        Leaf(Leaf),
-        /// The concatenation of two ropes
-        Concat(Concat),
-    }
-
-    /**
-     * The maximal number of chars that _should_ be permitted in a single node
-     *
-     * This is not a strict value
-     */
-    pub static hint_max_leaf_char_len: uint = 256u;
-
-    /**
-     * The maximal height that _should_ be permitted in a tree.
-     *
-     * This is not a strict value
-     */
-    pub static hint_max_node_height:   uint = 16u;
-
-    /**
-     * Adopt a string as a node.
-     *
-     * If the string is longer than `max_leaf_char_len`, it is
-     * logically split between as many leaves as necessary. Regardless,
-     * the string itself is not copied.
-     *
-     * Performance note: The complexity of this function is linear in
-     * the length of `str`.
-     */
-    pub fn of_str(str: @~str) -> @Node {
-        return of_substr(str, 0u, str::len(*str));
-    }
-
-    /**
-     * Adopt a slice of a string as a node.
-     *
-     * If the slice is longer than `max_leaf_char_len`, it is logically split
-     * between as many leaves as necessary. Regardless, the string itself
-     * is not copied
-     *
-     * # Arguments
-     *
-     * * byte_start - The byte offset where the slice of `str` starts.
-     * * byte_len   - The number of bytes from `str` to use.
-     *
-     * # Safety note
-     *
-     * Behavior is undefined if `byte_start` or `byte_len` do not represent
-     * valid positions in `str`
-     */
-    pub fn of_substr(str: @~str, byte_start: uint, byte_len: uint) -> @Node {
-        return of_substr_unsafer(str, byte_start, byte_len,
-                              str::count_chars(*str, byte_start, byte_len));
-    }
-
-    /**
-     * Adopt a slice of a string as a node.
-     *
-     * If the slice is longer than `max_leaf_char_len`, it is logically split
-     * between as many leaves as necessary. Regardless, the string itself
-     * is not copied
-     *
-     * # Arguments
-     *
-     * * byte_start - The byte offset where the slice of `str` starts.
-     * * byte_len - The number of bytes from `str` to use.
-     * * char_len - The number of chars in `str` in the interval
-     *              [byte_start, byte_start+byte_len)
-     *
-     * # Safety notes
-     *
-     * * Behavior is undefined if `byte_start` or `byte_len` do not represent
-     *   valid positions in `str`
-     * * Behavior is undefined if `char_len` does not accurately represent the
-     *   number of chars between byte_start and byte_start+byte_len
-     */
-    pub fn of_substr_unsafer(str: @~str, byte_start: uint, byte_len: uint,
-                             char_len: uint) -> @Node {
-        assert!((byte_start + byte_len <= str::len(*str)));
-        let candidate = @Leaf(Leaf {
-            byte_offset: byte_start,
-            byte_len: byte_len,
-            char_len: char_len,
-            content: str,
-        });
-        if char_len <= hint_max_leaf_char_len {
-            return candidate;
-        } else {
-            //Firstly, split `str` in slices of hint_max_leaf_char_len
-            let mut leaves = uint::div_ceil(char_len, hint_max_leaf_char_len);
-            //Number of leaves
-            let mut nodes  = vec::from_elem(leaves, candidate);
-
-            let mut i = 0u;
-            let mut offset = byte_start;
-            let first_leaf_char_len =
-                if char_len%hint_max_leaf_char_len == 0u {
-                  hint_max_leaf_char_len
-                } else {
-                char_len%hint_max_leaf_char_len
-               };
-            while i < leaves {
-                let chunk_char_len: uint =
-                    if i == 0u  { first_leaf_char_len }
-                    else { hint_max_leaf_char_len };
-                let chunk_byte_len =
-                    str::count_bytes(*str, offset, chunk_char_len);
-                nodes[i] = @Leaf(Leaf {
-                    byte_offset: offset,
-                    byte_len: chunk_byte_len,
-                    char_len: chunk_char_len,
-                    content: str,
-                });
-
-                offset += chunk_byte_len;
-                i      += 1u;
-            }
-
-            //Then, build a tree from these slices by collapsing them
-            while leaves > 1u {
-                i = 0u;
-                while i < leaves - 1u {//Concat nodes 0 with 1, 2 with 3 etc.
-                    nodes[i/2u] = concat2(nodes[i], nodes[i + 1u]);
-                    i += 2u;
-                }
-                if i == leaves - 1u {
-                    //And don't forget the last node if it is in even position
-                    nodes[i/2u] = nodes[i];
-                }
-                leaves = uint::div_ceil(leaves, 2u);
-            }
-            return nodes[0u];
-        }
-    }
-
-    pub fn byte_len(node: @Node) -> uint {
-        //FIXME (#2744): Could we do this without the pattern-matching?
-        match (*node) {
-          Leaf(y) => y.byte_len,
-          Concat(ref y) => y.byte_len
-        }
-    }
-
-    pub fn char_len(node: @Node) -> uint {
-        match (*node) {
-          Leaf(y) => y.char_len,
-          Concat(ref y) => y.char_len
-        }
-    }
-
-    /**
-     * Concatenate a forest of nodes into one tree.
-     *
-     * # Arguments
-     *
-     * * forest - The forest. This vector is progressively rewritten during
-     *            execution and should be discarded as meaningless afterwards.
-     */
-    pub fn tree_from_forest_destructive(forest: &mut [@Node]) -> @Node {
-        let mut i;
-        let mut len = forest.len();
-        while len > 1u {
-            i = 0u;
-            while i < len - 1u {//Concat nodes 0 with 1, 2 with 3 etc.
-                let mut left  = forest[i];
-                let mut right = forest[i+1u];
-                let left_len = char_len(left);
-                let right_len= char_len(right);
-                let mut left_height= height(left);
-                let mut right_height=height(right);
-                if left_len + right_len > hint_max_leaf_char_len {
-                    if left_len <= hint_max_leaf_char_len {
-                        left = flatten(left);
-                        left_height = height(left);
-                    }
-                    if right_len <= hint_max_leaf_char_len {
-                        right = flatten(right);
-                        right_height = height(right);
-                    }
-                }
-                if left_height >= hint_max_node_height {
-                    left = of_substr_unsafer(@serialize_node(left),
-                                             0u,byte_len(left),
-                                             left_len);
-                }
-                if right_height >= hint_max_node_height {
-                    right = of_substr_unsafer(@serialize_node(right),
-                                             0u,byte_len(right),
-                                             right_len);
-                }
-                forest[i/2u] = concat2(left, right);
-                i += 2u;
-            }
-            if i == len - 1u {
-                //And don't forget the last node if it is in even position
-                forest[i/2u] = forest[i];
-            }
-            len = uint::div_ceil(len, 2u);
-        }
-        return forest[0];
-    }
-
-    pub fn serialize_node(node: @Node) -> ~str {
-        unsafe {
-            let mut buf = vec::from_elem(byte_len(node), 0);
-            let mut offset = 0u;//Current position in the buffer
-            let mut it = leaf_iterator::start(node);
-            loop {
-                match leaf_iterator::next(&mut it) {
-                  None => break,
-                  Some(x) => {
-                    //FIXME (#2744): Replace with memcpy or something similar
-                    let local_buf: ~[u8] = cast::transmute(copy *x.content);
-                    let mut i = x.byte_offset;
-                    while i < x.byte_len {
-                        buf[offset] = local_buf[i];
-                        offset += 1u;
-                        i      += 1u;
-                    }
-                    cast::forget(local_buf);
-                  }
-                }
-            }
-            return cast::transmute(buf);
-        }
-    }
-
-    /**
-     * Replace a subtree by a single leaf with the same contents.
-     *
-     * * Performance note
-     *
-     * This function executes in linear time.
-     */
-    pub fn flatten(node: @Node) -> @Node {
-        match (*node) {
-            Leaf(_) => node,
-            Concat(ref x) => {
-                @Leaf(Leaf {
-                    byte_offset: 0u,
-                    byte_len: x.byte_len,
-                    char_len: x.char_len,
-                    content: @serialize_node(node),
-                })
-            }
-        }
-    }
-
-    /**
-     * Balance a node.
-     *
-     * # Algorithm
-     *
-     * * if the node height is smaller than `hint_max_node_height`, do nothing
-     * * otherwise, gather all leaves as a forest, rebuild a balanced node,
-     *   concatenating small leaves along the way
-     *
-     * # Return value
-     *
-     * * `None` if no transformation happened
-     * * `Some(x)` otherwise, in which case `x` has the same contents
-     *    as `node` bot lower height and/or fragmentation.
-     */
-    pub fn bal(node: @Node) -> Option<@Node> {
-        if height(node) < hint_max_node_height { return None; }
-        //1. Gather all leaves as a forest
-        let mut forest = ~[];
-        let mut it = leaf_iterator::start(node);
-        loop {
-            match leaf_iterator::next(&mut it) {
-              None    => break,
-              Some(x) => forest.push(@Leaf(x))
-            }
-        }
-        //2. Rebuild tree from forest
-        let root = @*tree_from_forest_destructive(forest);
-        return Some(root);
-
-    }
-
-    /**
-     * Compute the subnode of a node.
-     *
-     * # Arguments
-     *
-     * * node        - A node
-     * * byte_offset - A byte offset in `node`
-     * * byte_len    - The number of bytes to return
-     *
-     * # Performance notes
-     *
-     * * this function performs no copying;
-     * * this function executes in a time proportional to the height of `node`
-     *
-     * # Safety notes
-     *
-     * This function fails if `byte_offset` or `byte_len` do not represent
-     * valid positions in `node`.
-     */
-    pub fn sub_bytes(node: @Node, byte_offset: uint,
-                     byte_len: uint) -> @Node {
-        let mut node        = node;
-        let mut byte_offset = byte_offset;
-        loop {
-            if byte_offset == 0u && byte_len == node::byte_len(node) {
-                return node;
-            }
-            match (*node) {
-              node::Leaf(x) => {
-                let char_len =
-                    str::count_chars(*x.content, byte_offset, byte_len);
-                return @Leaf(Leaf {
-                    byte_offset: byte_offset,
-                    byte_len: byte_len,
-                    char_len: char_len,
-                    content: x.content,
-                });
-              }
-              node::Concat(ref x) => {
-                let left_len: uint = node::byte_len(x.left);
-                if byte_offset <= left_len {
-                    if byte_offset + byte_len <= left_len {
-                        //Case 1: Everything fits in x.left, tail-call
-                        node = x.left;
-                    } else {
-                        //Case 2: A (non-empty, possibly full) suffix
-                        //of x.left and a (non-empty, possibly full) prefix
-                        //of x.right
-                        let left_result  =
-                            sub_bytes(x.left, byte_offset, left_len);
-                        let right_result =
-                            sub_bytes(x.right, 0u, left_len - byte_offset);
-                        return concat2(left_result, right_result);
-                    }
-                } else {
-                    //Case 3: Everything fits in x.right
-                    byte_offset -= left_len;
-                    node = x.right;
-                }
-              }
-            }
-        };
-    }
-
-    /**
-     * Compute the subnode of a node.
-     *
-     * # Arguments
-     *
-     * * node        - A node
-     * * char_offset - A char offset in `node`
-     * * char_len    - The number of chars to return
-     *
-     * # Performance notes
-     *
-     * * this function performs no copying;
-     * * this function executes in a time proportional to the height of `node`
-     *
-     * # Safety notes
-     *
-     * This function fails if `char_offset` or `char_len` do not represent
-     * valid positions in `node`.
-     */
-    pub fn sub_chars(node: @Node, char_offset: uint,
-                     char_len: uint) -> @Node {
-        let mut node        = node;
-        let mut char_offset = char_offset;
-        loop {
-            match (*node) {
-              node::Leaf(x) => {
-                if char_offset == 0u && char_len == x.char_len {
-                    return node;
-                }
-                let byte_offset =
-                    str::count_bytes(*x.content, 0u, char_offset);
-                let byte_len    =
-                    str::count_bytes(*x.content, byte_offset, char_len);
-                return @Leaf(Leaf {
-                    byte_offset: byte_offset,
-                    byte_len: byte_len,
-                    char_len: char_len,
-                    content: x.content,
-                });
-              }
-              node::Concat(ref x) => {
-                if char_offset == 0u && char_len == x.char_len {return node;}
-                let left_len : uint = node::char_len(x.left);
-                if char_offset <= left_len {
-                    if char_offset + char_len <= left_len {
-                        //Case 1: Everything fits in x.left, tail call
-                        node        = x.left;
-                    } else {
-                        //Case 2: A (non-empty, possibly full) suffix
-                        //of x.left and a (non-empty, possibly full) prefix
-                        //of x.right
-                        let left_result  =
-                            sub_chars(x.left, char_offset, left_len);
-                        let right_result =
-                            sub_chars(x.right, 0u, left_len - char_offset);
-                        return concat2(left_result, right_result);
-                    }
-                } else {
-                    //Case 3: Everything fits in x.right, tail call
-                    node = x.right;
-                    char_offset -= left_len;
-                }
-              }
-            }
-        };
-    }
-
-    pub fn concat2(left: @Node, right: @Node) -> @Node {
-        @Concat(Concat {
-            left: left,
-            right: right,
-            char_len: char_len(left) + char_len(right),
-            byte_len: byte_len(left) + byte_len(right),
-            height: uint::max(height(left), height(right)) + 1u,
-        })
-    }
-
-    pub fn height(node: @Node) -> uint {
-        match (*node) {
-          Leaf(_) => 0u,
-          Concat(ref x) => x.height,
-        }
-    }
-
-    pub fn cmp(a: @Node, b: @Node) -> int {
-        let mut ita = char_iterator::start(a);
-        let mut itb = char_iterator::start(b);
-        let mut result = 0;
-        while result == 0 {
-            match (char_iterator::next(&mut ita), char_iterator::next(&mut itb))
-            {
-              (None, None) => break,
-              (Some(chara), Some(charb)) => {
-                result = chara.cmp(&charb) as int;
-              }
-              (Some(_), _) => {
-                result = 1;
-              }
-              (_, Some(_)) => {
-                result = -1;
-              }
-            }
-        }
-        return result;
-    }
-
-    pub fn loop_chars(node: @Node, it: &fn(c: char) -> bool) -> bool {
-        return loop_leaves(node,|leaf| {
-            str::all_between(*leaf.content,
-                             leaf.byte_offset,
-                             leaf.byte_len, it)
-        });
-    }
-
-    /**
-     * Loop through a node, leaf by leaf
-     *
-     * # Arguments
-     *
-     * * rope - A node to traverse.
-     * * it - A block to execute with each consecutive leaf of the node.
-     *        Return `true` to continue, `false` to stop
-     *
-     * # Arguments
-     *
-     * `true` If execution proceeded correctly, `false` if it was interrupted,
-     * that is if `it` returned `false` at any point.
-     */
-    pub fn loop_leaves(node: @Node, it: &fn(Leaf) -> bool) -> bool{
-        let mut current = node;
-        loop {
-            match (*current) {
-              Leaf(x) => return it(x),
-              Concat(ref x) => if loop_leaves(x.left, it) { //non tail call
-                current = x.right;       //tail call
-              } else {
-                return false;
-              }
-            }
-        };
-    }
-
-    /**
-     * # Arguments
-     *
-     * * pos - A position in the rope
-     *
-     * # Return value
-     *
-     * The character at position `pos`
-     *
-     * # Safety notes
-     *
-     * The function will fail if `pos` is not a valid position in the rope.
-     *
-     * Performance note: This function executes in a time
-     * proportional to the height of the rope + the (bounded)
-     * length of the largest leaf.
-     */
-    pub fn char_at(mut node: @Node, mut pos: uint) -> char {
-        loop {
-            match *node {
-              Leaf(x) => return str::char_at(*x.content, pos),
-              Concat(Concat {left, right, _}) => {
-                let left_len = char_len(left);
-                node = if left_len > pos { left }
-                       else { pos -= left_len; right };
-              }
-            }
-        };
-    }
-
-    pub mod leaf_iterator {
-        use rope::node::{Concat, Leaf, Node, height};
-
-        pub struct T {
-            stack: ~[@Node],
-            stackpos: int,
-        }
-
-        pub fn empty() -> T {
-            let stack : ~[@Node] = ~[];
-            T { stack: stack, stackpos: -1 }
-        }
-
-        pub fn start(node: @Node) -> T {
-            let stack = vec::from_elem(height(node)+1u, node);
-            T {
-                stack: stack,
-                stackpos:  0,
-            }
-        }
-
-        pub fn next(it: &mut T) -> Option<Leaf> {
-            if it.stackpos < 0 { return None; }
-            loop {
-                let current = it.stack[it.stackpos];
-                it.stackpos -= 1;
-                match (*current) {
-                  Concat(ref x) => {
-                    it.stackpos += 1;
-                    it.stack[it.stackpos] = x.right;
-                    it.stackpos += 1;
-                    it.stack[it.stackpos] = x.left;
-                  }
-                  Leaf(x) => return Some(x)
-                }
-            };
-        }
-    }
-
-    pub mod char_iterator {
-        use rope::node::{Leaf, Node};
-        use rope::node::leaf_iterator;
-
-        pub struct T {
-            leaf_iterator: leaf_iterator::T,
-            leaf:  Option<Leaf>,
-            leaf_byte_pos: uint,
-        }
-
-        pub fn start(node: @Node) -> T {
-            T {
-                leaf_iterator: leaf_iterator::start(node),
-                leaf: None,
-                leaf_byte_pos: 0u,
-            }
-        }
-
-        pub fn empty() -> T {
-            T {
-                leaf_iterator: leaf_iterator::empty(),
-                leaf: None,
-                leaf_byte_pos: 0u,
-            }
-        }
-
-        pub fn next(it: &mut T) -> Option<char> {
-            loop {
-                match get_current_or_next_leaf(it) {
-                  None => return None,
-                  Some(_) => {
-                    let next_char = get_next_char_in_leaf(it);
-                    match next_char {
-                      None => loop,
-                      Some(_) => return next_char
-                    }
-                  }
-                }
-            };
-        }
-
-        pub fn get_current_or_next_leaf(it: &mut T) -> Option<Leaf> {
-            match it.leaf {
-              Some(_) => return it.leaf,
-              None => {
-                let next = leaf_iterator::next(&mut it.leaf_iterator);
-                match next {
-                  None => return None,
-                  Some(_) => {
-                    it.leaf          = next;
-                    it.leaf_byte_pos = 0u;
-                    return next;
-                  }
-                }
-              }
-            }
-        }
-
-        pub fn get_next_char_in_leaf(it: &mut T) -> Option<char> {
-            match copy it.leaf {
-              None => return None,
-              Some(aleaf) => {
-                if it.leaf_byte_pos >= aleaf.byte_len {
-                    //We are actually past the end of the leaf
-                    it.leaf = None;
-                    return None
-                } else {
-                    let range =
-                        str::char_range_at(*aleaf.content,
-                                     (*it).leaf_byte_pos + aleaf.byte_offset);
-                    let ch = range.ch;
-                    let next = range.next;
-                    (*it).leaf_byte_pos = next - aleaf.byte_offset;
-                    return Some(ch)
-                }
-              }
-            }
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use rope::*;
-    use core::prelude::*;
-
-    //Utility function, used for sanity check
-    fn rope_to_string(r: Rope) -> ~str {
-        match (r) {
-          node::Empty => return ~"",
-          node::Content(x) => {
-            let mut str = ~"";
-            fn aux(str: &mut ~str, node: @node::Node) {
-                match (*node) {
-                    node::Leaf(x) => {
-                        str::push_str(
-                            str,
-                            str::slice(
-                                *x.content, x.byte_offset,
-                                x.byte_offset + x.byte_len));
-                    }
-                    node::Concat(ref x) => {
-                        aux(str, x.left);
-                        aux(str, x.right);
-                    }
-                }
-            }
-            aux(&mut str, x);
-            return str
-          }
-        }
-    }
-
-
-    #[test]
-    fn trivial() {
-        assert_eq!(char_len(empty()), 0u);
-        assert_eq!(byte_len(empty()), 0u);
-    }
-
-    #[test]
-    fn of_string1() {
-        let sample = @~"0123456789ABCDE";
-        let r      = of_str(sample);
-
-        assert_eq!(char_len(r), str::char_len(*sample));
-        assert!(rope_to_string(r) == *sample);
-    }
-
-    #[test]
-    fn of_string2() {
-        let buf = @ mut ~"1234567890";
-        let mut i = 0;
-        while i < 10 {
-            let a = copy *buf;
-            let b = copy *buf;
-            *buf = a + b;
-            i+=1;
-        }
-        let sample = @copy *buf;
-        let r      = of_str(sample);
-        assert!(char_len(r) == str::char_len(*sample));
-        assert!(rope_to_string(r) == *sample);
-
-        let mut string_iter = 0u;
-        let string_len = str::len(*sample);
-        let mut rope_iter = iterator::char::start(r);
-        let mut equal = true;
-        while equal {
-            match (node::char_iterator::next(&mut rope_iter)) {
-              None => {
-                if string_iter < string_len {
-                    equal = false;
-                } break; }
-              Some(c) => {
-                let range = str::char_range_at(*sample, string_iter);
-                string_iter = range.next;
-                if range.ch != c { equal = false; break; }
-              }
-            }
-        }
-
-        assert!(equal);
-    }
-
-    #[test]
-    fn iter1() {
-        let buf = @ mut ~"1234567890";
-        let mut i = 0;
-        while i < 10 {
-            let a = copy *buf;
-            let b = copy *buf;
-            *buf = a + b;
-            i+=1;
-        }
-        let sample = @copy *buf;
-        let r      = of_str(sample);
-
-        let mut len = 0u;
-        let mut it  = iterator::char::start(r);
-        loop {
-            match (node::char_iterator::next(&mut it)) {
-              None => break,
-              Some(_) => len += 1u
-            }
-        }
-
-        assert_eq!(len, str::char_len(*sample));
-    }
-
-    #[test]
-    fn bal1() {
-        let init = @~"1234567890";
-        let buf  = @mut copy *init;
-        let mut i = 0;
-        while i < 8 {
-            let a = copy *buf;
-            let b = copy *buf;
-            *buf = a + b;
-            i+=1;
-        }
-        let sample = @copy *buf;
-        let r1     = of_str(sample);
-        let mut r2 = of_str(init);
-        i = 0;
-        while i < 8 { r2 = append_rope(r2, r2); i+= 1;}
-
-
-        assert!(eq(r1, r2));
-        let r3 = bal(r2);
-        assert_eq!(char_len(r1), char_len(r3));
-
-        assert!(eq(r1, r3));
-    }
-
-    #[test]
-    #[ignore]
-    fn char_at1() {
-        //Generate a large rope
-        let mut r = of_str(@~"123456789");
-        for uint::range(0u, 10u) |_i| {
-            r = append_rope(r, r);
-        }
-
-        //Copy it in the slowest possible way
-        let mut r2 = empty();
-        for uint::range(0u, char_len(r)) |i| {
-            r2 = append_char(r2, char_at(r, i));
-        }
-        assert!(eq(r, r2));
-
-        let mut r3 = empty();
-        for uint::range(0u, char_len(r)) |i| {
-            r3 = prepend_char(r3, char_at(r, char_len(r) - i - 1u));
-        }
-        assert!(eq(r, r3));
-
-        //Additional sanity checks
-        let balr = bal(r);
-        let bal2 = bal(r2);
-        let bal3 = bal(r3);
-        assert!(eq(r, balr));
-        assert!(eq(r, bal2));
-        assert!(eq(r, bal3));
-        assert!(eq(r2, r3));
-        assert!(eq(bal2, bal3));
-    }
-
-    #[test]
-    fn concat1() {
-        //Generate a reasonable rope
-        let chunk = of_str(@~"123456789");
-        let mut r = empty();
-        for uint::range(0u, 10u) |_i| {
-            r = append_rope(r, chunk);
-        }
-
-        //Same rope, obtained with rope::concat
-        let r2 = concat(vec::from_elem(10u, chunk));
-
-        assert!(eq(r, r2));
-    }
-}
diff --git a/src/libstd/rt/context.rs b/src/libstd/rt/context.rs
new file mode 100644
index 00000000000..0d011ce42ba
--- /dev/null
+++ b/src/libstd/rt/context.rs
@@ -0,0 +1,214 @@
+// 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::*;
+use super::stack::StackSegment;
+use libc::c_void;
+use cast::{transmute, transmute_mut_unsafe,
+           transmute_region, transmute_mut_region};
+
+// XXX: Registers is boxed so that it is 16-byte aligned, for storing
+// SSE regs.  It would be marginally better not to do this. In C++ we
+// use an attribute on a struct.
+// XXX: It would be nice to define regs as `~Option<Registers>` since
+// the registers are sometimes empty, but the discriminant would
+// then misalign the regs again.
+pub struct Context {
+    /// The context entry point, saved here for later destruction
+    start: Option<~~fn()>,
+    /// Hold the registers while the task or scheduler is suspended
+    regs: ~Registers
+}
+
+pub impl Context {
+    fn empty() -> Context {
+        Context {
+            start: None,
+            regs: new_regs()
+        }
+    }
+
+    /// Create a new context that will resume execution by running ~fn()
+    fn new(start: ~fn(), stack: &mut StackSegment) -> Context {
+        // XXX: Putting main into a ~ so it's a thin pointer and can
+        // be passed to the spawn function.  Another unfortunate
+        // allocation
+        let start = ~start;
+
+        // The C-ABI function that is the task entry point
+        extern fn task_start_wrapper(f: &~fn()) { (*f)() }
+
+        let fp: *c_void = task_start_wrapper as *c_void;
+        let argp: *c_void = unsafe { transmute::<&~fn(), *c_void>(&*start) };
+        let sp: *uint = stack.end();
+        let sp: *mut uint = unsafe { transmute_mut_unsafe(sp) };
+
+        // Save and then immediately load the current context,
+        // which we will then modify to call the given function when restored
+        let mut regs = new_regs();
+        unsafe {
+            swap_registers(transmute_mut_region(&mut *regs), transmute_region(&*regs))
+        };
+
+        initialize_call_frame(&mut *regs, fp, argp, sp);
+
+        return Context {
+            start: Some(start),
+            regs: regs
+        }
+    }
+
+    /* Switch contexts
+
+    Suspend the current execution context and resume another by
+    saving the registers values of the executing thread to a Context
+    then loading the registers from a previously saved Context.
+    */
+    fn swap(out_context: &mut Context, in_context: &Context) {
+        let out_regs: &mut Registers = match out_context {
+            &Context { regs: ~ref mut r, _ } => r
+        };
+        let in_regs: &Registers = match in_context {
+            &Context { regs: ~ref r, _ } => r
+        };
+
+        unsafe { swap_registers(out_regs, in_regs) };
+    }
+}
+
+extern {
+    #[rust_stack]
+    fn swap_registers(out_regs: *mut Registers, in_regs: *Registers);
+}
+
+#[cfg(target_arch = "x86")]
+struct Registers {
+    eax: u32, ebx: u32, ecx: u32, edx: u32,
+    ebp: u32, esi: u32, edi: u32, esp: u32,
+    cs: u16, ds: u16, ss: u16, es: u16, fs: u16, gs: u16,
+    eflags: u32, eip: u32
+}
+
+#[cfg(target_arch = "x86")]
+fn new_regs() -> ~Registers {
+    ~Registers {
+        eax: 0, ebx: 0, ecx: 0, edx: 0,
+        ebp: 0, esi: 0, edi: 0, esp: 0,
+        cs: 0, ds: 0, ss: 0, es: 0, fs: 0, gs: 0,
+        eflags: 0, eip: 0
+    }
+}
+
+#[cfg(target_arch = "x86")]
+fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
+
+    let sp = align_down(sp);
+    let sp = mut_offset(sp, -4);
+
+    unsafe { *sp = arg as uint };
+    let sp = mut_offset(sp, -1);
+    unsafe { *sp = 0 }; // The final return address
+
+    regs.esp = sp as u32;
+    regs.eip = fptr as u32;
+
+    // Last base pointer on the stack is 0
+    regs.ebp = 0;
+}
+
+#[cfg(target_arch = "x86_64")]
+type Registers = [uint, ..22];
+
+#[cfg(target_arch = "x86_64")]
+fn new_regs() -> ~Registers { ~([0, .. 22]) }
+
+#[cfg(target_arch = "x86_64")]
+fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
+
+    // Redefinitions from regs.h
+    static RUSTRT_ARG0: uint = 3;
+    static RUSTRT_RSP: uint = 1;
+    static RUSTRT_IP: uint = 8;
+    static RUSTRT_RBP: uint = 2;
+
+    let sp = align_down(sp);
+    let sp = mut_offset(sp, -1);
+
+    // The final return address. 0 indicates the bottom of the stack
+    unsafe { *sp = 0; }
+
+    rtdebug!("creating call frame");
+    rtdebug!("fptr %x", fptr as uint);
+    rtdebug!("arg %x", arg as uint);
+    rtdebug!("sp %x", sp as uint);
+
+    regs[RUSTRT_ARG0] = arg as uint;
+    regs[RUSTRT_RSP] = sp as uint;
+    regs[RUSTRT_IP] = fptr as uint;
+
+    // Last base pointer on the stack should be 0
+    regs[RUSTRT_RBP] = 0;
+}
+
+#[cfg(target_arch = "arm")]
+type Registers = [uint, ..32];
+
+#[cfg(target_arch = "arm")]
+fn new_regs() -> ~Registers { ~([0, .. 32]) }
+
+#[cfg(target_arch = "arm")]
+fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
+    let sp = align_down(sp);
+    // sp of arm eabi is 8-byte aligned
+    let sp = mut_offset(sp, -2);
+
+    // The final return address. 0 indicates the bottom of the stack
+    unsafe { *sp = 0; }
+
+    regs[0] = arg as uint;   // r0
+    regs[13] = sp as uint;   // #53 sp, r13
+    regs[14] = fptr as uint; // #60 pc, r15 --> lr
+}
+
+#[cfg(target_arch = "mips")]
+type Registers = [uint, ..32];
+
+#[cfg(target_arch = "mips")]
+fn new_regs() -> ~Registers { ~([0, .. 32]) }
+
+#[cfg(target_arch = "mips")]
+fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
+    let sp = align_down(sp);
+    // sp of mips o32 is 8-byte aligned
+    let sp = mut_offset(sp, -2);
+
+    // The final return address. 0 indicates the bottom of the stack
+    unsafe { *sp = 0; }
+
+    regs[4] = arg as uint;
+    regs[29] = sp as uint;
+    regs[25] = fptr as uint;
+    regs[31] = fptr as uint;
+}
+
+fn align_down(sp: *mut uint) -> *mut uint {
+    unsafe {
+        let sp: uint = transmute(sp);
+        let sp = sp & !(16 - 1);
+        transmute::<uint, *mut uint>(sp)
+    }
+}
+
+// XXX: ptr::offset is positive ints only
+#[inline(always)]
+pub fn mut_offset<T>(ptr: *mut T, count: int) -> *mut T {
+    use core::sys::size_of;
+    (ptr as int + count * (size_of::<T>() as int)) as *mut T
+}
diff --git a/src/libstd/rt/env.rs b/src/libstd/rt/env.rs
new file mode 100644
index 00000000000..1d7ff173149
--- /dev/null
+++ b/src/libstd/rt/env.rs
@@ -0,0 +1,49 @@
+// 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.
+
+//! Runtime environment settings
+
+use libc::{size_t, c_char, c_int};
+
+pub struct Environment {
+    /// The number of threads to use by default
+    num_sched_threads: size_t,
+    /// The minimum size of a stack segment
+    min_stack_size: size_t,
+    /// The maximum amount of total stack per task before aborting
+    max_stack_size: size_t,
+    /// The default logging configuration
+    logspec: *c_char,
+    /// Record and report detailed information about memory leaks
+    detailed_leaks: bool,
+    /// Seed the random number generator
+    rust_seed: *c_char,
+    /// Poison allocations on free
+    poison_on_free: bool,
+    /// The argc value passed to main
+    argc: c_int,
+    /// The argv value passed to main
+    argv: **c_char,
+    /// Print GC debugging info (true if env var RUST_DEBUG_MEM is set)
+    debug_mem: bool,
+    /// Print GC debugging info (true if env var RUST_DEBUG_BORROW is set)
+    debug_borrow: bool,
+}
+
+/// Get the global environment settings
+/// # Safety Note
+/// This will abort the process if run outside of task context
+pub fn get() -> &Environment {
+    unsafe { rust_get_rt_env() }
+}
+
+extern {
+    fn rust_get_rt_env() -> &Environment;
+}
diff --git a/src/libstd/rt/io/comm_adapters.rs b/src/libstd/rt/io/comm_adapters.rs
new file mode 100644
index 00000000000..7e891f1718e
--- /dev/null
+++ b/src/libstd/rt/io/comm_adapters.rs
@@ -0,0 +1,58 @@
+// 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 prelude::*;
+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> {
+    pub fn write(&mut self, _buf: &[u8]) { fail!() }
+
+    pub fn flush(&mut self) { 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
new file mode 100644
index 00000000000..ceff2ecd77d
--- /dev/null
+++ b/src/libstd/rt/io/extensions.rs
@@ -0,0 +1,903 @@
+// 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 uint;
+use int;
+use vec;
+use rt::io::{Reader, Writer};
+use rt::io::{read_error, standard_error, EndOfFile, DEFAULT_BUF_SIZE};
+use option::{Option, Some, None};
+use unstable::finally::Finally;
+use util;
+use cast;
+use io::{u64_to_le_bytes, u64_to_be_bytes};
+
+pub trait ReaderUtil {
+
+    /// 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>;
+
+    /// 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 `read_error`
+    /// on EOF. If `read_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);
+
+    /// Reads `len` bytes and gives you back a new vector of length `len`
+    ///
+    /// # Failure
+    ///
+    /// Raises the same conditions as `read`. Additionally raises `read_error`
+    /// on EOF. If `read_error` is handled then the returned vector may
+    /// contain less than the requested number of bytes.
+    fn read_bytes(&mut self, len: uint) -> ~[u8];
+
+    /// Reads all remaining bytes from the stream.
+    ///
+    /// # Failure
+    ///
+    /// Raises the same conditions as the `read` method.
+    fn read_to_end(&mut self) -> ~[u8];
+
+}
+
+pub trait ReaderByteConversions {
+    /// 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;
+
+    /// 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;
+
+    /// 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;
+
+    /// 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;
+
+    /// Reads a little-endian unsigned integer.
+    ///
+    /// The number of bytes returned is system-dependant.
+    fn read_le_uint(&mut self) -> uint;
+
+    /// Reads a little-endian integer.
+    ///
+    /// The number of bytes returned is system-dependant.
+    fn read_le_int(&mut self) -> int;
+
+    /// Reads a big-endian unsigned integer.
+    ///
+    /// The number of bytes returned is system-dependant.
+    fn read_be_uint(&mut self) -> uint;
+
+    /// Reads a big-endian integer.
+    ///
+    /// The number of bytes returned is system-dependant.
+    fn read_be_int(&mut self) -> int;
+
+    /// Reads a big-endian `u64`.
+    ///
+    /// `u64`s are 8 bytes long.
+    fn read_be_u64(&mut self) -> u64;
+
+    /// Reads a big-endian `u32`.
+    ///
+    /// `u32`s are 4 bytes long.
+    fn read_be_u32(&mut self) -> u32;
+
+    /// Reads a big-endian `u16`.
+    ///
+    /// `u16`s are 2 bytes long.
+    fn read_be_u16(&mut self) -> u16;
+
+    /// Reads a big-endian `i64`.
+    ///
+    /// `i64`s are 8 bytes long.
+    fn read_be_i64(&mut self) -> i64;
+
+    /// Reads a big-endian `i32`.
+    ///
+    /// `i32`s are 4 bytes long.
+    fn read_be_i32(&mut self) -> i32;
+
+    /// Reads a big-endian `i16`.
+    ///
+    /// `i16`s are 2 bytes long.
+    fn read_be_i16(&mut self) -> i16;
+
+    /// Reads a big-endian `f64`.
+    ///
+    /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
+    fn read_be_f64(&mut self) -> f64;
+
+    /// Reads a big-endian `f32`.
+    ///
+    /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
+    fn read_be_f32(&mut self) -> f32;
+
+    /// Reads a little-endian `u64`.
+    ///
+    /// `u64`s are 8 bytes long.
+    fn read_le_u64(&mut self) -> u64;
+
+    /// Reads a little-endian `u32`.
+    ///
+    /// `u32`s are 4 bytes long.
+    fn read_le_u32(&mut self) -> u32;
+
+    /// Reads a little-endian `u16`.
+    ///
+    /// `u16`s are 2 bytes long.
+    fn read_le_u16(&mut self) -> u16;
+
+    /// Reads a little-endian `i64`.
+    ///
+    /// `i64`s are 8 bytes long.
+    fn read_le_i64(&mut self) -> i64;
+
+    /// Reads a little-endian `i32`.
+    ///
+    /// `i32`s are 4 bytes long.
+    fn read_le_i32(&mut self) -> i32;
+
+    /// Reads a little-endian `i16`.
+    ///
+    /// `i16`s are 2 bytes long.
+    fn read_le_i16(&mut self) -> i16;
+
+    /// Reads a little-endian `f64`.
+    ///
+    /// `f64`s are 8 byte, IEEE754 double-precision floating point numbers.
+    fn read_le_f64(&mut self) -> f64;
+
+    /// Reads a little-endian `f32`.
+    ///
+    /// `f32`s are 4 byte, IEEE754 single-precision floating point numbers.
+    fn read_le_f32(&mut self) -> f32;
+
+    /// Read a u8.
+    ///
+    /// `u8`s are 1 byte.
+    fn read_u8(&mut self) -> u8;
+
+    /// Read an i8.
+    ///
+    /// `i8`s are 1 byte.
+    fn read_i8(&mut self) -> i8;
+
+}
+
+pub trait WriterByteConversions {
+    /// Write the result of passing n through `int::to_str_bytes`.
+    fn write_int(&mut self, n: int);
+
+    /// Write the result of passing n through `uint::to_str_bytes`.
+    fn write_uint(&mut self, n: uint);
+
+    /// Write a little-endian uint (number of bytes depends on system).
+    fn write_le_uint(&mut self, n: uint);
+
+    /// Write a little-endian int (number of bytes depends on system).
+    fn write_le_int(&mut self, n: int);
+
+    /// Write a big-endian uint (number of bytes depends on system).
+    fn write_be_uint(&mut self, n: uint);
+
+    /// Write a big-endian int (number of bytes depends on system).
+    fn write_be_int(&mut self, n: int);
+
+    /// Write a big-endian u64 (8 bytes).
+    fn write_be_u64_(&mut self, n: u64);
+
+    /// Write a big-endian u32 (4 bytes).
+    fn write_be_u32(&mut self, n: u32);
+
+    /// Write a big-endian u16 (2 bytes).
+    fn write_be_u16(&mut self, n: u16);
+
+    /// Write a big-endian i64 (8 bytes).
+    fn write_be_i64(&mut self, n: i64);
+
+    /// Write a big-endian i32 (4 bytes).
+    fn write_be_i32(&mut self, n: i32);
+
+    /// Write a big-endian i16 (2 bytes).
+    fn write_be_i16(&mut self, n: i16);
+
+    /// Write a big-endian IEEE754 double-precision floating-point (8 bytes).
+    fn write_be_f64(&mut self, f: f64);
+
+    /// Write a big-endian IEEE754 single-precision floating-point (4 bytes).
+    fn write_be_f32(&mut self, f: f32);
+
+    /// Write a little-endian u64 (8 bytes).
+    fn write_le_u64_(&mut self, n: u64);
+
+    /// Write a little-endian u32 (4 bytes).
+    fn write_le_u32(&mut self, n: u32);
+
+    /// Write a little-endian u16 (2 bytes).
+    fn write_le_u16(&mut self, n: u16);
+
+    /// Write a little-endian i64 (8 bytes).
+    fn write_le_i64(&mut self, n: i64);
+
+    /// Write a little-endian i32 (4 bytes).
+    fn write_le_i32(&mut self, n: i32);
+
+    /// Write a little-endian i16 (2 bytes).
+    fn write_le_i16(&mut self, n: i16);
+
+    /// Write a little-endian IEEE754 double-precision floating-point
+    /// (8 bytes).
+    fn write_le_f64(&mut self, f: f64);
+
+    /// Write a litten-endian IEEE754 single-precision floating-point
+    /// (4 bytes).
+    fn write_le_f32(&mut self, f: f32);
+
+    /// Write a u8 (1 byte).
+    fn write_u8(&mut self, n: u8);
+
+    /// Write a i8 (1 byte).
+    fn write_i8(&mut self, n: i8);
+}
+
+impl<T: Reader> ReaderUtil for T {
+    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(_) => util::unreachable(),
+            None => None
+        }
+    }
+
+    fn push_bytes(&mut self, buf: &mut ~[u8], len: uint) {
+        unsafe {
+            let start_len = buf.len();
+            let mut total_read = 0;
+
+            vec::reserve_at_least(buf, start_len + len);
+            vec::raw::set_len(buf, start_len + len);
+
+            do (|| {
+                while total_read < len {
+                    let slice = vec::mut_slice(*buf, start_len + total_read, buf.len());
+                    match self.read(slice) {
+                        Some(nread) => {
+                            total_read += nread;
+                        }
+                        None => {
+                            read_error::cond.raise(standard_error(EndOfFile));
+                            break;
+                        }
+                    }
+                }
+            }).finally {
+                vec::raw::set_len(buf, start_len + total_read);
+            }
+        }
+    }
+
+    fn read_bytes(&mut self, len: uint) -> ~[u8] {
+        let mut buf = vec::with_capacity(len);
+        self.push_bytes(&mut buf, len);
+        return buf;
+    }
+
+    fn read_to_end(&mut self) -> ~[u8] {
+        let mut buf = vec::with_capacity(DEFAULT_BUF_SIZE);
+        let mut keep_reading = true;
+        do read_error::cond.trap(|e| {
+            if e.kind == EndOfFile {
+                keep_reading = false;
+            } else {
+                read_error::cond.raise(e)
+            }
+        }).in {
+            while keep_reading {
+                self.push_bytes(&mut buf, DEFAULT_BUF_SIZE)
+            }
+        }
+        return buf;
+    }
+}
+
+impl<T: Reader> ReaderByteConversions for T {
+    fn read_le_uint_n(&mut self, nbytes: uint) -> u64 {
+        assert!(nbytes > 0 && nbytes <= 8);
+
+        let mut val = 0u64, pos = 0, i = nbytes;
+        while i > 0 {
+            val += (self.read_u8() as u64) << pos;
+            pos += 8;
+            i -= 1;
+        }
+        val
+    }
+
+    fn read_le_int_n(&mut self, nbytes: uint) -> i64 {
+        extend_sign(self.read_le_uint_n(nbytes), nbytes)
+    }
+
+    fn read_be_uint_n(&mut self, nbytes: uint) -> u64 {
+        assert!(nbytes > 0 && nbytes <= 8);
+
+        let mut val = 0u64, i = nbytes;
+        while i > 0 {
+            i -= 1;
+            val += (self.read_u8() as u64) << i * 8;
+        }
+        val
+    }
+
+    fn read_be_int_n(&mut self, nbytes: uint) -> i64 {
+        extend_sign(self.read_be_uint_n(nbytes), nbytes)
+    }
+
+    fn read_le_uint(&mut self) -> uint {
+        self.read_le_uint_n(uint::bytes) as uint
+    }
+
+    fn read_le_int(&mut self) -> int {
+        self.read_le_int_n(int::bytes) as int
+    }
+
+    fn read_be_uint(&mut self) -> uint {
+        self.read_be_uint_n(uint::bytes) as uint
+    }
+
+    fn read_be_int(&mut self) -> int {
+        self.read_be_int_n(int::bytes) as int
+    }
+
+    fn read_be_u64(&mut self) -> u64 {
+        self.read_be_uint_n(8) as u64
+    }
+
+    fn read_be_u32(&mut self) -> u32 {
+        self.read_be_uint_n(4) as u32
+    }
+
+    fn read_be_u16(&mut self) -> u16 {
+        self.read_be_uint_n(2) as u16
+    }
+
+    fn read_be_i64(&mut self) -> i64 {
+        self.read_be_int_n(8) as i64
+    }
+
+    fn read_be_i32(&mut self) -> i32 {
+        self.read_be_int_n(4) as i32
+    }
+
+    fn read_be_i16(&mut self) -> i16 {
+        self.read_be_int_n(2) as i16
+    }
+
+    fn read_be_f64(&mut self) -> f64 {
+        unsafe {
+            cast::transmute::<u64, f64>(self.read_be_u64())
+        }
+    }
+
+    fn read_be_f32(&mut self) -> f32 {
+        unsafe {
+            cast::transmute::<u32, f32>(self.read_be_u32())
+        }
+    }
+
+    fn read_le_u64(&mut self) -> u64 {
+        self.read_le_uint_n(8) as u64
+    }
+
+    fn read_le_u32(&mut self) -> u32 {
+        self.read_le_uint_n(4) as u32
+    }
+
+    fn read_le_u16(&mut self) -> u16 {
+        self.read_le_uint_n(2) as u16
+    }
+
+    fn read_le_i64(&mut self) -> i64 {
+        self.read_le_int_n(8) as i64
+    }
+
+    fn read_le_i32(&mut self) -> i32 {
+        self.read_le_int_n(4) as i32
+    }
+
+    fn read_le_i16(&mut self) -> i16 {
+        self.read_le_int_n(2) as i16
+    }
+
+    fn read_le_f64(&mut self) -> f64 {
+        unsafe {
+            cast::transmute::<u64, f64>(self.read_le_u64())
+        }
+    }
+
+    fn read_le_f32(&mut self) -> f32 {
+        unsafe {
+            cast::transmute::<u32, f32>(self.read_le_u32())
+        }
+    }
+
+    fn read_u8(&mut self) -> u8 {
+        match self.read_byte() {
+            Some(b) => b as u8,
+            None => 0
+        }
+    }
+
+    fn read_i8(&mut self) -> i8 {
+        match self.read_byte() {
+            Some(b) => b as i8,
+            None => 0
+        }
+    }
+
+}
+
+impl<T: Writer> WriterByteConversions for T {
+    fn write_int(&mut self, n: int) {
+        int::to_str_bytes(n, 10u, |bytes| self.write(bytes))
+    }
+
+    fn write_uint(&mut self, n: uint) {
+        uint::to_str_bytes(n, 10u, |bytes| self.write(bytes))
+    }
+
+    fn write_le_uint(&mut self, n: uint) {
+        u64_to_le_bytes(n as u64, uint::bytes, |v| self.write(v))
+    }
+
+    fn write_le_int(&mut self, n: int) {
+        u64_to_le_bytes(n as u64, int::bytes, |v| self.write(v))
+    }
+
+    fn write_be_uint(&mut self, n: uint) {
+        u64_to_be_bytes(n as u64, uint::bytes, |v| self.write(v))
+    }
+
+    fn write_be_int(&mut self, n: int) {
+        u64_to_be_bytes(n as u64, int::bytes, |v| self.write(v))
+    }
+
+    fn write_be_u64_(&mut self, n: u64) {
+        u64_to_be_bytes(n, 8u, |v| self.write(v))
+    }
+
+    fn write_be_u32(&mut self, n: u32) {
+        u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
+    }
+
+    fn write_be_u16(&mut self, n: u16) {
+        u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
+    }
+
+    fn write_be_i64(&mut self, n: i64) {
+        u64_to_be_bytes(n as u64, 8u, |v| self.write(v))
+    }
+
+    fn write_be_i32(&mut self, n: i32) {
+        u64_to_be_bytes(n as u64, 4u, |v| self.write(v))
+    }
+
+    fn write_be_i16(&mut self, n: i16) {
+        u64_to_be_bytes(n as u64, 2u, |v| self.write(v))
+    }
+
+    fn write_be_f64(&mut self, f: f64) {
+        unsafe {
+            self.write_be_u64_(cast::transmute(f))
+        }
+    }
+
+    fn write_be_f32(&mut self, f: f32) {
+        unsafe {
+            self.write_be_u32(cast::transmute(f))
+        }
+    }
+
+    fn write_le_u64_(&mut self, n: u64) {
+        u64_to_le_bytes(n, 8u, |v| self.write(v))
+    }
+
+    fn write_le_u32(&mut self, n: u32) {
+        u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
+    }
+
+    fn write_le_u16(&mut self, n: u16) {
+        u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
+    }
+
+    fn write_le_i64(&mut self, n: i64) {
+        u64_to_le_bytes(n as u64, 8u, |v| self.write(v))
+    }
+
+    fn write_le_i32(&mut self, n: i32) {
+        u64_to_le_bytes(n as u64, 4u, |v| self.write(v))
+    }
+
+    fn write_le_i16(&mut self, n: i16) {
+        u64_to_le_bytes(n as u64, 2u, |v| self.write(v))
+    }
+
+    fn write_le_f64(&mut self, f: f64) {
+        unsafe {
+            self.write_le_u64_(cast::transmute(f))
+        }
+    }
+
+    fn write_le_f32(&mut self, f: f32) {
+        unsafe {
+            self.write_le_u32(cast::transmute(f))
+        }
+    }
+
+    fn write_u8(&mut self, n: u8) {
+        self.write([n])
+    }
+
+    fn write_i8(&mut self, n: i8) {
+        self.write([n as u8])
+    }
+}
+
+fn extend_sign(val: u64, nbytes: uint) -> i64 {
+    let shift = (8 - nbytes) * 8;
+    (val << shift) as i64 >> shift
+}
+
+#[cfg(test)]
+mod test {
+    use super::{ReaderUtil, ReaderByteConversions, WriterByteConversions};
+    use u64;
+    use i32;
+    use option::{Some, None};
+    use cell::Cell;
+    use rt::io::mem::{MemReader, MemWriter};
+    use rt::io::mock::MockReader;
+    use rt::io::{read_error, placeholder_error};
+
+    #[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 = MockReader::new();
+        let count = Cell(0);
+        reader.read = |buf| {
+            do count.with_mut_ref |count| {
+                if *count == 0 {
+                    *count = 1;
+                    Some(0)
+                } else {
+                    buf[0] = 10;
+                    Some(1)
+                }
+            }
+        };
+        let byte = reader.read_byte();
+        assert!(byte == Some(10));
+    }
+
+    #[test]
+    fn read_byte_eof() {
+        let mut reader = MockReader::new();
+        reader.read = |_| None;
+        let byte = reader.read_byte();
+        assert!(byte == None);
+    }
+
+    #[test]
+    fn read_byte_error() {
+        let mut reader = MockReader::new();
+        reader.read = |_| {
+            read_error::cond.raise(placeholder_error());
+            None
+        };
+        do read_error::cond.trap(|_| {
+        }).in {
+            let byte = reader.read_byte();
+            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 = MockReader::new();
+        let count = Cell(0);
+        reader.read = |buf| {
+            do count.with_mut_ref |count| {
+                if *count == 0 {
+                    *count = 1;
+                    buf[0] = 10;
+                    buf[1] = 11;
+                    Some(2)
+                } else {
+                    buf[0] = 12;
+                    buf[1] = 13;
+                    Some(2)
+                }
+            }
+        };
+        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 read_error::cond.trap(|_| {
+        }).in {
+            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 = MockReader::new();
+        let count = Cell(0);
+        reader.read = |buf| {
+            do count.with_mut_ref |count| {
+                if *count == 0 {
+                    *count = 1;
+                    buf[0] = 10;
+                    buf[1] = 11;
+                    Some(2)
+                } else {
+                    buf[0] = 12;
+                    buf[1] = 13;
+                    Some(2)
+                }
+            }
+        };
+        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 read_error::cond.trap(|_| {
+        }).in {
+            reader.push_bytes(&mut buf, 4);
+            assert!(buf == ~[8, 9, 10, 11]);
+        }
+    }
+
+    #[test]
+    fn push_bytes_error() {
+        let mut reader = MockReader::new();
+        let count = Cell(0);
+        reader.read = |buf| {
+            do count.with_mut_ref |count| {
+                if *count == 0 {
+                    *count = 1;
+                    buf[0] = 10;
+                    Some(1)
+                } else {
+                    read_error::cond.raise(placeholder_error());
+                    None
+                }
+            }
+        };
+        let mut buf = ~[8, 9];
+        do read_error::cond.trap(|_| { } ).in {
+            reader.push_bytes(&mut buf, 4);
+        }
+        assert!(buf == ~[8, 9, 10]);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn push_bytes_fail_reset_len() {
+        use unstable::finally::Finally;
+
+        // push_bytes unsafely sets the vector length. This is testing that
+        // upon failure the length is reset correctly.
+        let mut reader = MockReader::new();
+        let count = Cell(0);
+        reader.read = |buf| {
+            do count.with_mut_ref |count| {
+                if *count == 0 {
+                    *count = 1;
+                    buf[0] = 10;
+                    Some(1)
+                } else {
+                    read_error::cond.raise(placeholder_error());
+                    None
+                }
+            }
+        };
+        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
+            rtassert!(*buf == ~[8, 9, 10]);
+        }
+    }
+
+    #[test]
+    fn read_to_end() {
+        let mut reader = MockReader::new();
+        let count = Cell(0);
+        reader.read = |buf| {
+            do count.with_mut_ref |count| {
+                if *count == 0 {
+                    *count = 1;
+                    buf[0] = 10;
+                    buf[1] = 11;
+                    Some(2)
+                } else if *count == 1 {
+                    *count = 2;
+                    buf[0] = 12;
+                    buf[1] = 13;
+                    Some(2)
+                } else {
+                    None
+                }
+            }
+        };
+        let buf = reader.read_to_end();
+        assert!(buf == ~[10, 11, 12, 13]);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn read_to_end_error() {
+        let mut reader = MockReader::new();
+        let count = Cell(0);
+        reader.read = |buf| {
+            do count.with_mut_ref |count| {
+                if *count == 0 {
+                    *count = 1;
+                    buf[0] = 10;
+                    buf[1] = 11;
+                    Some(2)
+                } else {
+                    read_error::cond.raise(placeholder_error());
+                    None
+                }
+            }
+        };
+        let buf = reader.read_to_end();
+        assert!(buf == ~[10, 11]);
+    }
+
+    // XXX: Some problem with resolve here
+    /*#[test]
+    fn test_read_write_le() {
+        let uints = [0, 1, 2, 42, 10_123, 100_123_456, u64::max_value];
+
+        let mut writer = MemWriter::new();
+        for uints.each |i| {
+            writer.write_le_u64(*i);
+        }
+
+        let mut reader = MemReader::new(writer.inner());
+        for uints.each |i| {
+            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 uints.each |i| {
+            writer.write_be_u64(*i);
+        }
+
+        let mut reader = MemReader::new(writer.inner());
+        for uints.each |i| {
+            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 ints.each |i| {
+            writer.write_be_i32(*i);
+        }
+
+        let mut reader = MemReader::new(writer.inner());
+        for ints.each |i| {
+            // 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/file.rs b/src/libstd/rt/io/file.rs
new file mode 100644
index 00000000000..1f61cf25fbd
--- /dev/null
+++ b/src/libstd/rt/io/file.rs
@@ -0,0 +1,79 @@
+// 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 prelude::*;
+use super::support::PathLike;
+use super::{Reader, Writer, Seek};
+use super::SeekStyle;
+
+/// # XXX
+/// * Ugh, this is ridiculous. What is the best way to represent these options?
+enum FileMode {
+    /// Opens an existing file. IoError if file does not exist.
+    Open,
+    /// Creates a file. IoError if file exists.
+    Create,
+    /// Opens an existing file or creates a new one.
+    OpenOrCreate,
+    /// Opens an existing file or creates a new one, positioned at EOF.
+    Append,
+    /// Opens an existing file, truncating it to 0 bytes.
+    Truncate,
+    /// Opens an existing file or creates a new one, truncating it to 0 bytes.
+    CreateOrTruncate,
+}
+
+enum FileAccess {
+    Read,
+    Write,
+    ReadWrite
+}
+
+pub struct FileStream;
+
+impl FileStream {
+    pub fn open<P: PathLike>(_path: &P,
+                             _mode: FileMode,
+                             _access: FileAccess
+                            ) -> Option<FileStream> {
+        fail!()
+    }
+}
+
+impl Reader for FileStream {
+    fn read(&mut self, _buf: &mut [u8]) -> Option<uint> {
+        fail!()
+    }
+
+    fn eof(&mut self) -> bool {
+        fail!()
+    }
+}
+
+impl Writer for FileStream {
+    fn write(&mut self, _v: &[u8]) { fail!() }
+
+    fn flush(&mut self) { fail!() }
+}
+
+impl Seek for FileStream {
+    fn tell(&self) -> u64 { fail!() }
+
+    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
+}
+
+#[test]
+#[ignore]
+fn super_simple_smoke_test_lets_go_read_some_files_and_have_a_good_time() {
+    let message = "it's alright. have a good time";
+    let filename = &Path("test.txt");
+    let mut outstream = FileStream::open(filename, Create, Read).unwrap();
+    outstream.write(message.to_bytes());
+}
diff --git a/src/libstd/rt/io/flate.rs b/src/libstd/rt/io/flate.rs
new file mode 100644
index 00000000000..db2683dc85d
--- /dev/null
+++ b/src/libstd/rt/io/flate.rs
@@ -0,0 +1,121 @@
+// 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
+
+// NOTE: These ultimately belong somewhere else
+
+use prelude::*;
+use super::*;
+
+/// A Writer decorator that compresses using the 'deflate' scheme
+pub struct DeflateWriter<W> {
+    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> {
+    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;
+
+    #[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.to_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).get();
+        assert_eq!(bytes_read, in_bytes.len());
+        let out_msg = str::from_bytes(out_bytes);
+        assert!(in_msg == out_msg);
+    }
+}
diff --git a/src/libstd/rt/io/mem.rs b/src/libstd/rt/io/mem.rs
new file mode 100644
index 00000000000..b2701c1fdc3
--- /dev/null
+++ b/src/libstd/rt/io/mem.rs
@@ -0,0 +1,221 @@
+// 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 prelude::*;
+use super::*;
+use cmp::min;
+
+/// Writes to an owned, growable byte vector
+pub struct MemWriter {
+    buf: ~[u8]
+}
+
+impl MemWriter {
+    pub fn new() -> MemWriter { MemWriter { buf: ~[] } }
+}
+
+impl Writer for MemWriter {
+    fn write(&mut self, buf: &[u8]) {
+        self.buf.push_all(buf)
+    }
+
+    fn flush(&mut self) { /* no-op */ }
+}
+
+impl Seek for MemWriter {
+    fn tell(&self) -> u64 { self.buf.len() as u64 }
+
+    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
+}
+
+impl Decorator<~[u8]> for MemWriter {
+
+    fn inner(self) -> ~[u8] {
+        match self {
+            MemWriter { buf: buf } => buf
+        }
+    }
+
+    fn inner_ref<'a>(&'a self) -> &'a ~[u8] {
+        match *self {
+            MemWriter { buf: ref buf } => buf
+        }
+    }
+
+    fn inner_mut_ref<'a>(&'a mut self) -> &'a mut ~[u8] {
+        match *self {
+            MemWriter { buf: ref mut buf } => buf
+        }
+    }
+}
+
+/// Reads from an owned byte vector
+pub struct MemReader {
+    buf: ~[u8],
+    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 = vec::mut_slice(buf, 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
+struct BufWriter<'self> {
+    buf: &'self mut [u8],
+    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
+struct BufReader<'self> {
+    buf: &'self [u8],
+    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> { fail!() }
+
+    fn eof(&mut self) -> bool { fail!() }
+}
+
+impl<'self> Seek for BufReader<'self> {
+    fn tell(&self) -> u64 { fail!() }
+
+    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
+}
+
+#[cfg(test)]
+mod test {
+    use prelude::*;
+    use super::*;
+
+    #[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(), ~[0, 1, 2, 3, 4, 5 , 6, 7]);
+    }
+
+    #[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());
+    }
+}
diff --git a/src/libstd/rt/io/mod.rs b/src/libstd/rt/io/mod.rs
new file mode 100644
index 00000000000..0ec51a3aa94
--- /dev/null
+++ b/src/libstd/rt/io/mod.rs
@@ -0,0 +1,504 @@
+// 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` and called 'streams',
+and automatically implement trait `Stream`.
+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 core::io, not core::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 continiues.
+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` conditon 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 withi/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
+* File vs. FileStream? File is shorter but could also be used for getting file info
+  - maybe File is for general file querying and *also* has a static `open` method
+* 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 prelude::*;
+
+// 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::file::FileStream;
+pub use self::net::ip::IpAddr;
+pub use self::net::tcp::TcpListener;
+pub use self::net::tcp::TcpStream;
+pub use self::net::udp::UdpStream;
+
+// Some extension traits that all Readers and Writers get.
+pub use self::extensions::ReaderUtil;
+pub use self::extensions::ReaderByteConversions;
+pub use self::extensions::WriterByteConversions;
+
+/// Synchronous, non-blocking file I/O.
+pub mod file;
+
+/// Synchronous, non-blocking network I/O.
+pub mod net {
+    pub mod tcp;
+    pub mod udp;
+    pub mod ip;
+    #[cfg(unix)]
+    pub mod unix;
+    pub mod http;
+}
+
+/// 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
+mod extensions;
+
+/// Non-I/O things needed by the I/O module
+mod support;
+
+/// Thread-blocking implementations
+pub mod native {
+    /// Posix file I/O
+    pub mod file;
+    /// # XXX - implement this
+    pub mod stdio { }
+    /// Sockets
+    /// # XXX - implement this
+    pub mod net {
+        pub mod tcp { }
+        pub mod udp { }
+        #[cfg(unix)]
+        pub mod unix { }
+    }
+}
+
+/// Mock implementations for testing
+mod mock;
+
+/// The default buffer size for various I/O operations
+/// XXX: Not pub
+pub 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>
+}
+
+#[deriving(Eq)]
+pub enum IoErrorKind {
+    PreviousIoError,
+    OtherIoError,
+    EndOfFile,
+    FileNotFound,
+    PermissionDenied,
+    ConnectionFailed,
+    Closed,
+    ConnectionRefused,
+    ConnectionReset,
+    BrokenPipe
+}
+
+// XXX: Can't put doc comments on macros
+// Raised by `I/O` operations on error.
+condition! {
+    // FIXME (#6009): uncomment `pub` after expansion support lands.
+    /*pub*/ io_error: super::IoError -> ();
+}
+
+// XXX: Can't put doc comments on macros
+// Raised by `read` on error
+condition! {
+    // FIXME (#6009): uncomment `pub` after expansion support lands.
+    /*pub*/ read_error: super::IoError -> ();
+}
+
+pub trait Reader {
+    /// 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 `read_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 = FileStream::new()
+    ///     while !reader.eof() {
+    ///         println(reader.read_line());
+    ///     }
+    ///
+    /// # Failue
+    ///
+    /// Returns `true` on failure.
+    fn eof(&mut self) -> bool;
+}
+
+pub trait Writer {
+    /// Write the given buffer
+    ///
+    /// # Failure
+    ///
+    /// Raises the `io_error` condition on error
+    fn write(&mut self, buf: &[u8]);
+
+    /// Flush output
+    fn flush(&mut self);
+}
+
+pub trait Stream: Reader + Writer { }
+
+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 {
+    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 listens for connections
+pub trait Listener<S> {
+    /// Wait for and accept an incoming connection
+    ///
+    /// Returns `None` on timeout.
+    ///
+    /// # Failure
+    ///
+    /// Raises `io_error` condition. If the condition is handled,
+    /// then `accept` returns `None`.
+    fn accept(&mut self) -> Option<S>;
+}
+
+/// 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
+            }
+        }
+        _ => fail!()
+    }
+}
+
+pub fn placeholder_error() -> IoError {
+    IoError {
+        kind: OtherIoError,
+        desc: "Placeholder error. You shouldn't be seeing this",
+        detail: None
+    }
+}
\ No newline at end of file
diff --git a/src/libstd/rt/io/native/file.rs b/src/libstd/rt/io/native/file.rs
new file mode 100644
index 00000000000..31c90336a24
--- /dev/null
+++ b/src/libstd/rt/io/native/file.rs
@@ -0,0 +1,74 @@
+// 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
+
+use prelude::*;
+use super::super::*;
+use libc::{c_int, FILE};
+
+#[allow(non_camel_case_types)]
+pub type fd_t = c_int;
+
+// Make this a newtype so we can't do I/O on arbitrary integers
+pub struct FileDesc(fd_t);
+
+impl FileDesc {
+    /// Create a `FileDesc` from an open C file descriptor.
+    ///
+    /// The `FileDesc` takes ownership of the file descriptor
+    /// and will close it upon destruction.
+    pub fn new(_fd: fd_t) -> FileDesc { fail!() }
+}
+
+impl Reader for FileDesc {
+    fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail!() }
+
+    fn eof(&mut self) -> bool { fail!() }
+}
+
+impl Writer for FileDesc {
+    fn write(&mut self, _buf: &[u8]) { fail!() }
+
+    fn flush(&mut self) { fail!() }
+}
+
+impl Seek for FileDesc {
+    fn tell(&self) -> u64 { fail!() }
+
+    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
+}
+
+pub struct CFile(*FILE);
+
+impl CFile {
+    /// Create a `CFile` from an open `FILE` pointer.
+    ///
+    /// The `CFile` takes ownership of the file descriptor
+    /// and will close it upon destruction.
+    pub fn new(_file: *FILE) -> CFile { fail!() }
+}
+
+impl Reader for CFile {
+    fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail!() }
+
+    fn eof(&mut self) -> bool { fail!() }
+}
+
+impl Writer for CFile {
+    fn write(&mut self, _buf: &[u8]) { fail!() }
+
+    fn flush(&mut self) { fail!() }
+}
+
+impl Seek for CFile {
+    fn tell(&self) -> u64 { fail!() }
+    fn seek(&mut self, _pos: i64, _style: SeekStyle) { fail!() }
+}
diff --git a/src/libstd/rt/io/net/http.rs b/src/libstd/rt/io/net/http.rs
new file mode 100644
index 00000000000..c693cfaab67
--- /dev/null
+++ b/src/libstd/rt/io/net/http.rs
@@ -0,0 +1,29 @@
+// 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.
+
+//! Simple HTTP client and server
+
+// XXX This should not be in core
+
+struct HttpServer;
+
+#[cfg(test)]
+mod test {
+    use unstable::run_in_bare_thread;
+
+    #[test] #[ignore]
+    fn smoke_test() {
+        do run_in_bare_thread {
+        }
+
+        do run_in_bare_thread {
+        }
+    }
+}
diff --git a/src/libstd/rt/io/net/ip.rs b/src/libstd/rt/io/net/ip.rs
new file mode 100644
index 00000000000..df1dfe4d38a
--- /dev/null
+++ b/src/libstd/rt/io/net/ip.rs
@@ -0,0 +1,14 @@
+// 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 enum IpAddr {
+    Ipv4(u8, u8, u8, u8, u16),
+    Ipv6
+}
diff --git a/src/libstd/rt/io/net/tcp.rs b/src/libstd/rt/io/net/tcp.rs
new file mode 100644
index 00000000000..f7c03c13a58
--- /dev/null
+++ b/src/libstd/rt/io/net/tcp.rs
@@ -0,0 +1,359 @@
+// 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::IpAddr;
+use rt::io::{Reader, Writer, Listener};
+use rt::io::{io_error, read_error, EndOfFile};
+use rt::rtio::{IoFactory, IoFactoryObject,
+               RtioTcpListener, RtioTcpListenerObject,
+               RtioTcpStream, RtioTcpStreamObject};
+use rt::local::Local;
+
+pub struct TcpStream {
+    rtstream: ~RtioTcpStreamObject
+}
+
+impl TcpStream {
+    fn new(s: ~RtioTcpStreamObject) -> TcpStream {
+        TcpStream {
+            rtstream: s
+        }
+    }
+
+    pub fn connect(addr: IpAddr) -> Option<TcpStream> {
+        let stream = unsafe {
+            rtdebug!("borrowing io to connect");
+            let io = Local::unsafe_borrow::<IoFactoryObject>();
+            rtdebug!("about to connect");
+            (*io).tcp_connect(addr)
+        };
+
+        match stream {
+            Ok(s) => {
+                Some(TcpStream::new(s))
+            }
+            Err(ioerr) => {
+                rtdebug!("failed to connect: %?", ioerr);
+                io_error::cond.raise(ioerr);
+                return None;
+            }
+        }
+    }
+}
+
+impl Reader for TcpStream {
+    fn read(&mut self, buf: &mut [u8]) -> Option<uint> {
+        let bytes_read = self.rtstream.read(buf);
+        match bytes_read {
+            Ok(read) => Some(read),
+            Err(ioerr) => {
+                // EOF is indicated by returning None
+                if ioerr.kind != EndOfFile {
+                    read_error::cond.raise(ioerr);
+                }
+                return None;
+            }
+        }
+    }
+
+    fn eof(&mut self) -> bool { fail!() }
+}
+
+impl Writer for TcpStream {
+    fn write(&mut self, buf: &[u8]) {
+        let res = self.rtstream.write(buf);
+        match res {
+            Ok(_) => (),
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+            }
+        }
+    }
+
+    fn flush(&mut self) { fail!() }
+}
+
+pub struct TcpListener {
+    rtlistener: ~RtioTcpListenerObject,
+}
+
+impl TcpListener {
+    pub fn bind(addr: IpAddr) -> Option<TcpListener> {
+        let listener = unsafe {
+            let io = Local::unsafe_borrow::<IoFactoryObject>();
+            (*io).tcp_bind(addr)
+        };
+        match listener {
+            Ok(l) => {
+                Some(TcpListener {
+                    rtlistener: l
+                })
+            }
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                return None;
+            }
+        }
+    }
+}
+
+impl Listener<TcpStream> for TcpListener {
+    fn accept(&mut self) -> Option<TcpStream> {
+        let rtstream = self.rtlistener.accept();
+        match rtstream {
+            Ok(s) => {
+                Some(TcpStream::new(s))
+            }
+            Err(ioerr) => {
+                io_error::cond.raise(ioerr);
+                return None;
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use int;
+    use cell::Cell;
+    use rt::test::*;
+    use rt::io::net::ip::Ipv4;
+    use rt::io::*;
+
+    #[test] #[ignore]
+    fn bind_error() {
+        do run_in_newsched_task {
+            let mut called = false;
+            do io_error::cond.trap(|e| {
+                assert!(e.kind == PermissionDenied);
+                called = true;
+            }).in {
+                let addr = Ipv4(0, 0, 0, 0, 1);
+                let listener = TcpListener::bind(addr);
+                assert!(listener.is_none());
+            }
+            assert!(called);
+        }
+    }
+
+    #[test]
+    fn connect_error() {
+        do run_in_newsched_task {
+            let mut called = false;
+            do io_error::cond.trap(|e| {
+                assert!(e.kind == ConnectionRefused);
+                called = true;
+            }).in {
+                let addr = Ipv4(0, 0, 0, 0, 1);
+                let stream = TcpStream::connect(addr);
+                assert!(stream.is_none());
+            }
+            assert!(called);
+        }
+    }
+
+    #[test]
+    fn smoke_test() {
+        do run_in_newsched_task {
+            let addr = next_test_ip4();
+
+            do spawntask_immediately {
+                let mut listener = TcpListener::bind(addr);
+                let mut stream = listener.accept();
+                let mut buf = [0];
+                stream.read(buf);
+                assert!(buf[0] == 99);
+            }
+
+            do spawntask_immediately {
+                let mut stream = TcpStream::connect(addr);
+                stream.write([99]);
+            }
+        }
+    }
+
+    #[test]
+    fn read_eof() {
+        do run_in_newsched_task {
+            let addr = next_test_ip4();
+
+            do spawntask_immediately {
+                let mut listener = TcpListener::bind(addr);
+                let mut stream = listener.accept();
+                let mut buf = [0];
+                let nread = stream.read(buf);
+                assert!(nread.is_none());
+            }
+
+            do spawntask_immediately {
+                let _stream = TcpStream::connect(addr);
+                // Close
+            }
+        }
+    }
+
+    #[test]
+    fn read_eof_twice() {
+        do run_in_newsched_task {
+            let addr = next_test_ip4();
+
+            do spawntask_immediately {
+                let mut listener = TcpListener::bind(addr);
+                let mut stream = listener.accept();
+                let mut buf = [0];
+                let nread = stream.read(buf);
+                assert!(nread.is_none());
+                let nread = stream.read(buf);
+                assert!(nread.is_none());
+            }
+
+            do spawntask_immediately {
+                let _stream = TcpStream::connect(addr);
+                // Close
+            }
+        }
+    }
+
+    #[test]
+    fn write_close() {
+        do run_in_newsched_task {
+            let addr = next_test_ip4();
+
+            do spawntask_immediately {
+                let mut listener = TcpListener::bind(addr);
+                let mut stream = listener.accept();
+                let buf = [0];
+                loop {
+                    let mut stop = false;
+                    do io_error::cond.trap(|e| {
+                        // NB: ECONNRESET on linux, EPIPE on mac
+                        assert!(e.kind == ConnectionReset || e.kind == BrokenPipe);
+                        stop = true;
+                    }).in {
+                        stream.write(buf);
+                    }
+                    if stop { break }
+                }
+            }
+
+            do spawntask_immediately {
+                let _stream = TcpStream::connect(addr);
+                // Close
+            }
+        }
+    }
+
+    #[test]
+    fn multiple_connect_serial() {
+        do run_in_newsched_task {
+            let addr = next_test_ip4();
+            let max = 10;
+
+            do spawntask_immediately {
+                let mut listener = TcpListener::bind(addr);
+                for max.times {
+                    let mut stream = listener.accept();
+                    let mut buf = [0];
+                    stream.read(buf);
+                    assert_eq!(buf[0], 99);
+                }
+            }
+
+            do spawntask_immediately {
+                for max.times {
+                    let mut stream = TcpStream::connect(addr);
+                    stream.write([99]);
+                }
+            }
+        }
+    }
+
+    #[test]
+    fn multiple_connect_interleaved_greedy_schedule() {
+        do run_in_newsched_task {
+            let addr = next_test_ip4();
+            static MAX: int = 10;
+
+            do spawntask_immediately {
+                let mut listener = TcpListener::bind(addr);
+                for int::range(0, MAX) |i| {
+                    let stream = Cell(listener.accept());
+                    rtdebug!("accepted");
+                    // Start another task to handle the connection
+                    do spawntask_immediately {
+                        let mut stream = stream.take();
+                        let mut buf = [0];
+                        stream.read(buf);
+                        assert!(buf[0] == i as u8);
+                        rtdebug!("read");
+                    }
+                }
+            }
+
+            connect(0, addr);
+
+            fn connect(i: int, addr: IpAddr) {
+                if i == MAX { return }
+
+                do spawntask_immediately {
+                    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() {
+        do run_in_newsched_task {
+            let addr = next_test_ip4();
+            static MAX: int = 10;
+
+            do spawntask_immediately {
+                let mut listener = TcpListener::bind(addr);
+                for int::range(0, MAX) |_| {
+                    let stream = Cell(listener.accept());
+                    rtdebug!("accepted");
+                    // 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");
+                    }
+                }
+            }
+
+            connect(0, addr);
+
+            fn connect(i: int, addr: IpAddr) {
+                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]);
+                }
+            }
+        }
+    }
+
+}
diff --git a/src/libstd/rt/io/net/udp.rs b/src/libstd/rt/io/net/udp.rs
new file mode 100644
index 00000000000..bb5457e334d
--- /dev/null
+++ b/src/libstd/rt/io/net/udp.rs
@@ -0,0 +1,45 @@
+// 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 prelude::*;
+use super::super::*;
+use super::ip::IpAddr;
+
+pub struct UdpStream;
+
+impl UdpStream {
+    pub fn connect(_addr: IpAddr) -> Option<UdpStream> {
+        fail!()
+    }
+}
+
+impl Reader for UdpStream {
+    fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail!() }
+
+    fn eof(&mut self) -> bool { fail!() }
+}
+
+impl Writer for UdpStream {
+    fn write(&mut self, _buf: &[u8]) { fail!() }
+
+    fn flush(&mut self) { fail!() }
+}
+
+pub struct UdpListener;
+
+impl UdpListener {
+    pub fn bind(_addr: IpAddr) -> Option<UdpListener> {
+        fail!()
+    }
+}
+
+impl Listener<UdpStream> for UdpListener {
+    fn accept(&mut self) -> Option<UdpStream> { fail!() }
+}
diff --git a/src/libstd/rt/io/net/unix.rs b/src/libstd/rt/io/net/unix.rs
new file mode 100644
index 00000000000..b85b7dd059d
--- /dev/null
+++ b/src/libstd/rt/io/net/unix.rs
@@ -0,0 +1,45 @@
+// 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 prelude::*;
+use super::super::*;
+use super::super::support::PathLike;
+
+pub struct UnixStream;
+
+impl UnixStream {
+    pub fn connect<P: PathLike>(_path: &P) -> Option<UnixStream> {
+        fail!()
+    }
+}
+
+impl Reader for UnixStream {
+    fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail!() }
+
+    fn eof(&mut self) -> bool { fail!() }
+}
+
+impl Writer for UnixStream {
+    fn write(&mut self, _v: &[u8]) { fail!() }
+
+    fn flush(&mut self) { fail!() }
+}
+
+pub struct UnixListener;
+
+impl UnixListener {
+    pub fn bind<P: PathLike>(_path: &P) -> Option<UnixListener> {
+        fail!()
+    }
+}
+
+impl Listener<UnixStream> for UnixListener {
+    fn accept(&mut self) -> Option<UnixStream> { fail!() }
+}
diff --git a/src/libstd/rt/io/option.rs b/src/libstd/rt/io/option.rs
new file mode 100644
index 00000000000..d71ef55d3ad
--- /dev/null
+++ b/src/libstd/rt/io/option.rs
@@ -0,0 +1,153 @@
+// 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<FileStream>` to be used
+//! as a `Reader` without unwrapping the option first.
+//!
+//! # XXX Seek and Close
+
+use option::*;
+use super::{Reader, Writer, Listener};
+use super::{standard_error, PreviousIoError, io_error, read_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 => {
+                read_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<L: Listener<S>, S> Listener<S> for Option<L> {
+    fn accept(&mut self) -> Option<S> {
+        match *self {
+            Some(ref mut listener) => listener.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, read_error};
+
+    #[test]
+    fn test_option_writer() {
+        do run_in_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_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;
+            }).in {
+                writer.write([0, 0, 0]);
+            }
+            assert!(called);
+
+            let mut called = false;
+            do io_error::cond.trap(|err| {
+                assert_eq!(err.kind, PreviousIoError);
+                called = true;
+            }).in {
+                writer.flush();
+            }
+            assert!(called);
+        }
+    }
+
+    #[test]
+    fn test_option_reader() {
+        do run_in_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 read_error::cond.trap(|err| {
+            assert_eq!(err.kind, PreviousIoError);
+            called = true;
+        }).in {
+            reader.read(buf);
+        }
+        assert!(called);
+
+        let mut called = false;
+        do io_error::cond.trap(|err| {
+            assert_eq!(err.kind, PreviousIoError);
+            called = true;
+        }).in {
+            assert!(reader.eof());
+        }
+        assert!(called);
+    }
+}
diff --git a/src/libstd/rt/io/stdio.rs b/src/libstd/rt/io/stdio.rs
new file mode 100644
index 00000000000..247fe954408
--- /dev/null
+++ b/src/libstd/rt/io/stdio.rs
@@ -0,0 +1,53 @@
+// 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 prelude::*;
+use super::{Reader, Writer};
+
+pub fn stdin() -> StdReader { fail!() }
+
+pub fn stdout() -> StdWriter { fail!() }
+
+pub fn stderr() -> StdReader { fail!() }
+
+pub fn print(_s: &str) { fail!() }
+
+pub fn println(_s: &str) { fail!() }
+
+pub enum StdStream {
+    StdIn,
+    StdOut,
+    StdErr
+}
+
+pub struct StdReader;
+
+impl StdReader {
+    pub fn new(_stream: StdStream) -> StdReader { fail!() }
+}
+
+impl Reader for StdReader {
+    fn read(&mut self, _buf: &mut [u8]) -> Option<uint> { fail!() }
+
+    fn eof(&mut self) -> bool { fail!() }
+}
+
+pub struct StdWriter;
+
+impl StdWriter {
+    pub fn new(_stream: StdStream) -> StdWriter { fail!() }
+}
+
+impl Writer for StdWriter {
+    fn write(&mut self, _buf: &[u8]) { fail!() }
+
+    fn flush(&mut self) { fail!() }
+}
+
diff --git a/src/libstd/rt/io/support.rs b/src/libstd/rt/io/support.rs
new file mode 100644
index 00000000000..7bace5d6df2
--- /dev/null
+++ b/src/libstd/rt/io/support.rs
@@ -0,0 +1,42 @@
+// 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 path::*;
+
+pub trait PathLike {
+    fn path_as_str<T>(&self, f: &fn(&str) -> T) -> T;
+}
+
+impl<'self> PathLike for &'self str {
+    fn path_as_str<T>(&self, f: &fn(&str) -> T) -> T {
+        f(*self)
+    }
+}
+
+impl PathLike for Path {
+    fn path_as_str<T>(&self, f: &fn(&str) -> T) -> T {
+        let s = self.to_str();
+        f(s)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use path::*;
+    use super::PathLike;
+
+    #[test]
+    fn path_like_smoke_test() {
+        let expected = "/home";
+        let path = Path(expected);
+        path.path_as_str(|p| assert!(p == expected));
+        path.path_as_str(|p| assert!(p == expected));
+    }
+}
diff --git a/src/libstd/rt/local_heap.rs b/src/libstd/rt/local_heap.rs
new file mode 100644
index 00000000000..6bf228a1b22
--- /dev/null
+++ b/src/libstd/rt/local_heap.rs
@@ -0,0 +1,80 @@
+// 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.
+
+//! The local, garbage collected heap
+
+use libc::{c_void, uintptr_t, size_t};
+use ops::Drop;
+
+type MemoryRegion = c_void;
+type BoxedRegion = c_void;
+
+pub type OpaqueBox = c_void;
+pub type TypeDesc = c_void;
+
+pub struct LocalHeap {
+    memory_region: *MemoryRegion,
+    boxed_region: *BoxedRegion
+}
+
+impl LocalHeap {
+    pub fn new() -> LocalHeap {
+        unsafe {
+            // Don't need synchronization for the single-threaded local heap
+            let synchronized = false as uintptr_t;
+            // XXX: These usually come from the environment
+            let detailed_leaks = false as uintptr_t;
+            let poison_on_free = false as uintptr_t;
+            let region = rust_new_memory_region(synchronized, detailed_leaks, poison_on_free);
+            assert!(region.is_not_null());
+            let boxed = rust_new_boxed_region(region, poison_on_free);
+            assert!(boxed.is_not_null());
+            LocalHeap {
+                memory_region: region,
+                boxed_region: boxed
+            }
+        }
+    }
+
+    pub fn alloc(&mut self, td: *TypeDesc, size: uint) -> *OpaqueBox {
+        unsafe {
+            return rust_boxed_region_malloc(self.boxed_region, td, size as size_t);
+        }
+    }
+
+    pub fn free(&mut self, box: *OpaqueBox) {
+        unsafe {
+            return rust_boxed_region_free(self.boxed_region, box);
+        }
+    }
+}
+
+impl Drop for LocalHeap {
+    fn finalize(&self) {
+        unsafe {
+            rust_delete_boxed_region(self.boxed_region);
+            rust_delete_memory_region(self.memory_region);
+        }
+    }
+}
+
+extern {
+    fn rust_new_memory_region(synchronized: uintptr_t,
+                               detailed_leaks: uintptr_t,
+                               poison_on_free: uintptr_t) -> *MemoryRegion;
+    fn rust_delete_memory_region(region: *MemoryRegion);
+    fn rust_new_boxed_region(region: *MemoryRegion,
+                             poison_on_free: uintptr_t) -> *BoxedRegion;
+    fn rust_delete_boxed_region(region: *BoxedRegion);
+    fn rust_boxed_region_malloc(region: *BoxedRegion,
+                                td: *TypeDesc,
+                                size: size_t) -> *OpaqueBox;
+    fn rust_boxed_region_free(region: *BoxedRegion, box: *OpaqueBox);
+}
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
new file mode 100644
index 00000000000..2fac1df01a4
--- /dev/null
+++ b/src/libstd/rt/mod.rs
@@ -0,0 +1,243 @@
+// 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.
+
+/*! The Rust Runtime, including the task scheduler and I/O
+
+The `rt` module provides the private runtime infrastructure necessary
+to support core language features like the exchange and local heap,
+the garbage collector, logging, local data and unwinding. It also
+implements the default task scheduler and task model. Initialization
+routines are provided for setting up runtime resources in common
+configurations, including that used by `rustc` when generating
+executables.
+
+It is intended that the features provided by `rt` can be factored in a
+way such that the core library can be built with different 'profiles'
+for different use cases, e.g. excluding the task scheduler. A number
+of runtime features though are critical to the functioning of the
+language and an implementation must be provided regardless of the
+execution environment.
+
+Of foremost importance is the global exchange heap, in the module
+`global_heap`. Very little practical Rust code can be written without
+access to the global heap. Unlike most of `rt` the global heap is
+truly a global resource and generally operates independently of the
+rest of the runtime.
+
+All other runtime features are task-local, including the local heap,
+the garbage collector, local storage, logging and the stack unwinder.
+
+The relationship between `rt` and the rest of the core library is
+not entirely clear yet and some modules will be moving into or
+out of `rt` as development proceeds.
+
+Several modules in `core` are clients of `rt`:
+
+* `core::task` - The user-facing interface to the Rust task model.
+* `core::task::local_data` - The interface to local data.
+* `core::gc` - The garbage collector.
+* `core::unstable::lang` - Miscellaneous lang items, some of which rely on `core::rt`.
+* `core::condition` - Uses local data.
+* `core::cleanup` - Local heap destruction.
+* `core::io` - In the future `core::io` will use an `rt` implementation.
+* `core::logging`
+* `core::pipes`
+* `core::comm`
+* `core::stackwalk`
+
+*/
+
+#[doc(hidden)];
+
+use ptr::Ptr;
+
+/// The global (exchange) heap.
+pub mod global_heap;
+
+/// Implementations of language-critical runtime features like @.
+pub mod task;
+
+/// The coroutine task scheduler, built on the `io` event loop.
+mod sched;
+
+/// Synchronous I/O.
+#[path = "io/mod.rs"]
+pub mod io;
+
+/// The EventLoop and internal synchronous I/O interface.
+mod rtio;
+
+/// libuv and default rtio implementation.
+#[path = "uv/mod.rs"]
+pub mod uv;
+
+/// The Local trait for types that are accessible via thread-local
+/// or task-local storage.
+pub mod local;
+
+/// A parallel work-stealing deque.
+mod work_queue;
+
+/// A parallel queue.
+mod message_queue;
+
+/// Stack segments and caching.
+mod stack;
+
+/// CPU context swapping.
+mod context;
+
+/// Bindings to system threading libraries.
+mod thread;
+
+/// The runtime configuration, read from environment variables
+pub mod env;
+
+/// The local, managed heap
+mod local_heap;
+
+/// The Logger trait and implementations
+pub mod logging;
+
+/// Tools for testing the runtime
+pub mod test;
+
+/// Reference counting
+pub mod rc;
+
+/// A simple single-threaded channel type for passing buffered data between
+/// scheduler and task context
+pub mod tube;
+
+/// Simple reimplementation of core::comm
+pub mod comm;
+
+// FIXME #5248 shouldn't be pub
+/// The runtime needs to be able to put a pointer into thread-local storage.
+pub mod local_ptr;
+
+// FIXME #5248: The import in `sched` doesn't resolve unless this is pub!
+/// Bindings to pthread/windows thread-local storage.
+pub mod thread_local_storage;
+
+
+/// Set up a default runtime configuration, given compiler-supplied arguments.
+///
+/// This is invoked by the `start` _language item_ (unstable::lang) to
+/// run a Rust executable.
+///
+/// # Arguments
+///
+/// * `argc` & `argv` - The argument vector. On Unix this information is used
+///   by os::args.
+/// * `crate_map` - Runtime information about the executing crate, mostly for logging
+///
+/// # Return value
+///
+/// The return value is used as the process return code. 0 on success, 101 on error.
+pub fn start(_argc: int, _argv: **u8, crate_map: *u8, main: ~fn()) -> int {
+
+    use self::sched::{Scheduler, Coroutine};
+    use self::uv::uvio::UvEventLoop;
+
+    init(crate_map);
+
+    let loop_ = ~UvEventLoop::new();
+    let mut sched = ~Scheduler::new(loop_);
+    let main_task = ~Coroutine::new(&mut sched.stack_pool, main);
+
+    sched.enqueue_task(main_task);
+    sched.run();
+
+    return 0;
+}
+
+/// One-time runtime initialization. Currently all this does is set up logging
+/// based on the RUST_LOG environment variable.
+pub fn init(crate_map: *u8) {
+    logging::init(crate_map);
+}
+
+/// Possible contexts in which Rust code may be executing.
+/// Different runtime services are available depending on context.
+/// Mostly used for determining if we're using the new scheduler
+/// or the old scheduler.
+#[deriving(Eq)]
+pub enum RuntimeContext {
+    // Only the exchange heap is available
+    GlobalContext,
+    // The scheduler may be accessed
+    SchedulerContext,
+    // Full task services, e.g. local heap, unwinding
+    TaskContext,
+    // Running in an old-style task
+    OldTaskContext
+}
+
+/// Determine the current RuntimeContext
+pub fn context() -> RuntimeContext {
+
+    use task::rt::rust_task;
+    use self::local::Local;
+    use self::sched::Scheduler;
+
+    // XXX: Hitting TLS twice to check if the scheduler exists
+    // then to check for the task is not good for perf
+    if unsafe { rust_try_get_task().is_not_null() } {
+        return OldTaskContext;
+    } else {
+        if Local::exists::<Scheduler>() {
+            let context = ::cell::empty_cell();
+            do Local::borrow::<Scheduler> |sched| {
+                if sched.in_task_context() {
+                    context.put_back(TaskContext);
+                } else {
+                    context.put_back(SchedulerContext);
+                }
+            }
+            return context.take();
+        } else {
+            return GlobalContext;
+        }
+    }
+
+    pub extern {
+        #[rust_stack]
+        fn rust_try_get_task() -> *rust_task;
+    }
+}
+
+#[test]
+fn test_context() {
+    use unstable::run_in_bare_thread;
+    use self::sched::{Scheduler, Coroutine};
+    use rt::uv::uvio::UvEventLoop;
+    use cell::Cell;
+    use rt::local::Local;
+
+    assert_eq!(context(), OldTaskContext);
+    do run_in_bare_thread {
+        assert_eq!(context(), GlobalContext);
+        let mut sched = ~UvEventLoop::new_scheduler();
+        let task = ~do Coroutine::new(&mut sched.stack_pool) {
+            assert_eq!(context(), TaskContext);
+            let sched = Local::take::<Scheduler>();
+            do sched.deschedule_running_task_and_then() |task| {
+                assert_eq!(context(), SchedulerContext);
+                let task = Cell(task);
+                do Local::borrow::<Scheduler> |sched| {
+                    sched.enqueue_task(task.take());
+                }
+            }
+        };
+        sched.enqueue_task(task);
+        sched.run();
+    }
+}
diff --git a/src/libstd/rt/rtio.rs b/src/libstd/rt/rtio.rs
new file mode 100644
index 00000000000..4b5eda22ff5
--- /dev/null
+++ b/src/libstd/rt/rtio.rs
@@ -0,0 +1,45 @@
+// 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::*;
+use result::*;
+
+use rt::io::IoError;
+use super::io::net::ip::IpAddr;
+use rt::uv::uvio;
+
+// XXX: ~object doesn't work currently so these are some placeholder
+// types to use instead
+pub type EventLoopObject = uvio::UvEventLoop;
+pub type IoFactoryObject = uvio::UvIoFactory;
+pub type RtioTcpStreamObject = uvio::UvTcpStream;
+pub type RtioTcpListenerObject = uvio::UvTcpListener;
+
+pub trait EventLoop {
+    fn run(&mut self);
+    fn callback(&mut self, ~fn());
+    fn callback_ms(&mut self, ms: u64, ~fn());
+    /// The asynchronous I/O services. Not all event loops may provide one
+    fn io<'a>(&'a mut self) -> Option<&'a mut IoFactoryObject>;
+}
+
+pub trait IoFactory {
+    fn tcp_connect(&mut self, addr: IpAddr) -> Result<~RtioTcpStreamObject, IoError>;
+    fn tcp_bind(&mut self, addr: IpAddr) -> Result<~RtioTcpListenerObject, IoError>;
+}
+
+pub trait RtioTcpListener {
+    fn accept(&mut self) -> Result<~RtioTcpStreamObject, IoError>;
+}
+
+pub trait RtioTcpStream {
+    fn read(&mut self, buf: &mut [u8]) -> Result<uint, IoError>;
+    fn write(&mut self, buf: &[u8]) -> Result<(), IoError>;
+}
diff --git a/src/libstd/rt/stack.rs b/src/libstd/rt/stack.rs
new file mode 100644
index 00000000000..ec56e65931c
--- /dev/null
+++ b/src/libstd/rt/stack.rs
@@ -0,0 +1,76 @@
+// 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 ptr::Ptr;
+use vec;
+use ops::Drop;
+use libc::{c_uint, uintptr_t};
+
+pub struct StackSegment {
+    buf: ~[u8],
+    valgrind_id: c_uint
+}
+
+pub impl StackSegment {
+    fn new(size: uint) -> StackSegment {
+        unsafe {
+            // Crate a block of uninitialized values
+            let mut stack = vec::with_capacity(size);
+            vec::raw::set_len(&mut stack, size);
+
+            let mut stk = StackSegment {
+                buf: stack,
+                valgrind_id: 0
+            };
+
+            // XXX: Using the FFI to call a C macro. Slow
+            stk.valgrind_id = rust_valgrind_stack_register(stk.start(), stk.end());
+            return stk;
+        }
+    }
+
+    /// Point to the low end of the allocated stack
+    fn start(&self) -> *uint {
+      vec::raw::to_ptr(self.buf) as *uint
+    }
+
+    /// Point one word beyond the high end of the allocated stack
+    fn end(&self) -> *uint {
+        vec::raw::to_ptr(self.buf).offset(self.buf.len()) as *uint
+    }
+}
+
+impl Drop for StackSegment {
+    fn finalize(&self) {
+        unsafe {
+            // XXX: Using the FFI to call a C macro. Slow
+            rust_valgrind_stack_deregister(self.valgrind_id);
+        }
+    }
+}
+
+pub struct StackPool(());
+
+impl StackPool {
+    pub fn new() -> StackPool { StackPool(()) }
+
+    fn take_segment(&self, min_size: uint) -> StackSegment {
+        StackSegment::new(min_size)
+    }
+
+    fn give_segment(&self, _stack: StackSegment) {
+    }
+}
+
+extern {
+    fn rust_valgrind_stack_register(start: *uintptr_t, end: *uintptr_t) -> c_uint;
+    fn rust_valgrind_stack_deregister(id: c_uint);
+}
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
new file mode 100644
index 00000000000..0314137fc7f
--- /dev/null
+++ b/src/libstd/rt/task.rs
@@ -0,0 +1,230 @@
+// 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.
+
+//! Language-level runtime services that should reasonably expected
+//! to be available 'everywhere'. Local heaps, GC, unwinding,
+//! local storage, and logging. Even a 'freestanding' Rust would likely want
+//! to implement this.
+
+use prelude::*;
+use libc::{c_void, uintptr_t};
+use cast::transmute;
+use super::sched::Scheduler;
+use rt::local::Local;
+use super::local_heap::LocalHeap;
+use rt::logging::StdErrLogger;
+
+pub struct Task {
+    heap: LocalHeap,
+    gc: GarbageCollector,
+    storage: LocalStorage,
+    logger: StdErrLogger,
+    unwinder: Option<Unwinder>,
+    destroyed: bool
+}
+
+pub struct GarbageCollector;
+pub struct LocalStorage(*c_void, Option<~fn(*c_void)>);
+
+pub struct Unwinder {
+    unwinding: bool,
+}
+
+impl Task {
+    pub fn new() -> Task {
+        Task {
+            heap: LocalHeap::new(),
+            gc: GarbageCollector,
+            storage: LocalStorage(ptr::null(), None),
+            logger: StdErrLogger,
+            unwinder: Some(Unwinder { unwinding: false }),
+            destroyed: false
+        }
+    }
+
+    pub fn without_unwinding() -> Task {
+        Task {
+            heap: LocalHeap::new(),
+            gc: GarbageCollector,
+            storage: LocalStorage(ptr::null(), None),
+            logger: StdErrLogger,
+            unwinder: None,
+            destroyed: false
+        }
+    }
+
+    pub fn run(&mut self, f: &fn()) {
+        // This is just an assertion that `run` was called unsafely
+        // and this instance of Task is still accessible.
+        do Local::borrow::<Task> |task| {
+            assert!(ptr::ref_eq(task, self));
+        }
+
+        match self.unwinder {
+            Some(ref mut unwinder) => {
+                // If there's an unwinder then set up the catch block
+                unwinder.try(f);
+            }
+            None => {
+                // Otherwise, just run the body
+                f()
+            }
+        }
+        self.destroy();
+    }
+
+    /// Must be called manually before finalization to clean up
+    /// thread-local resources. Some of the routines here expect
+    /// Task to be available recursively so this must be
+    /// called unsafely, without removing Task from
+    /// thread-local-storage.
+    fn destroy(&mut self) {
+        // This is just an assertion that `destroy` was called unsafely
+        // and this instance of Task is still accessible.
+        do Local::borrow::<Task> |task| {
+            assert!(ptr::ref_eq(task, self));
+        }
+        match self.storage {
+            LocalStorage(ptr, Some(ref dtor)) => {
+                (*dtor)(ptr)
+            }
+            _ => ()
+        }
+        self.destroyed = true;
+    }
+}
+
+impl Drop for Task {
+    fn finalize(&self) { assert!(self.destroyed) }
+}
+
+// Just a sanity check to make sure we are catching a Rust-thrown exception
+static UNWIND_TOKEN: uintptr_t = 839147;
+
+impl Unwinder {
+    pub fn try(&mut self, f: &fn()) {
+        use sys::Closure;
+
+        unsafe {
+            let closure: Closure = transmute(f);
+            let code = transmute(closure.code);
+            let env = transmute(closure.env);
+
+            let token = rust_try(try_fn, code, env);
+            assert!(token == 0 || token == UNWIND_TOKEN);
+        }
+
+        extern fn try_fn(code: *c_void, env: *c_void) {
+            unsafe {
+                let closure: Closure = Closure {
+                    code: transmute(code),
+                    env: transmute(env),
+                };
+                let closure: &fn() = transmute(closure);
+                closure();
+            }
+        }
+
+        extern {
+            #[rust_stack]
+            fn rust_try(f: *u8, code: *c_void, data: *c_void) -> uintptr_t;
+        }
+    }
+
+    pub fn begin_unwind(&mut self) -> ! {
+        self.unwinding = true;
+        unsafe {
+            rust_begin_unwind(UNWIND_TOKEN);
+            return transmute(());
+        }
+        extern {
+            fn rust_begin_unwind(token: uintptr_t);
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use rt::test::*;
+
+    #[test]
+    fn local_heap() {
+        do run_in_newsched_task() {
+            let a = @5;
+            let b = a;
+            assert!(*a == 5);
+            assert!(*b == 5);
+        }
+    }
+
+    #[test]
+    fn tls() {
+        use local_data::*;
+        do run_in_newsched_task() {
+            unsafe {
+                fn key(_x: @~str) { }
+                local_data_set(key, @~"data");
+                assert!(*local_data_get(key).get() == ~"data");
+                fn key2(_x: @~str) { }
+                local_data_set(key2, @~"data");
+                assert!(*local_data_get(key2).get() == ~"data");
+            }
+        }
+    }
+
+    #[test]
+    fn unwind() {
+        do run_in_newsched_task() {
+            let result = spawntask_try(||());
+            assert!(result.is_ok());
+            let result = spawntask_try(|| fail!());
+            assert!(result.is_err());
+        }
+    }
+
+    #[test]
+    fn rng() {
+        do run_in_newsched_task() {
+            use rand::{rng, Rng};
+            let mut r = rng();
+            let _ = r.next();
+        }
+    }
+
+    #[test]
+    fn logging() {
+        do run_in_newsched_task() {
+            info!("here i am. logging in a newsched task");
+        }
+    }
+
+    #[test]
+    fn comm_oneshot() {
+        use comm::*;
+
+        do run_in_newsched_task {
+            let (port, chan) = oneshot();
+            send_one(chan, 10);
+            assert!(recv_one(port) == 10);
+        }
+    }
+
+    #[test]
+    fn comm_stream() {
+        use comm::*;
+
+        do run_in_newsched_task() {
+            let (port, chan) = stream();
+            chan.send(10);
+            assert!(port.recv() == 10);
+        }
+    }
+}
+
diff --git a/src/libstd/rt/test.rs b/src/libstd/rt/test.rs
new file mode 100644
index 00000000000..c60ae2bfeff
--- /dev/null
+++ b/src/libstd/rt/test.rs
@@ -0,0 +1,192 @@
+// 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 uint;
+use option::*;
+use cell::Cell;
+use result::{Result, Ok, Err};
+use super::io::net::ip::{IpAddr, Ipv4};
+use rt::task::Task;
+use rt::thread::Thread;
+use rt::local::Local;
+
+/// Creates a new scheduler in a new thread and runs a task in it,
+/// then waits for the scheduler to exit. Failure of the task
+/// will abort the process.
+pub fn run_in_newsched_task(f: ~fn()) {
+    use super::sched::*;
+    use unstable::run_in_bare_thread;
+    use rt::uv::uvio::UvEventLoop;
+
+    let f = Cell(f);
+
+    do run_in_bare_thread {
+        let mut sched = ~UvEventLoop::new_scheduler();
+        let task = ~Coroutine::with_task(&mut sched.stack_pool,
+                                         ~Task::without_unwinding(),
+                                         f.take());
+        sched.enqueue_task(task);
+        sched.run();
+    }
+}
+
+/// Test tasks will abort on failure instead of unwinding
+pub fn spawntask(f: ~fn()) {
+    use super::sched::*;
+
+    let mut sched = Local::take::<Scheduler>();
+    let task = ~Coroutine::with_task(&mut sched.stack_pool,
+                                     ~Task::without_unwinding(),
+                                     f);
+    do sched.switch_running_tasks_and_then(task) |task| {
+        let task = Cell(task);
+        let sched = Local::take::<Scheduler>();
+        sched.schedule_new_task(task.take());
+    }
+}
+
+/// Create a new task and run it right now. Aborts on failure
+pub fn spawntask_immediately(f: ~fn()) {
+    use super::sched::*;
+
+    let mut sched = Local::take::<Scheduler>();
+    let task = ~Coroutine::with_task(&mut sched.stack_pool,
+                                     ~Task::without_unwinding(),
+                                     f);
+    do sched.switch_running_tasks_and_then(task) |task| {
+        let task = Cell(task);
+        do Local::borrow::<Scheduler> |sched| {
+            sched.enqueue_task(task.take());
+        }
+    }
+}
+
+/// Create a new task and run it right now. Aborts on failure
+pub fn spawntask_later(f: ~fn()) {
+    use super::sched::*;
+
+    let mut sched = Local::take::<Scheduler>();
+    let task = ~Coroutine::with_task(&mut sched.stack_pool,
+                                     ~Task::without_unwinding(),
+                                     f);
+
+    sched.enqueue_task(task);
+    Local::put(sched);
+}
+
+/// Spawn a task and either run it immediately or run it later
+pub fn spawntask_random(f: ~fn()) {
+    use super::sched::*;
+    use rand::{Rand, rng};
+
+    let mut rng = rng();
+    let run_now: bool = Rand::rand(&mut rng);
+
+    let mut sched = Local::take::<Scheduler>();
+    let task = ~Coroutine::with_task(&mut sched.stack_pool,
+                                     ~Task::without_unwinding(),
+                                     f);
+
+    if run_now {
+        do sched.switch_running_tasks_and_then(task) |task| {
+            let task = Cell(task);
+            do Local::borrow::<Scheduler> |sched| {
+                sched.enqueue_task(task.take());
+            }
+        }
+    } else {
+        sched.enqueue_task(task);
+        Local::put(sched);
+    }
+}
+
+
+/// Spawn a task and wait for it to finish, returning whether it completed successfully or failed
+pub fn spawntask_try(f: ~fn()) -> Result<(), ()> {
+    use cell::Cell;
+    use super::sched::*;
+    use task;
+    use unstable::finally::Finally;
+
+    // Our status variables will be filled in from the scheduler context
+    let mut failed = false;
+    let failed_ptr: *mut bool = &mut failed;
+
+    // Switch to the scheduler
+    let f = Cell(Cell(f));
+    let sched = Local::take::<Scheduler>();
+    do sched.deschedule_running_task_and_then() |old_task| {
+        let old_task = Cell(old_task);
+        let f = f.take();
+        let mut sched = Local::take::<Scheduler>();
+        let new_task = ~do Coroutine::new(&mut sched.stack_pool) {
+            do (|| {
+                (f.take())()
+            }).finally {
+                // Check for failure then resume the parent task
+                unsafe { *failed_ptr = task::failing(); }
+                let sched = Local::take::<Scheduler>();
+                do sched.switch_running_tasks_and_then(old_task.take()) |new_task| {
+                    let new_task = Cell(new_task);
+                    do Local::borrow::<Scheduler> |sched| {
+                        sched.enqueue_task(new_task.take());
+                    }
+                }
+            }
+        };
+
+        sched.resume_task_immediately(new_task);
+    }
+
+    if !failed { Ok(()) } else { Err(()) }
+}
+
+// Spawn a new task in a new scheduler and return a thread handle.
+pub fn spawntask_thread(f: ~fn()) -> Thread {
+    use rt::sched::*;
+    use rt::uv::uvio::UvEventLoop;
+
+    let f = Cell(f);
+    let thread = do Thread::start {
+        let mut sched = ~UvEventLoop::new_scheduler();
+        let task = ~Coroutine::with_task(&mut sched.stack_pool,
+                                         ~Task::without_unwinding(),
+                                         f.take());
+        sched.enqueue_task(task);
+        sched.run();
+    };
+    return thread;
+}
+
+/// Get a port number, starting at 9600, for use in tests
+pub fn next_test_port() -> u16 {
+    unsafe {
+        return rust_dbg_next_port() as u16;
+    }
+    extern {
+        fn rust_dbg_next_port() -> ::libc::uintptr_t;
+    }
+}
+
+/// Get a unique localhost:port pair starting at 9600
+pub fn next_test_ip4() -> IpAddr {
+    Ipv4(127, 0, 0, 1, next_test_port())
+}
+
+/// Get a constant that represents the number of times to repeat stress tests. Default 1.
+pub fn stress_factor() -> uint {
+    use os::getenv;
+
+    match getenv("RUST_RT_STRESS") {
+        Some(val) => uint::from_str(val).get(),
+        None => 1
+    }
+}
+
diff --git a/src/libstd/rt/thread.rs b/src/libstd/rt/thread.rs
new file mode 100644
index 00000000000..0f1ae09bd94
--- /dev/null
+++ b/src/libstd/rt/thread.rs
@@ -0,0 +1,44 @@
+// 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 ops::Drop;
+
+#[allow(non_camel_case_types)] // runtime type
+type raw_thread = libc::c_void;
+
+pub struct Thread {
+    main: ~fn(),
+    raw_thread: *raw_thread
+}
+
+pub impl Thread {
+    fn start(main: ~fn()) -> Thread {
+        fn substart(main: &~fn()) -> *raw_thread {
+            unsafe { rust_raw_thread_start(main) }
+        }
+        let raw = substart(&main);
+        Thread {
+            main: main,
+            raw_thread: raw
+        }
+    }
+}
+
+impl Drop for Thread {
+    fn finalize(&self) {
+        unsafe { rust_raw_thread_join_delete(self.raw_thread) }
+    }
+}
+
+extern {
+    pub unsafe fn rust_raw_thread_start(f: &(~fn())) -> *raw_thread;
+    pub unsafe fn rust_raw_thread_join_delete(thread: *raw_thread);
+}
diff --git a/src/libstd/rt/thread_local_storage.rs b/src/libstd/rt/thread_local_storage.rs
new file mode 100644
index 00000000000..7187d2db41c
--- /dev/null
+++ b/src/libstd/rt/thread_local_storage.rs
@@ -0,0 +1,100 @@
+// 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::c_void;
+#[cfg(unix)]
+use libc::c_int;
+#[cfg(unix)]
+use ptr::null;
+#[cfg(windows)]
+use libc::types::os::arch::extra::{DWORD, LPVOID, BOOL};
+
+#[cfg(unix)]
+pub type Key = pthread_key_t;
+
+#[cfg(unix)]
+pub unsafe fn create(key: &mut Key) {
+    assert_eq!(0, pthread_key_create(key, null()));
+}
+
+#[cfg(unix)]
+pub unsafe fn set(key: Key, value: *mut c_void) {
+    assert_eq!(0, pthread_setspecific(key, value));
+}
+
+#[cfg(unix)]
+pub unsafe fn get(key: Key) -> *mut c_void {
+    pthread_getspecific(key)
+}
+
+#[cfg(target_os="macos")]
+#[allow(non_camel_case_types)] // foreign type
+type pthread_key_t = ::libc::c_ulong;
+
+#[cfg(target_os="linux")]
+#[cfg(target_os="freebsd")]
+#[cfg(target_os="android")]
+#[allow(non_camel_case_types)] // foreign type
+type pthread_key_t = ::libc::c_uint;
+
+#[cfg(unix)]
+extern {
+    #[fast_ffi]
+    fn pthread_key_create(key: *mut pthread_key_t, dtor: *u8) -> c_int;
+    #[fast_ffi]
+    fn pthread_setspecific(key: pthread_key_t, value: *mut c_void) -> c_int;
+    #[fast_ffi]
+    fn pthread_getspecific(key: pthread_key_t) -> *mut c_void;
+}
+
+#[cfg(windows)]
+pub type Key = DWORD;
+
+#[cfg(windows)]
+pub unsafe fn create(key: &mut Key) {
+    static TLS_OUT_OF_INDEXES: DWORD = 0xFFFFFFFF;
+    *key = unsafe { TlsAlloc() };
+    assert!(*key != TLS_OUT_OF_INDEXES);
+}
+
+#[cfg(windows)]
+pub unsafe fn set(key: Key, value: *mut c_void) {
+    unsafe { assert!(0 != TlsSetValue(key, value)) }
+}
+
+#[cfg(windows)]
+pub unsafe fn get(key: Key) -> *mut c_void {
+    TlsGetValue(key)
+}
+
+#[cfg(windows)]
+#[abi = "stdcall"]
+extern "stdcall" {
+       fn TlsAlloc() -> DWORD;
+       fn TlsSetValue(dwTlsIndex: DWORD, lpTlsvalue: LPVOID) -> BOOL;
+       fn TlsGetValue(dwTlsIndex: DWORD) -> LPVOID;
+}
+
+#[test]
+fn tls_smoke_test() {
+    use cast::transmute;
+    unsafe {
+        let mut key = 0;
+        let value = ~20;
+        create(&mut key);
+        set(key, transmute(value));
+        let value: ~int = transmute(get(key));
+        assert_eq!(value, ~20);
+        let value = ~30;
+        set(key, transmute(value));
+        let value: ~int = transmute(get(key));
+        assert_eq!(value, ~30);
+    }
+}
diff --git a/src/libstd/rt/uv/file.rs b/src/libstd/rt/uv/file.rs
new file mode 100644
index 00000000000..2d145055097
--- /dev/null
+++ b/src/libstd/rt/uv/file.rs
@@ -0,0 +1,48 @@
+// 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 prelude::*;
+use ptr::null;
+use libc::c_void;
+use rt::uv::{Request, NativeHandle, Loop, FsCallback};
+use rt::uv::uvll;
+use rt::uv::uvll::*;
+
+pub struct FsRequest(*uvll::uv_fs_t);
+impl Request for FsRequest;
+
+impl FsRequest {
+    fn new() -> FsRequest {
+        let fs_req = unsafe { malloc_req(UV_FS) };
+        assert!(fs_req.is_not_null());
+        let fs_req = fs_req as *uvll::uv_write_t;
+        unsafe { uvll::set_data_for_req(fs_req, null::<()>()); }
+        NativeHandle::from_native_handle(fs_req)
+    }
+
+    fn delete(self) {
+        unsafe { free_req(self.native_handle() as *c_void) }
+    }
+
+    fn open(&mut self, _loop_: &Loop, _cb: FsCallback) {
+    }
+
+    fn close(&mut self, _loop_: &Loop, _cb: FsCallback) {
+    }
+}
+
+impl NativeHandle<*uvll::uv_fs_t> for FsRequest {
+    fn from_native_handle(handle: *uvll:: uv_fs_t) -> FsRequest {
+        FsRequest(handle)
+    }
+    fn native_handle(&self) -> *uvll::uv_fs_t {
+        match self { &FsRequest(ptr) => ptr }
+    }
+}
diff --git a/src/libstd/rt/uv/mod.rs b/src/libstd/rt/uv/mod.rs
new file mode 100644
index 00000000000..2bd657fd864
--- /dev/null
+++ b/src/libstd/rt/uv/mod.rs
@@ -0,0 +1,420 @@
+// 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 to libuv, along with the default implementation of `core::rt::rtio`.
+
+UV types consist of the event loop (Loop), Watchers, Requests and
+Callbacks.
+
+Watchers and Requests encapsulate pointers to uv *handles*, which have
+subtyping relationships with each other.  This subtyping is reflected
+in the bindings with explicit or implicit coercions. For example, an
+upcast from TcpWatcher to StreamWatcher is done with
+`tcp_watcher.as_stream()`. In other cases a callback on a specific
+type of watcher will be passed a watcher of a supertype.
+
+Currently all use of Request types (connect/write requests) are
+encapsulated in the bindings and don't need to be dealt with by the
+caller.
+
+# Safety note
+
+Due to the complex lifecycle of uv handles, as well as compiler bugs,
+this module is not memory safe and requires explicit memory management,
+via `close` and `delete` methods.
+
+*/
+
+use container::Container;
+use option::*;
+use str::raw::from_c_str;
+use to_str::ToStr;
+use ptr::Ptr;
+use libc;
+use vec;
+use ptr;
+use cast;
+use str;
+use libc::{c_void, c_int, size_t, malloc, free};
+use cast::transmute;
+use ptr::null;
+use unstable::finally::Finally;
+
+use rt::io::IoError;
+
+#[cfg(test)] use unstable::run_in_bare_thread;
+
+pub use self::file::FsRequest;
+pub use self::net::{StreamWatcher, TcpWatcher};
+pub use self::idle::IdleWatcher;
+pub use self::timer::TimerWatcher;
+
+/// The implementation of `rtio` for libuv
+pub mod uvio;
+
+/// C bindings to libuv
+pub mod uvll;
+
+pub mod file;
+pub mod net;
+pub mod idle;
+pub mod timer;
+
+/// XXX: Loop(*handle) is buggy with destructors. Normal structs
+/// with dtors may not be destructured, but tuple structs can,
+/// but the results are not correct.
+pub struct Loop {
+    handle: *uvll::uv_loop_t
+}
+
+/// The trait implemented by uv 'watchers' (handles). Watchers are
+/// non-owning wrappers around the uv handles and are not completely
+/// safe - there may be multiple instances for a single underlying
+/// handle.  Watchers are generally created, then `start`ed, `stop`ed
+/// and `close`ed, but due to their complex life cycle may not be
+/// entirely memory safe if used in unanticipated patterns.
+pub trait Watcher { }
+
+pub trait Request { }
+
+/// A type that wraps a native handle
+pub trait NativeHandle<T> {
+    pub fn from_native_handle(T) -> Self;
+    pub fn native_handle(&self) -> T;
+}
+
+pub impl Loop {
+    fn new() -> Loop {
+        let handle = unsafe { uvll::loop_new() };
+        assert!(handle.is_not_null());
+        NativeHandle::from_native_handle(handle)
+    }
+
+    fn run(&mut self) {
+        unsafe { uvll::run(self.native_handle()) };
+    }
+
+    fn close(&mut self) {
+        unsafe { uvll::loop_delete(self.native_handle()) };
+    }
+}
+
+impl NativeHandle<*uvll::uv_loop_t> for Loop {
+    fn from_native_handle(handle: *uvll::uv_loop_t) -> Loop {
+        Loop { handle: handle }
+    }
+    fn native_handle(&self) -> *uvll::uv_loop_t {
+        self.handle
+    }
+}
+
+// XXX: The uv alloc callback also has a *uv_handle_t arg
+pub type AllocCallback = ~fn(uint) -> Buf;
+pub type ReadCallback = ~fn(StreamWatcher, int, Buf, Option<UvError>);
+pub type NullCallback = ~fn();
+pub type IdleCallback = ~fn(IdleWatcher, Option<UvError>);
+pub type ConnectionCallback = ~fn(StreamWatcher, Option<UvError>);
+pub type FsCallback = ~fn(FsRequest, Option<UvError>);
+pub type TimerCallback = ~fn(TimerWatcher, Option<UvError>);
+
+
+/// Callbacks used by StreamWatchers, set as custom data on the foreign handle
+struct WatcherData {
+    read_cb: Option<ReadCallback>,
+    write_cb: Option<ConnectionCallback>,
+    connect_cb: Option<ConnectionCallback>,
+    close_cb: Option<NullCallback>,
+    alloc_cb: Option<AllocCallback>,
+    idle_cb: Option<IdleCallback>,
+    timer_cb: Option<TimerCallback>
+}
+
+pub trait WatcherInterop {
+    fn event_loop(&self) -> Loop;
+    fn install_watcher_data(&mut self);
+    fn get_watcher_data<'r>(&'r mut self) -> &'r mut WatcherData;
+    fn drop_watcher_data(&mut self);
+}
+
+impl<H, W: Watcher + NativeHandle<*H>> WatcherInterop for W {
+    /// Get the uv event loop from a Watcher
+    pub fn event_loop(&self) -> Loop {
+        unsafe {
+            let handle = self.native_handle();
+            let loop_ = uvll::get_loop_for_uv_handle(handle);
+            NativeHandle::from_native_handle(loop_)
+        }
+    }
+
+    pub fn install_watcher_data(&mut self) {
+        unsafe {
+            let data = ~WatcherData {
+                read_cb: None,
+                write_cb: None,
+                connect_cb: None,
+                close_cb: None,
+                alloc_cb: None,
+                idle_cb: None,
+                timer_cb: None
+            };
+            let data = transmute::<~WatcherData, *c_void>(data);
+            uvll::set_data_for_uv_handle(self.native_handle(), data);
+        }
+    }
+
+    pub fn get_watcher_data<'r>(&'r mut self) -> &'r mut WatcherData {
+        unsafe {
+            let data = uvll::get_data_for_uv_handle(self.native_handle());
+            let data = transmute::<&*c_void, &mut ~WatcherData>(&data);
+            return &mut **data;
+        }
+    }
+
+    pub fn drop_watcher_data(&mut self) {
+        unsafe {
+            let data = uvll::get_data_for_uv_handle(self.native_handle());
+            let _data = transmute::<*c_void, ~WatcherData>(data);
+            uvll::set_data_for_uv_handle(self.native_handle(), null::<()>());
+        }
+    }
+}
+
+// XXX: Need to define the error constants like EOF so they can be
+// compared to the UvError type
+
+pub struct UvError(uvll::uv_err_t);
+
+pub impl UvError {
+
+    fn name(&self) -> ~str {
+        unsafe {
+            let inner = match self { &UvError(ref a) => a };
+            let name_str = uvll::err_name(inner);
+            assert!(name_str.is_not_null());
+            from_c_str(name_str)
+        }
+    }
+
+    fn desc(&self) -> ~str {
+        unsafe {
+            let inner = match self { &UvError(ref a) => a };
+            let desc_str = uvll::strerror(inner);
+            assert!(desc_str.is_not_null());
+            from_c_str(desc_str)
+        }
+    }
+
+    fn is_eof(&self) -> bool {
+        self.code == uvll::EOF
+    }
+}
+
+impl ToStr for UvError {
+    fn to_str(&self) -> ~str {
+        fmt!("%s: %s", self.name(), self.desc())
+    }
+}
+
+#[test]
+fn error_smoke_test() {
+    let err = uvll::uv_err_t { code: 1, sys_errno_: 1 };
+    let err: UvError = UvError(err);
+    assert_eq!(err.to_str(), ~"EOF: end of file");
+}
+
+pub fn last_uv_error<H, W: Watcher + NativeHandle<*H>>(watcher: &W) -> UvError {
+    unsafe {
+        let loop_ = watcher.event_loop();
+        UvError(uvll::last_error(loop_.native_handle()))
+    }
+}
+
+pub fn uv_error_to_io_error(uverr: UvError) -> IoError {
+
+    // XXX: Could go in str::raw
+    unsafe fn c_str_to_static_slice(s: *libc::c_char) -> &'static str {
+        let s = s as *u8;
+        let mut curr = s, len = 0u;
+        while *curr != 0u8 {
+            len += 1u;
+            curr = ptr::offset(s, len);
+        }
+
+        str::raw::buf_as_slice(s, len, |d| cast::transmute(d))
+    }
+
+
+    unsafe {
+        // Importing error constants
+        use rt::uv::uvll::*;
+        use rt::io::*;
+
+        // uv error descriptions are static
+        let c_desc = uvll::strerror(&*uverr);
+        let desc = c_str_to_static_slice(c_desc);
+
+        let kind = match uverr.code {
+            UNKNOWN => OtherIoError,
+            OK => OtherIoError,
+            EOF => EndOfFile,
+            EACCES => PermissionDenied,
+            ECONNREFUSED => ConnectionRefused,
+            ECONNRESET => ConnectionReset,
+            EPIPE => BrokenPipe,
+            _ => {
+                rtdebug!("uverr.code %u", uverr.code as uint);
+                // XXX: Need to map remaining uv error types
+                OtherIoError
+            }
+        };
+
+        IoError {
+            kind: kind,
+            desc: desc,
+            detail: None
+        }
+    }
+}
+
+/// Given a uv handle, convert a callback status to a UvError
+// XXX: Follow the pattern below by parameterizing over T: Watcher, not T
+pub fn status_to_maybe_uv_error<T>(handle: *T, status: c_int) -> Option<UvError> {
+    if status != -1 {
+        None
+    } else {
+        unsafe {
+            rtdebug!("handle: %x", handle as uint);
+            let loop_ = uvll::get_loop_for_uv_handle(handle);
+            rtdebug!("loop: %x", loop_ as uint);
+            let err = uvll::last_error(loop_);
+            Some(UvError(err))
+        }
+    }
+}
+
+/// The uv buffer type
+pub type Buf = uvll::uv_buf_t;
+
+/// Borrow a slice to a Buf
+pub fn slice_to_uv_buf(v: &[u8]) -> Buf {
+    let data = vec::raw::to_ptr(v);
+    unsafe { uvll::buf_init(data, v.len()) }
+}
+
+// XXX: Do these conversions without copying
+
+/// Transmute an owned vector to a Buf
+pub fn vec_to_uv_buf(v: ~[u8]) -> Buf {
+    unsafe {
+        let data = malloc(v.len() as size_t) as *u8;
+        assert!(data.is_not_null());
+        do vec::as_imm_buf(v) |b, l| {
+            let data = data as *mut u8;
+            ptr::copy_memory(data, b, l)
+        }
+        uvll::buf_init(data, v.len())
+    }
+}
+
+/// Transmute a Buf that was once a ~[u8] back to ~[u8]
+pub fn vec_from_uv_buf(buf: Buf) -> Option<~[u8]> {
+    if !(buf.len == 0 && buf.base.is_null()) {
+        let v = unsafe { vec::from_buf(buf.base, buf.len as uint) };
+        unsafe { free(buf.base as *c_void) };
+        return Some(v);
+    } else {
+        // No buffer
+        rtdebug!("No buffer!");
+        return None;
+    }
+}
+
+#[test]
+fn test_slice_to_uv_buf() {
+    let slice = [0, .. 20];
+    let buf = slice_to_uv_buf(slice);
+
+    assert!(buf.len == 20);
+
+    unsafe {
+        let base = transmute::<*u8, *mut u8>(buf.base);
+        (*base) = 1;
+        (*ptr::mut_offset(base, 1)) = 2;
+    }
+
+    assert!(slice[0] == 1);
+    assert!(slice[1] == 2);
+}
+
+
+#[test]
+fn loop_smoke_test() {
+    do run_in_bare_thread {
+        let mut loop_ = Loop::new();
+        loop_.run();
+        loop_.close();
+    }
+}
+
+#[test]
+#[ignore(reason = "valgrind - loop destroyed before watcher?")]
+fn idle_new_then_close() {
+    do run_in_bare_thread {
+        let mut loop_ = Loop::new();
+        let idle_watcher = { IdleWatcher::new(&mut loop_) };
+        idle_watcher.close(||());
+    }
+}
+
+#[test]
+fn idle_smoke_test() {
+    do run_in_bare_thread {
+        let mut loop_ = Loop::new();
+        let mut idle_watcher = { IdleWatcher::new(&mut loop_) };
+        let mut count = 10;
+        let count_ptr: *mut int = &mut count;
+        do idle_watcher.start |idle_watcher, status| {
+            let mut idle_watcher = idle_watcher;
+            assert!(status.is_none());
+            if unsafe { *count_ptr == 10 } {
+                idle_watcher.stop();
+                idle_watcher.close(||());
+            } else {
+                unsafe { *count_ptr = *count_ptr + 1; }
+            }
+        }
+        loop_.run();
+        loop_.close();
+        assert_eq!(count, 10);
+    }
+}
+
+#[test]
+fn idle_start_stop_start() {
+    do run_in_bare_thread {
+        let mut loop_ = Loop::new();
+        let mut idle_watcher = { IdleWatcher::new(&mut loop_) };
+        do idle_watcher.start |idle_watcher, status| {
+            let mut idle_watcher = idle_watcher;
+            assert!(status.is_none());
+            idle_watcher.stop();
+            do idle_watcher.start |idle_watcher, status| {
+                assert!(status.is_none());
+                let mut idle_watcher = idle_watcher;
+                idle_watcher.stop();
+                idle_watcher.close(||());
+            }
+        }
+        loop_.run();
+        loop_.close();
+    }
+}
diff --git a/src/libstd/rt/uv/net.rs b/src/libstd/rt/uv/net.rs
new file mode 100644
index 00000000000..68b871e6b31
--- /dev/null
+++ b/src/libstd/rt/uv/net.rs
@@ -0,0 +1,436 @@
+// 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 prelude::*;
+use libc::{size_t, ssize_t, c_int, c_void};
+use rt::uv::uvll;
+use rt::uv::uvll::*;
+use rt::uv::{AllocCallback, ConnectionCallback, ReadCallback};
+use rt::uv::{Loop, Watcher, Request, UvError, Buf, NativeHandle, NullCallback,
+             status_to_maybe_uv_error};
+use rt::io::net::ip::{IpAddr, Ipv4, Ipv6};
+use rt::uv::last_uv_error;
+
+fn ip4_as_uv_ip4<T>(addr: IpAddr, f: &fn(*sockaddr_in) -> T) -> T {
+    match addr {
+        Ipv4(a, b, c, d, p) => {
+            unsafe {
+                let addr = malloc_ip4_addr(fmt!("%u.%u.%u.%u",
+                                                a as uint,
+                                                b as uint,
+                                                c as uint,
+                                                d as uint), p as int);
+                do (|| {
+                    f(addr)
+                }).finally {
+                    free_ip4_addr(addr);
+                }
+            }
+        }
+        Ipv6 => fail!()
+    }
+}
+
+// uv_stream t is the parent class of uv_tcp_t, uv_pipe_t, uv_tty_t
+// and uv_file_t
+pub struct StreamWatcher(*uvll::uv_stream_t);
+impl Watcher for StreamWatcher { }
+
+pub impl StreamWatcher {
+
+    fn read_start(&mut self, alloc: AllocCallback, cb: ReadCallback) {
+        {
+            let data = self.get_watcher_data();
+            data.alloc_cb = Some(alloc);
+            data.read_cb = Some(cb);
+        }
+
+        let handle = self.native_handle();
+        unsafe { uvll::read_start(handle, alloc_cb, read_cb); }
+
+        extern fn alloc_cb(stream: *uvll::uv_stream_t, suggested_size: size_t) -> Buf {
+            let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(stream);
+            let data = stream_watcher.get_watcher_data();
+            let alloc_cb = data.alloc_cb.get_ref();
+            return (*alloc_cb)(suggested_size as uint);
+        }
+
+        extern fn read_cb(stream: *uvll::uv_stream_t, nread: ssize_t, buf: Buf) {
+            rtdebug!("buf addr: %x", buf.base as uint);
+            rtdebug!("buf len: %d", buf.len as int);
+            let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(stream);
+            let data = stream_watcher.get_watcher_data();
+            let cb = data.read_cb.get_ref();
+            let status = status_to_maybe_uv_error(stream, nread as c_int);
+            (*cb)(stream_watcher, nread as int, buf, status);
+        }
+    }
+
+    fn read_stop(&mut self) {
+        // It would be nice to drop the alloc and read callbacks here,
+        // but read_stop may be called from inside one of them and we
+        // would end up freeing the in-use environment
+        let handle = self.native_handle();
+        unsafe { uvll::read_stop(handle); }
+    }
+
+    fn write(&mut self, buf: Buf, cb: ConnectionCallback) {
+        {
+            let data = self.get_watcher_data();
+            assert!(data.write_cb.is_none());
+            data.write_cb = Some(cb);
+        }
+
+        let req = WriteRequest::new();
+        let bufs = [buf];
+        unsafe {
+            assert!(0 == uvll::write(req.native_handle(),
+                                     self.native_handle(),
+                                     bufs, write_cb));
+        }
+
+        extern fn write_cb(req: *uvll::uv_write_t, status: c_int) {
+            let write_request: WriteRequest = NativeHandle::from_native_handle(req);
+            let mut stream_watcher = write_request.stream();
+            write_request.delete();
+            let cb = {
+                let data = stream_watcher.get_watcher_data();
+                let cb = data.write_cb.swap_unwrap();
+                cb
+            };
+            let status = status_to_maybe_uv_error(stream_watcher.native_handle(), status);
+            cb(stream_watcher, status);
+        }
+    }
+
+    fn accept(&mut self, stream: StreamWatcher) {
+        let self_handle = self.native_handle() as *c_void;
+        let stream_handle = stream.native_handle() as *c_void;
+        unsafe {
+            assert_eq!(0, uvll::accept(self_handle, stream_handle));
+        }
+    }
+
+    fn close(self, cb: NullCallback) {
+        {
+            let mut this = self;
+            let data = this.get_watcher_data();
+            assert!(data.close_cb.is_none());
+            data.close_cb = Some(cb);
+        }
+
+        unsafe { uvll::close(self.native_handle(), close_cb); }
+
+        extern fn close_cb(handle: *uvll::uv_stream_t) {
+            let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(handle);
+            {
+                let data = stream_watcher.get_watcher_data();
+                data.close_cb.swap_unwrap()();
+            }
+            stream_watcher.drop_watcher_data();
+            unsafe { free_handle(handle as *c_void) }
+        }
+    }
+}
+
+impl NativeHandle<*uvll::uv_stream_t> for StreamWatcher {
+    fn from_native_handle(
+        handle: *uvll::uv_stream_t) -> StreamWatcher {
+        StreamWatcher(handle)
+    }
+    fn native_handle(&self) -> *uvll::uv_stream_t {
+        match self { &StreamWatcher(ptr) => ptr }
+    }
+}
+
+pub struct TcpWatcher(*uvll::uv_tcp_t);
+impl Watcher for TcpWatcher { }
+
+pub impl TcpWatcher {
+    fn new(loop_: &mut Loop) -> TcpWatcher {
+        unsafe {
+            let handle = malloc_handle(UV_TCP);
+            assert!(handle.is_not_null());
+            assert_eq!(0, uvll::tcp_init(loop_.native_handle(), handle));
+            let mut watcher: TcpWatcher = NativeHandle::from_native_handle(handle);
+            watcher.install_watcher_data();
+            return watcher;
+        }
+    }
+
+    fn bind(&mut self, address: IpAddr) -> Result<(), UvError> {
+        match address {
+            Ipv4(*) => {
+                do ip4_as_uv_ip4(address) |addr| {
+                    let result = unsafe {
+                        uvll::tcp_bind(self.native_handle(), addr)
+                    };
+                    if result == 0 {
+                        Ok(())
+                    } else {
+                        Err(last_uv_error(self))
+                    }
+                }
+            }
+            _ => fail!()
+        }
+    }
+
+    fn connect(&mut self, address: IpAddr, cb: ConnectionCallback) {
+        unsafe {
+            assert!(self.get_watcher_data().connect_cb.is_none());
+            self.get_watcher_data().connect_cb = Some(cb);
+
+            let connect_handle = ConnectRequest::new().native_handle();
+            match address {
+                Ipv4(*) => {
+                    do ip4_as_uv_ip4(address) |addr| {
+                        rtdebug!("connect_t: %x", connect_handle as uint);
+                        assert!(0 == uvll::tcp_connect(connect_handle,
+                                                            self.native_handle(),
+                                                            addr, connect_cb));
+                    }
+                }
+                _ => fail!()
+            }
+
+            extern fn connect_cb(req: *uvll::uv_connect_t, status: c_int) {
+                rtdebug!("connect_t: %x", req as uint);
+                let connect_request: ConnectRequest = NativeHandle::from_native_handle(req);
+                let mut stream_watcher = connect_request.stream();
+                connect_request.delete();
+                let cb: ConnectionCallback = {
+                    let data = stream_watcher.get_watcher_data();
+                    data.connect_cb.swap_unwrap()
+                };
+                let status = status_to_maybe_uv_error(stream_watcher.native_handle(), status);
+                cb(stream_watcher, status);
+            }
+        }
+    }
+
+    fn listen(&mut self, cb: ConnectionCallback) {
+        {
+            let data = self.get_watcher_data();
+            assert!(data.connect_cb.is_none());
+            data.connect_cb = Some(cb);
+        }
+
+        unsafe {
+            static BACKLOG: c_int = 128; // XXX should be configurable
+            // XXX: This can probably fail
+            assert!(0 == uvll::listen(self.native_handle(),
+                                           BACKLOG, connection_cb));
+        }
+
+        extern fn connection_cb(handle: *uvll::uv_stream_t, status: c_int) {
+            rtdebug!("connection_cb");
+            let mut stream_watcher: StreamWatcher = NativeHandle::from_native_handle(handle);
+            let data = stream_watcher.get_watcher_data();
+            let cb = data.connect_cb.get_ref();
+            let status = status_to_maybe_uv_error(handle, status);
+            (*cb)(stream_watcher, status);
+        }
+    }
+
+    fn as_stream(&self) -> StreamWatcher {
+        NativeHandle::from_native_handle(self.native_handle() as *uvll::uv_stream_t)
+    }
+}
+
+impl NativeHandle<*uvll::uv_tcp_t> for TcpWatcher {
+    fn from_native_handle(handle: *uvll::uv_tcp_t) -> TcpWatcher {
+        TcpWatcher(handle)
+    }
+    fn native_handle(&self) -> *uvll::uv_tcp_t {
+        match self { &TcpWatcher(ptr) => ptr }
+    }
+}
+
+// uv_connect_t is a subclass of uv_req_t
+struct ConnectRequest(*uvll::uv_connect_t);
+impl Request for ConnectRequest { }
+
+impl ConnectRequest {
+
+    fn new() -> ConnectRequest {
+        let connect_handle = unsafe {
+            malloc_req(UV_CONNECT)
+        };
+        assert!(connect_handle.is_not_null());
+        let connect_handle = connect_handle as *uvll::uv_connect_t;
+        ConnectRequest(connect_handle)
+    }
+
+    fn stream(&self) -> StreamWatcher {
+        unsafe {
+            let stream_handle = uvll::get_stream_handle_from_connect_req(self.native_handle());
+            NativeHandle::from_native_handle(stream_handle)
+        }
+    }
+
+    fn delete(self) {
+        unsafe { free_req(self.native_handle() as *c_void) }
+    }
+}
+
+impl NativeHandle<*uvll::uv_connect_t> for ConnectRequest {
+    fn from_native_handle(
+        handle: *uvll:: uv_connect_t) -> ConnectRequest {
+        ConnectRequest(handle)
+    }
+    fn native_handle(&self) -> *uvll::uv_connect_t {
+        match self { &ConnectRequest(ptr) => ptr }
+    }
+}
+
+pub struct WriteRequest(*uvll::uv_write_t);
+
+impl Request for WriteRequest { }
+
+pub impl WriteRequest {
+
+    fn new() -> WriteRequest {
+        let write_handle = unsafe {
+            malloc_req(UV_WRITE)
+        };
+        assert!(write_handle.is_not_null());
+        let write_handle = write_handle as *uvll::uv_write_t;
+        WriteRequest(write_handle)
+    }
+
+    fn stream(&self) -> StreamWatcher {
+        unsafe {
+            let stream_handle = uvll::get_stream_handle_from_write_req(self.native_handle());
+            NativeHandle::from_native_handle(stream_handle)
+        }
+    }
+
+    fn delete(self) {
+        unsafe { free_req(self.native_handle() as *c_void) }
+    }
+}
+
+impl NativeHandle<*uvll::uv_write_t> for WriteRequest {
+    fn from_native_handle(handle: *uvll:: uv_write_t) -> WriteRequest {
+        WriteRequest(handle)
+    }
+    fn native_handle(&self) -> *uvll::uv_write_t {
+        match self { &WriteRequest(ptr) => ptr }
+    }
+}
+
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use util::ignore;
+    use cell::Cell;
+    use vec;
+    use unstable::run_in_bare_thread;
+    use rt::thread::Thread;
+    use rt::test::*;
+    use rt::uv::{Loop, AllocCallback};
+    use rt::uv::{vec_from_uv_buf, vec_to_uv_buf, slice_to_uv_buf};
+
+    #[test]
+    fn connect_close() {
+        do run_in_bare_thread() {
+            let mut loop_ = Loop::new();
+            let mut tcp_watcher = { TcpWatcher::new(&mut loop_) };
+            // Connect to a port where nobody is listening
+            let addr = next_test_ip4();
+            do tcp_watcher.connect(addr) |stream_watcher, status| {
+                rtdebug!("tcp_watcher.connect!");
+                assert!(status.is_some());
+                assert_eq!(status.get().name(), ~"ECONNREFUSED");
+                stream_watcher.close(||());
+            }
+            loop_.run();
+            loop_.close();
+        }
+    }
+
+    #[test]
+    fn listen() {
+        do run_in_bare_thread() {
+            static MAX: int = 10;
+            let mut loop_ = Loop::new();
+            let mut server_tcp_watcher = { TcpWatcher::new(&mut loop_) };
+            let addr = next_test_ip4();
+            server_tcp_watcher.bind(addr);
+            let loop_ = loop_;
+            rtdebug!("listening");
+            do server_tcp_watcher.listen |server_stream_watcher, status| {
+                rtdebug!("listened!");
+                assert!(status.is_none());
+                let mut server_stream_watcher = server_stream_watcher;
+                let mut loop_ = loop_;
+                let client_tcp_watcher = TcpWatcher::new(&mut loop_);
+                let mut client_tcp_watcher = client_tcp_watcher.as_stream();
+                server_stream_watcher.accept(client_tcp_watcher);
+                let count_cell = Cell(0);
+                let server_stream_watcher = server_stream_watcher;
+                rtdebug!("starting read");
+                let alloc: AllocCallback = |size| {
+                    vec_to_uv_buf(vec::from_elem(size, 0))
+                };
+                do client_tcp_watcher.read_start(alloc)
+                    |stream_watcher, nread, buf, status| {
+
+                    rtdebug!("i'm reading!");
+                    let buf = vec_from_uv_buf(buf);
+                    let mut count = count_cell.take();
+                    if status.is_none() {
+                        rtdebug!("got %d bytes", nread);
+                        let buf = buf.unwrap();
+                        for buf.slice(0, nread as uint).each |byte| {
+                            assert!(*byte == count as u8);
+                            rtdebug!("%u", *byte as uint);
+                            count += 1;
+                        }
+                    } else {
+                        assert_eq!(count, MAX);
+                        do stream_watcher.close {
+                            server_stream_watcher.close(||());
+                        }
+                    }
+                    count_cell.put_back(count);
+                }
+            }
+
+            let _client_thread = do Thread::start {
+                rtdebug!("starting client thread");
+                let mut loop_ = Loop::new();
+                let mut tcp_watcher = { TcpWatcher::new(&mut loop_) };
+                do tcp_watcher.connect(addr) |stream_watcher, status| {
+                    rtdebug!("connecting");
+                    assert!(status.is_none());
+                    let mut stream_watcher = stream_watcher;
+                    let msg = ~[0, 1, 2, 3, 4, 5, 6 ,7 ,8, 9];
+                    let buf = slice_to_uv_buf(msg);
+                    let msg_cell = Cell(msg);
+                    do stream_watcher.write(buf) |stream_watcher, status| {
+                        rtdebug!("writing");
+                        assert!(status.is_none());
+                        let msg_cell = Cell(msg_cell.take());
+                        stream_watcher.close(||ignore(msg_cell.take()));
+                    }
+                }
+                loop_.run();
+                loop_.close();
+            };
+
+            let mut loop_ = loop_;
+            loop_.run();
+            loop_.close();
+        }
+    }
+}
diff --git a/src/libstd/rt/uvio.rs b/src/libstd/rt/uvio.rs
new file mode 100644
index 00000000000..24bffd8d1cd
--- /dev/null
+++ b/src/libstd/rt/uvio.rs
@@ -0,0 +1,459 @@
+// 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::*;
+use result::*;
+
+use super::io::net::ip::IpAddr;
+use super::uv::*;
+use super::rtio::*;
+use ops::Drop;
+use old_iter::CopyableIter;
+use cell::{Cell, empty_cell};
+use cast::transmute;
+use super::sched::{Scheduler, local_sched};
+
+#[cfg(test)] use container::Container;
+#[cfg(test)] use uint;
+#[cfg(test)] use unstable::run_in_bare_thread;
+#[cfg(test)] use super::test::*;
+
+pub struct UvEventLoop {
+    uvio: UvIoFactory
+}
+
+pub impl UvEventLoop {
+    fn new() -> UvEventLoop {
+        UvEventLoop {
+            uvio: UvIoFactory(Loop::new())
+        }
+    }
+
+    /// A convenience constructor
+    fn new_scheduler() -> Scheduler {
+        Scheduler::new(~UvEventLoop::new())
+    }
+}
+
+impl Drop for UvEventLoop {
+    fn finalize(&self) {
+        // XXX: Need mutable finalizer
+        let this = unsafe {
+            transmute::<&UvEventLoop, &mut UvEventLoop>(self)
+        };
+        this.uvio.uv_loop().close();
+    }
+}
+
+impl EventLoop for UvEventLoop {
+
+    fn run(&mut self) {
+        self.uvio.uv_loop().run();
+    }
+
+    fn callback(&mut self, f: ~fn()) {
+        let mut idle_watcher =  IdleWatcher::new(self.uvio.uv_loop());
+        do idle_watcher.start |idle_watcher, status| {
+            assert!(status.is_none());
+            let mut idle_watcher = idle_watcher;
+            idle_watcher.stop();
+            idle_watcher.close();
+            f();
+        }
+    }
+
+    fn io<'a>(&'a mut self) -> Option<&'a mut IoFactoryObject> {
+        Some(&mut self.uvio)
+    }
+}
+
+#[test]
+fn test_callback_run_once() {
+    do run_in_bare_thread {
+        let mut event_loop = UvEventLoop::new();
+        let mut count = 0;
+        let count_ptr: *mut int = &mut count;
+        do event_loop.callback {
+            unsafe { *count_ptr += 1 }
+        }
+        event_loop.run();
+        assert!(count == 1);
+    }
+}
+
+pub struct UvIoFactory(Loop);
+
+pub impl UvIoFactory {
+    fn uv_loop<'a>(&'a mut self) -> &'a mut Loop {
+        match self { &UvIoFactory(ref mut ptr) => ptr }
+    }
+}
+
+impl IoFactory for UvIoFactory {
+    // Connect to an address and return a new stream
+    // NB: This blocks the task waiting on the connection.
+    // It would probably be better to return a future
+    fn connect(&mut self, addr: IpAddr) -> Option<~StreamObject> {
+        // Create a cell in the task to hold the result. We will fill
+        // the cell before resuming the task.
+        let result_cell = empty_cell();
+        let result_cell_ptr: *Cell<Option<~StreamObject>> = &result_cell;
+
+        let scheduler = local_sched::take();
+        assert!(scheduler.in_task_context());
+
+        // Block this task and take ownership, switch to scheduler context
+        do scheduler.deschedule_running_task_and_then |task| {
+
+            rtdebug!("connect: entered scheduler context");
+            do local_sched::borrow |scheduler| {
+                assert!(!scheduler.in_task_context());
+            }
+            let mut tcp_watcher = TcpWatcher::new(self.uv_loop());
+            let task_cell = Cell(task);
+
+            // Wait for a connection
+            do tcp_watcher.connect(addr) |stream_watcher, status| {
+                rtdebug!("connect: in connect callback");
+                let maybe_stream = if status.is_none() {
+                    rtdebug!("status is none");
+                    Some(~UvStream(stream_watcher))
+                } else {
+                    rtdebug!("status is some");
+                    stream_watcher.close(||());
+                    None
+                };
+
+                // Store the stream in the task's stack
+                unsafe { (*result_cell_ptr).put_back(maybe_stream); }
+
+                // Context switch
+                let scheduler = local_sched::take();
+                scheduler.resume_task_immediately(task_cell.take());
+            }
+        }
+
+        assert!(!result_cell.is_empty());
+        return result_cell.take();
+    }
+
+    fn bind(&mut self, addr: IpAddr) -> Option<~TcpListenerObject> {
+        let mut watcher = TcpWatcher::new(self.uv_loop());
+        watcher.bind(addr);
+        return Some(~UvTcpListener(watcher));
+    }
+}
+
+pub struct UvTcpListener(TcpWatcher);
+
+impl UvTcpListener {
+    fn watcher(&self) -> TcpWatcher {
+        match self { &UvTcpListener(w) => w }
+    }
+
+    fn close(&self) {
+        // XXX: Need to wait until close finishes before returning
+        self.watcher().as_stream().close(||());
+    }
+}
+
+impl Drop for UvTcpListener {
+    fn finalize(&self) {
+        // XXX: Again, this never gets called. Use .close() instead
+        //self.watcher().as_stream().close(||());
+    }
+}
+
+impl TcpListener for UvTcpListener {
+
+    fn listen(&mut self) -> Option<~StreamObject> {
+        rtdebug!("entering listen");
+        let result_cell = empty_cell();
+        let result_cell_ptr: *Cell<Option<~StreamObject>> = &result_cell;
+
+        let server_tcp_watcher = self.watcher();
+
+        let scheduler = local_sched::take();
+        assert!(scheduler.in_task_context());
+
+        do scheduler.deschedule_running_task_and_then |task| {
+            let task_cell = Cell(task);
+            let mut server_tcp_watcher = server_tcp_watcher;
+            do server_tcp_watcher.listen |server_stream_watcher, status| {
+                let maybe_stream = if status.is_none() {
+                    let mut server_stream_watcher = server_stream_watcher;
+                    let mut loop_ = loop_from_watcher(&server_stream_watcher);
+                    let client_tcp_watcher = TcpWatcher::new(&mut loop_).as_stream();
+                    // XXX: Needs to be surfaced in interface
+                    server_stream_watcher.accept(client_tcp_watcher);
+                    Some(~UvStream::new(client_tcp_watcher))
+                } else {
+                    None
+                };
+
+                unsafe { (*result_cell_ptr).put_back(maybe_stream); }
+
+                rtdebug!("resuming task from listen");
+                // Context switch
+                let scheduler = local_sched::take();
+                scheduler.resume_task_immediately(task_cell.take());
+            }
+        }
+
+        assert!(!result_cell.is_empty());
+        return result_cell.take();
+    }
+}
+
+pub struct UvStream(StreamWatcher);
+
+impl UvStream {
+    fn new(watcher: StreamWatcher) -> UvStream {
+        UvStream(watcher)
+    }
+
+    fn watcher(&self) -> StreamWatcher {
+        match self { &UvStream(w) => w }
+    }
+
+    // XXX: finalize isn't working for ~UvStream???
+    fn close(&self) {
+        // XXX: Need to wait until this finishes before returning
+        self.watcher().close(||());
+    }
+}
+
+impl Drop for UvStream {
+    fn finalize(&self) {
+        rtdebug!("closing stream");
+        //self.watcher().close(||());
+    }
+}
+
+impl Stream for UvStream {
+    fn read(&mut self, buf: &mut [u8]) -> Result<uint, ()> {
+        let result_cell = empty_cell();
+        let result_cell_ptr: *Cell<Result<uint, ()>> = &result_cell;
+
+        let scheduler = local_sched::take();
+        assert!(scheduler.in_task_context());
+        let watcher = self.watcher();
+        let buf_ptr: *&mut [u8] = &buf;
+        do scheduler.deschedule_running_task_and_then |task| {
+            rtdebug!("read: entered scheduler context");
+            do local_sched::borrow |scheduler| {
+                assert!(!scheduler.in_task_context());
+            }
+            let mut watcher = watcher;
+            let task_cell = Cell(task);
+            // XXX: We shouldn't reallocate these callbacks every
+            // call to read
+            let alloc: AllocCallback = |_| unsafe {
+                slice_to_uv_buf(*buf_ptr)
+            };
+            do watcher.read_start(alloc) |watcher, nread, _buf, status| {
+
+                // Stop reading so that no read callbacks are
+                // triggered before the user calls `read` again.
+                // XXX: Is there a performance impact to calling
+                // stop here?
+                let mut watcher = watcher;
+                watcher.read_stop();
+
+                let result = if status.is_none() {
+                    assert!(nread >= 0);
+                    Ok(nread as uint)
+                } else {
+                    Err(())
+                };
+
+                unsafe { (*result_cell_ptr).put_back(result); }
+
+                let scheduler = local_sched::take();
+                scheduler.resume_task_immediately(task_cell.take());
+            }
+        }
+
+        assert!(!result_cell.is_empty());
+        return result_cell.take();
+    }
+
+    fn write(&mut self, buf: &[u8]) -> Result<(), ()> {
+        let result_cell = empty_cell();
+        let result_cell_ptr: *Cell<Result<(), ()>> = &result_cell;
+        let scheduler = local_sched::take();
+        assert!(scheduler.in_task_context());
+        let watcher = self.watcher();
+        let buf_ptr: *&[u8] = &buf;
+        do scheduler.deschedule_running_task_and_then |task| {
+            let mut watcher = watcher;
+            let task_cell = Cell(task);
+            let buf = unsafe { &*buf_ptr };
+            // XXX: OMGCOPIES
+            let buf = buf.to_vec();
+            do watcher.write(buf) |_watcher, status| {
+                let result = if status.is_none() {
+                    Ok(())
+                } else {
+                    Err(())
+                };
+
+                unsafe { (*result_cell_ptr).put_back(result); }
+
+                let scheduler = local_sched::take();
+                scheduler.resume_task_immediately(task_cell.take());
+            }
+        }
+
+        assert!(!result_cell.is_empty());
+        return result_cell.take();
+    }
+}
+
+#[test]
+fn test_simple_io_no_connect() {
+    do run_in_newsched_task {
+        let io = unsafe { local_sched::unsafe_borrow_io() };
+        let addr = next_test_ip4();
+        let maybe_chan = io.connect(addr);
+        assert!(maybe_chan.is_none());
+    }
+}
+
+#[test]
+fn test_simple_tcp_server_and_client() {
+    do run_in_newsched_task {
+        let addr = next_test_ip4();
+
+        // Start the server first so it's listening when we connect
+        do spawntask_immediately {
+            unsafe {
+                let io = local_sched::unsafe_borrow_io();
+                let mut listener = io.bind(addr).unwrap();
+                let mut stream = listener.listen().unwrap();
+                let mut buf = [0, .. 2048];
+                let nread = stream.read(buf).unwrap();
+                assert!(nread == 8);
+                for uint::range(0, nread) |i| {
+                    rtdebug!("%u", buf[i] as uint);
+                    assert!(buf[i] == i as u8);
+                }
+                stream.close();
+                listener.close();
+            }
+        }
+
+        do spawntask_immediately {
+            unsafe {
+                let io = local_sched::unsafe_borrow_io();
+                let mut stream = io.connect(addr).unwrap();
+                stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
+                stream.close();
+            }
+        }
+    }
+}
+
+#[test] #[ignore(reason = "busted")]
+fn test_read_and_block() {
+    do run_in_newsched_task {
+        let addr = next_test_ip4();
+
+        do spawntask_immediately {
+            let io = unsafe { local_sched::unsafe_borrow_io() };
+            let mut listener = io.bind(addr).unwrap();
+            let mut stream = listener.listen().unwrap();
+            let mut buf = [0, .. 2048];
+
+            let expected = 32;
+            let mut current = 0;
+            let mut reads = 0;
+
+            while current < expected {
+                let nread = stream.read(buf).unwrap();
+                for uint::range(0, nread) |i| {
+                    let val = buf[i] as uint;
+                    assert!(val == current % 8);
+                    current += 1;
+                }
+                reads += 1;
+
+                let scheduler = local_sched::take();
+                // Yield to the other task in hopes that it
+                // will trigger a read callback while we are
+                // not ready for it
+                do scheduler.deschedule_running_task_and_then |task| {
+                    let task = Cell(task);
+                    do local_sched::borrow |scheduler| {
+                        scheduler.task_queue.push_back(task.take());
+                    }
+                }
+            }
+
+            // Make sure we had multiple reads
+            assert!(reads > 1);
+
+            stream.close();
+            listener.close();
+        }
+
+        do spawntask_immediately {
+            let io = unsafe { local_sched::unsafe_borrow_io() };
+            let mut stream = io.connect(addr).unwrap();
+            stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
+            stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
+            stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
+            stream.write([0, 1, 2, 3, 4, 5, 6, 7]);
+            stream.close();
+        }
+
+    }
+}
+
+#[test]
+fn test_read_read_read() {
+    do run_in_newsched_task {
+        let addr = next_test_ip4();
+        static MAX: uint = 500000;
+
+        do spawntask_immediately {
+            unsafe {
+                let io = local_sched::unsafe_borrow_io();
+                let mut listener = io.bind(addr).unwrap();
+                let mut stream = listener.listen().unwrap();
+                let buf = [1, .. 2048];
+                let mut total_bytes_written = 0;
+                while total_bytes_written < MAX {
+                    stream.write(buf);
+                    total_bytes_written += buf.len();
+                }
+                stream.close();
+                listener.close();
+            }
+        }
+
+        do spawntask_immediately {
+            let io = unsafe { local_sched::unsafe_borrow_io() };
+            let mut stream = io.connect(addr).unwrap();
+            let mut buf = [0, .. 2048];
+            let mut total_bytes_read = 0;
+            while total_bytes_read < MAX {
+                let nread = stream.read(buf).unwrap();
+                rtdebug!("read %u bytes", nread as uint);
+                total_bytes_read += nread;
+                for uint::range(0, nread) |i| {
+                    assert!(buf[i] == 1);
+                }
+            }
+            rtdebug!("read %u bytes total", total_bytes_read as uint);
+            stream.close();
+        }
+    }
+}
diff --git a/src/libstd/rt/uvll.rs b/src/libstd/rt/uvll.rs
new file mode 100644
index 00000000000..0d298bde6b5
--- /dev/null
+++ b/src/libstd/rt/uvll.rs
@@ -0,0 +1,443 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+ * Low-level bindings to the libuv library.
+ *
+ * This module contains a set of direct, 'bare-metal' wrappers around
+ * the libuv C-API.
+ *
+ * We're not bothering yet to redefine uv's structs as Rust structs
+ * because they are quite large and change often between versions.
+ * The maintenance burden is just too high. Instead we use the uv's
+ * `uv_handle_size` and `uv_req_size` to find the correct size of the
+ * structs and allocate them on the heap. This can be revisited later.
+ *
+ * There are also a collection of helper functions to ease interacting
+ * with the low-level API.
+ *
+ * As new functionality, existant in uv.h, is added to the rust stdlib,
+ * the mappings should be added in this module.
+ */
+
+#[allow(non_camel_case_types)]; // C types
+
+use libc::{size_t, c_int, c_uint, c_void, c_char, uintptr_t};
+use libc::{malloc, free};
+use prelude::*;
+
+pub struct uv_err_t {
+    code: c_int,
+    sys_errno_: c_int
+}
+
+pub struct uv_buf_t {
+    base: *u8,
+    len: libc::size_t,
+}
+
+pub type uv_handle_t = c_void;
+pub type uv_loop_t = c_void;
+pub type uv_idle_t = c_void;
+pub type uv_tcp_t = c_void;
+pub type uv_connect_t = c_void;
+pub type uv_write_t = c_void;
+pub type uv_async_t = c_void;
+pub type uv_timer_t = c_void;
+pub type uv_stream_t = c_void;
+pub type uv_fs_t = c_void;
+
+pub type uv_idle_cb = *u8;
+
+pub type sockaddr_in = c_void;
+pub type sockaddr_in6 = c_void;
+
+#[deriving(Eq)]
+pub enum uv_handle_type {
+    UV_UNKNOWN_HANDLE,
+    UV_ASYNC,
+    UV_CHECK,
+    UV_FS_EVENT,
+    UV_FS_POLL,
+    UV_HANDLE,
+    UV_IDLE,
+    UV_NAMED_PIPE,
+    UV_POLL,
+    UV_PREPARE,
+    UV_PROCESS,
+    UV_STREAM,
+    UV_TCP,
+    UV_TIMER,
+    UV_TTY,
+    UV_UDP,
+    UV_SIGNAL,
+    UV_FILE,
+    UV_HANDLE_TYPE_MAX
+}
+
+#[deriving(Eq)]
+pub enum uv_req_type {
+    UV_UNKNOWN_REQ,
+    UV_REQ,
+    UV_CONNECT,
+    UV_WRITE,
+    UV_SHUTDOWN,
+    UV_UDP_SEND,
+    UV_FS,
+    UV_WORK,
+    UV_GETADDRINFO,
+    UV_REQ_TYPE_MAX
+}
+
+pub unsafe fn malloc_handle(handle: uv_handle_type) -> *c_void {
+    assert!(handle != UV_UNKNOWN_HANDLE && handle != UV_HANDLE_TYPE_MAX);
+    let size = rust_uv_handle_size(handle as uint);
+    let p = malloc(size);
+    assert!(p.is_not_null());
+    return p;
+}
+
+pub unsafe fn free_handle(v: *c_void) {
+    free(v)
+}
+
+pub unsafe fn malloc_req(req: uv_req_type) -> *c_void {
+    assert!(req != UV_UNKNOWN_REQ && req != UV_REQ_TYPE_MAX);
+    let size = rust_uv_req_size(req as uint);
+    let p = malloc(size);
+    assert!(p.is_not_null());
+    return p;
+}
+
+pub unsafe fn free_req(v: *c_void) {
+    free(v)
+}
+
+#[test]
+fn handle_sanity_check() {
+    unsafe {
+        assert!(UV_HANDLE_TYPE_MAX as uint == rust_uv_handle_type_max());
+    }
+}
+
+#[test]
+fn request_sanity_check() {
+    unsafe {
+        assert!(UV_REQ_TYPE_MAX as uint == rust_uv_req_type_max());
+    }
+}
+
+pub unsafe fn loop_new() -> *c_void {
+    return rust_uv_loop_new();
+}
+
+pub unsafe fn loop_delete(loop_handle: *c_void) {
+    rust_uv_loop_delete(loop_handle);
+}
+
+pub unsafe fn run(loop_handle: *c_void) {
+    rust_uv_run(loop_handle);
+}
+
+pub unsafe fn close<T>(handle: *T, cb: *u8) {
+    rust_uv_close(handle as *c_void, cb);
+}
+
+pub unsafe fn walk(loop_handle: *c_void, cb: *u8, arg: *c_void) {
+    rust_uv_walk(loop_handle, cb, arg);
+}
+
+pub unsafe fn idle_new() -> *uv_idle_t {
+    rust_uv_idle_new()
+}
+
+pub unsafe fn idle_delete(handle: *uv_idle_t) {
+    rust_uv_idle_delete(handle)
+}
+
+pub unsafe fn idle_init(loop_handle: *uv_loop_t, handle: *uv_idle_t) -> c_int {
+    rust_uv_idle_init(loop_handle, handle)
+}
+
+pub unsafe fn idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> c_int {
+    rust_uv_idle_start(handle, cb)
+}
+
+pub unsafe fn idle_stop(handle: *uv_idle_t) -> c_int {
+    rust_uv_idle_stop(handle)
+}
+
+pub unsafe fn tcp_init(loop_handle: *c_void, handle: *uv_tcp_t) -> c_int {
+    return rust_uv_tcp_init(loop_handle, handle);
+}
+
+// FIXME ref #2064
+pub unsafe fn tcp_connect(connect_ptr: *uv_connect_t,
+                          tcp_handle_ptr: *uv_tcp_t,
+                          addr_ptr: *sockaddr_in,
+                          after_connect_cb: *u8) -> c_int {
+    return rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr,
+                                       after_connect_cb, addr_ptr);
+}
+// FIXME ref #2064
+pub unsafe fn tcp_connect6(connect_ptr: *uv_connect_t,
+                           tcp_handle_ptr: *uv_tcp_t,
+                           addr_ptr: *sockaddr_in6,
+                           after_connect_cb: *u8) -> c_int {
+    return rust_uv_tcp_connect6(connect_ptr, tcp_handle_ptr,
+                                        after_connect_cb, addr_ptr);
+}
+// FIXME ref #2064
+pub unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t, addr_ptr: *sockaddr_in) -> c_int {
+    return rust_uv_tcp_bind(tcp_server_ptr, addr_ptr);
+}
+// FIXME ref #2064
+pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t, addr_ptr: *sockaddr_in6) -> c_int {
+    return rust_uv_tcp_bind6(tcp_server_ptr, addr_ptr);
+}
+
+pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, name: *sockaddr_in) -> c_int {
+    return rust_uv_tcp_getpeername(tcp_handle_ptr, name);
+}
+
+pub unsafe fn tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t, name: *sockaddr_in6) ->c_int {
+    return rust_uv_tcp_getpeername6(tcp_handle_ptr, name);
+}
+
+pub unsafe fn listen<T>(stream: *T, backlog: c_int, cb: *u8) -> c_int {
+    return rust_uv_listen(stream as *c_void, backlog, cb);
+}
+
+pub unsafe fn accept(server: *c_void, client: *c_void) -> c_int {
+    return rust_uv_accept(server as *c_void, client as *c_void);
+}
+
+pub unsafe fn write<T>(req: *uv_write_t, stream: *T, buf_in: &[uv_buf_t], cb: *u8) -> c_int {
+    let buf_ptr = vec::raw::to_ptr(buf_in);
+    let buf_cnt = buf_in.len() as i32;
+    return rust_uv_write(req as *c_void, stream as *c_void, buf_ptr, buf_cnt, cb);
+}
+pub unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8, on_read: *u8) -> c_int {
+    return rust_uv_read_start(stream as *c_void, on_alloc, on_read);
+}
+
+pub unsafe fn read_stop(stream: *uv_stream_t) -> c_int {
+    return rust_uv_read_stop(stream as *c_void);
+}
+
+pub unsafe fn last_error(loop_handle: *c_void) -> uv_err_t {
+    return rust_uv_last_error(loop_handle);
+}
+
+pub unsafe fn strerror(err: *uv_err_t) -> *c_char {
+    return rust_uv_strerror(err);
+}
+pub unsafe fn err_name(err: *uv_err_t) -> *c_char {
+    return rust_uv_err_name(err);
+}
+
+pub unsafe fn async_init(loop_handle: *c_void, async_handle: *uv_async_t, cb: *u8) -> c_int {
+    return rust_uv_async_init(loop_handle, async_handle, cb);
+}
+
+pub unsafe fn async_send(async_handle: *uv_async_t) {
+    return rust_uv_async_send(async_handle);
+}
+pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t {
+    let out_buf = uv_buf_t { base: ptr::null(), len: 0 as size_t };
+    let out_buf_ptr = ptr::to_unsafe_ptr(&out_buf);
+    rust_uv_buf_init(out_buf_ptr, input, len as size_t);
+    return out_buf;
+}
+
+pub unsafe fn timer_init(loop_ptr: *c_void, timer_ptr: *uv_timer_t) -> c_int {
+    return rust_uv_timer_init(loop_ptr, timer_ptr);
+}
+pub unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: uint,
+                          repeat: uint) -> c_int {
+    return rust_uv_timer_start(timer_ptr, cb, timeout as c_uint, repeat as c_uint);
+}
+pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> c_int {
+    return rust_uv_timer_stop(timer_ptr);
+}
+
+pub unsafe fn malloc_ip4_addr(ip: &str, port: int) -> *sockaddr_in {
+    do str::as_c_str(ip) |ip_buf| {
+        rust_uv_ip4_addrp(ip_buf as *u8, port as libc::c_int)
+    }
+}
+pub unsafe fn malloc_ip6_addr(ip: &str, port: int) -> *sockaddr_in6 {
+    do str::as_c_str(ip) |ip_buf| {
+        rust_uv_ip6_addrp(ip_buf as *u8, port as libc::c_int)
+    }
+}
+
+pub unsafe fn free_ip4_addr(addr: *sockaddr_in) {
+    rust_uv_free_ip4_addr(addr);
+}
+
+pub unsafe fn free_ip6_addr(addr: *sockaddr_in6) {
+    rust_uv_free_ip6_addr(addr);
+}
+
+// data access helpers
+pub unsafe fn get_loop_for_uv_handle<T>(handle: *T) -> *c_void {
+    return rust_uv_get_loop_for_uv_handle(handle as *c_void);
+}
+pub unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t) -> *uv_stream_t {
+    return rust_uv_get_stream_handle_from_connect_req(connect);
+}
+pub unsafe fn get_stream_handle_from_write_req(write_req: *uv_write_t) -> *uv_stream_t {
+    return rust_uv_get_stream_handle_from_write_req(write_req);
+}
+pub unsafe fn get_data_for_uv_loop(loop_ptr: *c_void) -> *c_void {
+    rust_uv_get_data_for_uv_loop(loop_ptr)
+}
+pub unsafe fn set_data_for_uv_loop(loop_ptr: *c_void, data: *c_void) {
+    rust_uv_set_data_for_uv_loop(loop_ptr, data);
+}
+pub unsafe fn get_data_for_uv_handle<T>(handle: *T) -> *c_void {
+    return rust_uv_get_data_for_uv_handle(handle as *c_void);
+}
+pub unsafe fn set_data_for_uv_handle<T, U>(handle: *T, data: *U) {
+    rust_uv_set_data_for_uv_handle(handle as *c_void, data as *c_void);
+}
+pub unsafe fn get_data_for_req<T>(req: *T) -> *c_void {
+    return rust_uv_get_data_for_req(req as *c_void);
+}
+pub unsafe fn set_data_for_req<T, U>(req: *T, data: *U) {
+    rust_uv_set_data_for_req(req as *c_void, data as *c_void);
+}
+pub unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 {
+    return rust_uv_get_base_from_buf(buf);
+}
+pub unsafe fn get_len_from_buf(buf: uv_buf_t) -> size_t {
+    return rust_uv_get_len_from_buf(buf);
+}
+pub unsafe fn malloc_buf_base_of(suggested_size: size_t) -> *u8 {
+    return rust_uv_malloc_buf_base_of(suggested_size);
+}
+pub unsafe fn free_base_of_buf(buf: uv_buf_t) {
+    rust_uv_free_base_of_buf(buf);
+}
+
+pub unsafe fn get_last_err_info(uv_loop: *c_void) -> ~str {
+    let err = last_error(uv_loop);
+    let err_ptr = ptr::to_unsafe_ptr(&err);
+    let err_name = str::raw::from_c_str(err_name(err_ptr));
+    let err_msg = str::raw::from_c_str(strerror(err_ptr));
+    return fmt!("LIBUV ERROR: name: %s msg: %s",
+                    err_name, err_msg);
+}
+
+pub unsafe fn get_last_err_data(uv_loop: *c_void) -> uv_err_data {
+    let err = last_error(uv_loop);
+    let err_ptr = ptr::to_unsafe_ptr(&err);
+    let err_name = str::raw::from_c_str(err_name(err_ptr));
+    let err_msg = str::raw::from_c_str(strerror(err_ptr));
+    uv_err_data { err_name: err_name, err_msg: err_msg }
+}
+
+pub struct uv_err_data {
+    err_name: ~str,
+    err_msg: ~str,
+}
+
+extern {
+
+    fn rust_uv_handle_size(type_: uintptr_t) -> size_t;
+    fn rust_uv_req_size(type_: uintptr_t) -> size_t;
+    fn rust_uv_handle_type_max() -> uintptr_t;
+    fn rust_uv_req_type_max() -> uintptr_t;
+
+    // libuv public API
+    fn rust_uv_loop_new() -> *c_void;
+    fn rust_uv_loop_delete(lp: *c_void);
+    fn rust_uv_run(loop_handle: *c_void);
+    fn rust_uv_close(handle: *c_void, cb: *u8);
+    fn rust_uv_walk(loop_handle: *c_void, cb: *u8, arg: *c_void);
+
+    fn rust_uv_idle_new() -> *uv_idle_t;
+    fn rust_uv_idle_delete(handle: *uv_idle_t);
+    fn rust_uv_idle_init(loop_handle: *uv_loop_t, handle: *uv_idle_t) -> c_int;
+    fn rust_uv_idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> c_int;
+    fn rust_uv_idle_stop(handle: *uv_idle_t) -> c_int;
+
+    fn rust_uv_async_send(handle: *uv_async_t);
+    fn rust_uv_async_init(loop_handle: *c_void,
+                          async_handle: *uv_async_t,
+                          cb: *u8) -> c_int;
+    fn rust_uv_tcp_init(loop_handle: *c_void, handle_ptr: *uv_tcp_t) -> c_int;
+    // FIXME ref #2604 .. ?
+    fn rust_uv_buf_init(out_buf: *uv_buf_t, base: *u8, len: size_t);
+    fn rust_uv_last_error(loop_handle: *c_void) -> uv_err_t;
+    // FIXME ref #2064
+    fn rust_uv_strerror(err: *uv_err_t) -> *c_char;
+    // FIXME ref #2064
+    fn rust_uv_err_name(err: *uv_err_t) -> *c_char;
+    fn rust_uv_ip4_addrp(ip: *u8, port: c_int) -> *sockaddr_in;
+    fn rust_uv_ip6_addrp(ip: *u8, port: c_int) -> *sockaddr_in6;
+    fn rust_uv_free_ip4_addr(addr: *sockaddr_in);
+    fn rust_uv_free_ip6_addr(addr: *sockaddr_in6);
+    fn rust_uv_ip4_name(src: *sockaddr_in, dst: *u8, size: size_t) -> c_int;
+    fn rust_uv_ip6_name(src: *sockaddr_in6, dst: *u8, size: size_t) -> c_int;
+    fn rust_uv_ip4_port(src: *sockaddr_in) -> c_uint;
+    fn rust_uv_ip6_port(src: *sockaddr_in6) -> c_uint;
+    // FIXME ref #2064
+    fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t,
+                           tcp_handle_ptr: *uv_tcp_t,
+                           after_cb: *u8,
+                           addr: *sockaddr_in) -> c_int;
+    // FIXME ref #2064
+    fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t, addr: *sockaddr_in) -> c_int;
+    // FIXME ref #2064
+    fn rust_uv_tcp_connect6(connect_ptr: *uv_connect_t,
+                            tcp_handle_ptr: *uv_tcp_t,
+                            after_cb: *u8,
+                            addr: *sockaddr_in6) -> c_int;
+    // FIXME ref #2064
+    fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t, addr: *sockaddr_in6) -> c_int;
+    fn rust_uv_tcp_getpeername(tcp_handle_ptr: *uv_tcp_t,
+                               name: *sockaddr_in) -> c_int;
+    fn rust_uv_tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t,
+                                name: *sockaddr_in6) ->c_int;
+    fn rust_uv_listen(stream: *c_void, backlog: c_int, cb: *u8) -> c_int;
+    fn rust_uv_accept(server: *c_void, client: *c_void) -> c_int;
+    fn rust_uv_write(req: *c_void,
+                     stream: *c_void,
+                     buf_in: *uv_buf_t,
+                     buf_cnt: c_int,
+                     cb: *u8) -> c_int;
+    fn rust_uv_read_start(stream: *c_void,
+                          on_alloc: *u8,
+                          on_read: *u8) -> c_int;
+    fn rust_uv_read_stop(stream: *c_void) -> c_int;
+    fn rust_uv_timer_init(loop_handle: *c_void,
+                          timer_handle: *uv_timer_t) -> c_int;
+    fn rust_uv_timer_start(timer_handle: *uv_timer_t,
+                           cb: *u8,
+                           timeout: c_uint,
+                           repeat: c_uint) -> c_int;
+    fn rust_uv_timer_stop(handle: *uv_timer_t) -> c_int;
+
+    fn rust_uv_malloc_buf_base_of(sug_size: size_t) -> *u8;
+    fn rust_uv_free_base_of_buf(buf: uv_buf_t);
+    fn rust_uv_get_stream_handle_from_connect_req(connect_req: *uv_connect_t) -> *uv_stream_t;
+    fn rust_uv_get_stream_handle_from_write_req(write_req: *uv_write_t) -> *uv_stream_t;
+    fn rust_uv_get_loop_for_uv_handle(handle: *c_void) -> *c_void;
+    fn rust_uv_get_data_for_uv_loop(loop_ptr: *c_void) -> *c_void;
+    fn rust_uv_set_data_for_uv_loop(loop_ptr: *c_void, data: *c_void);
+    fn rust_uv_get_data_for_uv_handle(handle: *c_void) -> *c_void;
+    fn rust_uv_set_data_for_uv_handle(handle: *c_void, data: *c_void);
+    fn rust_uv_get_data_for_req(req: *c_void) -> *c_void;
+    fn rust_uv_set_data_for_req(req: *c_void, data: *c_void);
+    fn rust_uv_get_base_from_buf(buf: uv_buf_t) -> *u8;
+    fn rust_uv_get_len_from_buf(buf: uv_buf_t) -> size_t;
+}
diff --git a/src/libstd/rt/work_queue.rs b/src/libstd/rt/work_queue.rs
new file mode 100644
index 00000000000..e9eb663392b
--- /dev/null
+++ b/src/libstd/rt/work_queue.rs
@@ -0,0 +1,67 @@
+// 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 option::*;
+use vec::OwnedVector;
+use unstable::sync::{Exclusive, exclusive};
+use cell::Cell;
+use kinds::Owned;
+use clone::Clone;
+
+pub struct WorkQueue<T> {
+    // XXX: Another mystery bug fixed by boxing this lock
+    priv queue: ~Exclusive<~[T]>
+}
+
+pub impl<T: Owned> WorkQueue<T> {
+    fn new() -> WorkQueue<T> {
+        WorkQueue {
+            queue: ~exclusive(~[])
+        }
+    }
+
+    fn push(&mut self, value: T) {
+        let value = Cell(value);
+        self.queue.with(|q| q.unshift(value.take()) );
+    }
+
+    fn pop(&mut self) -> Option<T> {
+        do self.queue.with |q| {
+            if !q.is_empty() {
+                Some(q.shift())
+            } else {
+                None
+            }
+        }
+    }
+
+    fn steal(&mut self) -> Option<T> {
+        do self.queue.with |q| {
+            if !q.is_empty() {
+                Some(q.pop())
+            } else {
+                None
+            }
+        }
+    }
+
+    fn is_empty(&self) -> bool {
+        self.queue.with_imm(|q| q.is_empty() )
+    }
+}
+
+impl<T> Clone for WorkQueue<T> {
+    fn clone(&self) -> WorkQueue<T> {
+        WorkQueue {
+            queue: self.queue.clone()
+        }
+    }
+}
diff --git a/src/libstd/run.rs b/src/libstd/run.rs
new file mode 100644
index 00000000000..02757ab4899
--- /dev/null
+++ b/src/libstd/run.rs
@@ -0,0 +1,856 @@
+// 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.
+
+//! Process spawning
+use cast;
+use io;
+use libc;
+use libc::{pid_t, c_void, c_int};
+use comm::{stream, SharedChan, GenericChan, GenericPort};
+use option::{Some, None};
+use os;
+use prelude::*;
+use ptr;
+use str;
+use task;
+use vec;
+
+/// A value representing a child process
+pub struct Program {
+    priv pid: pid_t,
+    priv handle: *(),
+    priv in_fd: c_int,
+    priv out_file: *libc::FILE,
+    priv err_file: *libc::FILE,
+    priv finished: bool,
+}
+
+impl Drop for Program {
+    fn finalize(&self) {
+        // FIXME #4943: transmute is bad.
+        let mut_self: &mut Program = unsafe { cast::transmute(self) };
+
+        mut_self.finish();
+        mut_self.close_outputs();
+        free_handle(self.handle);
+    }
+}
+
+pub impl Program {
+
+    /// Returns the process id of the program
+    fn get_id(&mut self) -> pid_t { self.pid }
+
+    /// Returns an io::Writer that can be used to write to stdin
+    fn input(&mut self) -> @io::Writer {
+        io::fd_writer(self.in_fd, false)
+    }
+
+    /// Returns an io::Reader that can be used to read from stdout
+    fn output(&mut self) -> @io::Reader {
+        io::FILE_reader(self.out_file, false)
+    }
+
+    /// Returns an io::Reader that can be used to read from stderr
+    fn err(&mut self) -> @io::Reader {
+        io::FILE_reader(self.err_file, false)
+    }
+
+    /// Closes the handle to the child processes standard input
+    fn close_input(&mut self) {
+        let invalid_fd = -1i32;
+        if self.in_fd != invalid_fd {
+            unsafe {
+                libc::close(self.in_fd);
+            }
+            self.in_fd = invalid_fd;
+        }
+    }
+
+    priv fn close_outputs(&mut self) {
+        unsafe {
+            fclose_and_null(&mut self.out_file);
+            fclose_and_null(&mut self.err_file);
+        }
+    }
+
+    /**
+     * Waits for the child process to terminate. Closes the handle
+     * to stdin if necessary.
+     */
+    fn finish(&mut self) -> int {
+        if self.finished { return 0; }
+        self.finished = true;
+        self.close_input();
+        return waitpid(self.pid);
+    }
+
+    priv fn destroy_internal(&mut self, force: bool) {
+        killpid(self.pid, force);
+        self.finish();
+        self.close_outputs();
+
+        #[cfg(windows)]
+        fn killpid(pid: pid_t, _force: bool) {
+            unsafe {
+                libc::funcs::extra::kernel32::TerminateProcess(
+                    cast::transmute(pid), 1);
+            }
+        }
+
+        #[cfg(unix)]
+        fn killpid(pid: pid_t, force: bool) {
+            let signal = if force {
+                libc::consts::os::posix88::SIGKILL
+            } else {
+                libc::consts::os::posix88::SIGTERM
+            };
+
+            unsafe {
+                libc::funcs::posix88::signal::kill(pid, signal as c_int);
+            }
+        }
+    }
+
+    /**
+     * Terminate the program, giving it a chance to clean itself up if
+     * this is supported by the operating system.
+     *
+     * On Posix OSs SIGTERM will be sent to the process. On Win32
+     * TerminateProcess(..) will be called.
+     */
+    fn destroy(&mut self) { self.destroy_internal(false); }
+
+    /**
+     * Terminate the program as soon as possible without giving it a
+     * chance to clean itself up.
+     *
+     * On Posix OSs SIGKILL will be sent to the process. On Win32
+     * TerminateProcess(..) will be called.
+     */
+    fn force_destroy(&mut self) { self.destroy_internal(true); }
+}
+
+
+/**
+ * Run a program, providing stdin, stdout and stderr handles
+ *
+ * # Arguments
+ *
+ * * prog - The path to an executable
+ * * args - Vector of arguments to pass to the child process
+ * * env - optional env-modification for child
+ * * dir - optional dir to run child in (default current dir)
+ * * in_fd - A file descriptor for the child to use as std input
+ * * out_fd - A file descriptor for the child to use as std output
+ * * err_fd - A file descriptor for the child to use as std error
+ *
+ * # Return value
+ *
+ * The process id of the spawned process
+ */
+pub fn spawn_process(prog: &str, args: &[~str],
+                     env: &Option<~[(~str,~str)]>,
+                     dir: &Option<~str>,
+                     in_fd: c_int, out_fd: c_int, err_fd: c_int) -> pid_t {
+
+    let res = spawn_process_internal(prog, args, env, dir, in_fd, out_fd, err_fd);
+    free_handle(res.handle);
+    return res.pid;
+}
+
+struct RunProgramResult {
+    // the process id of the program (this should never be negative)
+    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.
+    handle: *(),
+}
+
+#[cfg(windows)]
+fn spawn_process_internal(prog: &str, args: &[~str],
+                          env: &Option<~[(~str,~str)]>,
+                          dir: &Option<~str>,
+                          in_fd: c_int, out_fd: c_int, err_fd: c_int) -> RunProgramResult {
+
+    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;
+
+    unsafe {
+
+        let mut si = zeroed_startupinfo();
+        si.cb = sys::size_of::<STARTUPINFO>() as DWORD;
+        si.dwFlags = STARTF_USESTDHANDLES;
+
+        let cur_proc = GetCurrentProcess();
+
+        let orig_std_in = get_osfhandle(if in_fd > 0 { in_fd } else { 0 }) as HANDLE;
+        if orig_std_in == INVALID_HANDLE_VALUE as HANDLE {
+            fail!("failure in get_osfhandle: %s", 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: %s", os::last_os_error());
+        }
+
+        let orig_std_out = get_osfhandle(if out_fd > 0 { out_fd } else { 1 }) as HANDLE;
+        if orig_std_out == INVALID_HANDLE_VALUE as HANDLE {
+            fail!("failure in get_osfhandle: %s", 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: %s", os::last_os_error());
+        }
+
+        let orig_std_err = get_osfhandle(if err_fd > 0 { err_fd } else { 2 }) as HANDLE;
+        if orig_std_err as HANDLE == INVALID_HANDLE_VALUE as HANDLE {
+            fail!("failure in get_osfhandle: %s", 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: %s", 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 str::as_c_str(cmd) |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 create_err.each |msg| {
+            fail!("failure in CreateProcess: %s", *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);
+
+        RunProgramResult {
+            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 args.each |arg| {
+        cmd.push_char(' ');
+        append_arg(&mut cmd, *arg);
+    }
+    return cmd;
+
+    fn append_arg(cmd: &mut ~str, arg: &str) {
+        let quote = arg.any(|c| c == ' ' || c == '\t');
+        if quote {
+            cmd.push_char('"');
+        }
+        for uint::range(0, arg.len()) |i| {
+            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_internal(prog: &str, args: &[~str],
+                          env: &Option<~[(~str,~str)]>,
+                          dir: &Option<~str>,
+                          in_fd: c_int, out_fd: c_int, err_fd: c_int) -> RunProgramResult {
+
+    use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
+    use libc::funcs::bsd44::getdtablesize;
+
+    mod rustrt {
+        use libc::c_void;
+
+        #[abi = "cdecl"]
+        pub extern {
+            unsafe fn rust_unset_sigprocmask();
+            unsafe fn rust_set_environ(envp: *c_void);
+        }
+    }
+
+    unsafe {
+
+        let pid = fork();
+        if pid < 0 {
+            fail!("failure in fork: %s", os::last_os_error());
+        } else if pid > 0 {
+            return RunProgramResult {pid: pid, handle: ptr::null()};
+        }
+
+        rustrt::rust_unset_sigprocmask();
+
+        if in_fd > 0 && dup2(in_fd, 0) == -1 {
+            fail!("failure in dup2(in_fd, 0): %s", os::last_os_error());
+        }
+        if out_fd > 0 && dup2(out_fd, 1) == -1 {
+            fail!("failure in dup2(out_fd, 1): %s", os::last_os_error());
+        }
+        if err_fd > 0 && dup2(err_fd, 2) == -1 {
+            fail!("failure in dup3(err_fd, 2): %s", os::last_os_error());
+        }
+        // close all other fds
+        for int::range_rev(getdtablesize() as int - 1, 2) |fd| {
+            close(fd as c_int);
+        }
+
+        for dir.each |dir| {
+            do str::as_c_str(*dir) |dirp| {
+                if chdir(dirp) == -1 {
+                    fail!("failure in chdir: %s", os::last_os_error());
+                }
+            }
+        }
+
+        do with_envp(env) |envp| {
+            if !envp.is_null() {
+                rustrt::rust_set_environ(envp);
+            }
+            do with_argv(prog, args) |argv| {
+                execvp(*argv, argv);
+                // execvp only returns if an error occurred
+                fail!("failure in execvp: %s", os::last_os_error());
+            }
+        }
+    }
+}
+
+#[cfg(unix)]
+fn with_argv<T>(prog: &str, args: &[~str],
+                cb: &fn(**libc::c_char) -> T) -> T {
+    let mut argptrs = str::as_c_str(prog, |b| ~[b]);
+    let mut tmps = ~[];
+    for args.each |arg| {
+        let t = @copy *arg;
+        tmps.push(t);
+        argptrs.push_all(str::as_c_str(*t, |b| ~[b]));
+    }
+    argptrs.push(ptr::null());
+    vec::as_imm_buf(argptrs, |buf, _len| cb(buf))
+}
+
+#[cfg(unix)]
+fn with_envp<T>(env: &Option<~[(~str,~str)]>,
+                cb: &fn(*c_void) -> T) -> T {
+    // On posixy systems we can pass a char** for envp, which is
+    // a null-terminated array of "k=v\n" strings.
+    match *env {
+      Some(ref es) if !vec::is_empty(*es) => {
+        let mut tmps = ~[];
+        let mut ptrs = ~[];
+
+        for (*es).each |e| {
+            let (k,v) = copy *e;
+            let t = @(fmt!("%s=%s", k, v));
+            tmps.push(t);
+            ptrs.push_all(str::as_c_str(*t, |b| ~[b]));
+        }
+        ptrs.push(ptr::null());
+        vec::as_imm_buf(ptrs, |p, _len|
+            unsafe { cb(::cast::transmute(p)) }
+        )
+      }
+      _ => 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.
+    unsafe {
+        match *env {
+          Some(ref es) if !vec::is_empty(*es) => {
+            let mut blk : ~[u8] = ~[];
+            for (*es).each |e| {
+                let (k,v) = copy *e;
+                let t = fmt!("%s=%s", k, v);
+                let mut v : ~[u8] = ::cast::transmute(t);
+                blk += v;
+                ::cast::forget(v);
+            }
+            blk += ~[0_u8];
+            vec::as_imm_buf(blk, |p, _len| cb(::cast::transmute(p)))
+          }
+          _ => cb(ptr::mut_null())
+        }
+    }
+}
+
+#[cfg(windows)]
+fn with_dirp<T>(d: &Option<~str>,
+                cb: &fn(*libc::c_char) -> T) -> T {
+    match *d {
+      Some(ref dir) => str::as_c_str(*dir, cb),
+      None => cb(ptr::null())
+    }
+}
+
+/// helper function that closes non-NULL files and then makes them NULL
+priv unsafe fn fclose_and_null(f: &mut *libc::FILE) {
+    if *f != 0 as *libc::FILE {
+        libc::fclose(*f);
+        *f = 0 as *libc::FILE;
+    }
+}
+
+#[cfg(windows)]
+priv fn free_handle(handle: *()) {
+    unsafe {
+        libc::funcs::extra::kernel32::CloseHandle(cast::transmute(handle));
+    }
+}
+
+#[cfg(unix)]
+priv fn free_handle(_handle: *()) {
+    // unix has no process handle object, just a pid
+}
+
+/**
+ * Spawns a process and waits for it to terminate
+ *
+ * # Arguments
+ *
+ * * prog - The path to an executable
+ * * args - Vector of arguments to pass to the child process
+ *
+ * # Return value
+ *
+ * The process's exit code
+ */
+pub fn run_program(prog: &str, args: &[~str]) -> int {
+    let res = spawn_process_internal(prog, args, &None, &None,
+                                     0i32, 0i32, 0i32);
+    let code = waitpid(res.pid);
+    free_handle(res.handle);
+    return code;
+}
+
+/**
+ * Spawns a process and returns a Program
+ *
+ * The returned value is a <Program> object that can be used for sending and
+ * receiving data over the standard file descriptors.  The class will ensure
+ * that file descriptors are closed properly.
+ *
+ * # Arguments
+ *
+ * * prog - The path to an executable
+ * * args - Vector of arguments to pass to the child process
+ *
+ * # Return value
+ *
+ * A <Program> object
+ */
+pub fn start_program(prog: &str, args: &[~str]) -> Program {
+    let pipe_input = os::pipe();
+    let pipe_output = os::pipe();
+    let pipe_err = os::pipe();
+    let res =
+        spawn_process_internal(prog, args, &None, &None,
+                               pipe_input.in, pipe_output.out,
+                               pipe_err.out);
+
+    unsafe {
+        libc::close(pipe_input.in);
+        libc::close(pipe_output.out);
+        libc::close(pipe_err.out);
+    }
+
+    Program {
+        pid: res.pid,
+        handle: res.handle,
+        in_fd: pipe_input.out,
+        out_file: os::fdopen(pipe_output.in),
+        err_file: os::fdopen(pipe_err.in),
+        finished: false,
+    }
+}
+
+fn read_all(rd: @io::Reader) -> ~str {
+    let buf = io::with_bytes_writer(|wr| {
+        let mut bytes = [0, ..4096];
+        while !rd.eof() {
+            let nread = rd.read(bytes, bytes.len());
+            wr.write(bytes.slice(0, nread));
+        }
+    });
+    str::from_bytes(buf)
+}
+
+pub struct ProgramOutput {status: int, out: ~str, err: ~str}
+
+/**
+ * Spawns a process, waits for it to exit, and returns the exit code, and
+ * contents of stdout and stderr.
+ *
+ * # Arguments
+ *
+ * * prog - The path to an executable
+ * * args - Vector of arguments to pass to the child process
+ *
+ * # Return value
+ *
+ * A record, {status: int, out: str, err: str} containing the exit code,
+ * the contents of stdout and the contents of stderr.
+ */
+pub fn program_output(prog: &str, args: &[~str]) -> ProgramOutput {
+    let pipe_in = os::pipe();
+    let pipe_out = os::pipe();
+    let pipe_err = os::pipe();
+    let res = spawn_process_internal(prog, args, &None, &None,
+                                     pipe_in.in, pipe_out.out, pipe_err.out);
+
+    os::close(pipe_in.in);
+    os::close(pipe_out.out);
+    os::close(pipe_err.out);
+    os::close(pipe_in.out);
+
+    // Spawn two entire schedulers to read both stdout and sterr
+    // in parallel so we don't deadlock while blocking on one
+    // or the other. FIXME (#2625): Surely there's a much more
+    // clever way to do this.
+    let (p, ch) = stream();
+    let ch = SharedChan::new(ch);
+    let ch_clone = ch.clone();
+    do task::spawn_sched(task::SingleThreaded) {
+        let errput = readclose(pipe_err.in);
+        ch.send((2, errput));
+    };
+    do task::spawn_sched(task::SingleThreaded) {
+        let output = readclose(pipe_out.in);
+        ch_clone.send((1, output));
+    };
+
+    let status = waitpid(res.pid);
+    free_handle(res.handle);
+
+    let mut errs = ~"";
+    let mut outs = ~"";
+    let mut count = 2;
+    while count > 0 {
+        let stream = p.recv();
+        match stream {
+            (1, copy s) => {
+                outs = s;
+            }
+            (2, copy s) => {
+                errs = s;
+            }
+            (n, _) => {
+                fail!("program_output received an unexpected file number: %u", n);
+            }
+        };
+        count -= 1;
+    };
+    return ProgramOutput {status: status,
+                          out: outs,
+                          err: errs};
+}
+
+pub fn writeclose(fd: c_int, s: ~str) {
+    use io::WriterUtil;
+
+    error!("writeclose %d, %s", fd as int, s);
+    let writer = io::fd_writer(fd, false);
+    writer.write_str(s);
+
+    os::close(fd);
+}
+
+pub fn readclose(fd: c_int) -> ~str {
+    unsafe {
+        let file = os::fdopen(fd);
+        let reader = io::FILE_reader(file, false);
+        let buf = io::with_bytes_writer(|writer| {
+            let mut bytes = [0, ..4096];
+            while !reader.eof() {
+                let nread = reader.read(bytes, bytes.len());
+                writer.write(bytes.slice(0, nread));
+            }
+        });
+        os::fclose(file);
+        str::from_bytes(buf)
+    }
+}
+
+/**
+ * Waits for a process to exit and returns the exit code, failing
+ * if there is no process with the specified id.
+ */
+pub 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 proc = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid as DWORD);
+            if proc.is_null() {
+                fail!("failure in OpenProcess: %s", os::last_os_error());
+            }
+
+            loop {
+                let mut status = 0;
+                if GetExitCodeProcess(proc, &mut status) == FALSE {
+                    CloseHandle(proc);
+                    fail!("failure in GetExitCodeProcess: %s", os::last_os_error());
+                }
+                if status != STILL_ACTIVE {
+                    CloseHandle(proc);
+                    return status as int;
+                }
+                if WaitForSingleObject(proc, INFINITE) == WAIT_FAILED {
+                    CloseHandle(proc);
+                    fail!("failure in WaitForSingleObject: %s", 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: %s", os::last_os_error());
+        }
+
+        return if WIFEXITED(status) {
+            WEXITSTATUS(status) as int
+        } else {
+            1
+        };
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use option::None;
+    use os;
+    use run::{readclose, writeclose};
+    use run;
+
+    #[test]
+    #[cfg(windows)]
+    fn test_make_command_line() {
+        assert_eq!(
+            run::make_command_line("prog", [~"aaa", ~"bbb", ~"ccc"]),
+            ~"prog aaa bbb ccc"
+        );
+        assert_eq!(
+            run::make_command_line("C:\\Program Files\\blah\\blah.exe", [~"aaa"]),
+            ~"\"C:\\Program Files\\blah\\blah.exe\" aaa"
+        );
+        assert_eq!(
+            run::make_command_line("C:\\Program Files\\test", [~"aa\"bb"]),
+            ~"\"C:\\Program Files\\test\" aa\\\"bb"
+        );
+        assert_eq!(
+            run::make_command_line("echo", [~"a b c"]),
+            ~"echo \"a b c\""
+        );
+    }
+
+    // Regression test for memory leaks
+    #[test]
+    fn test_leaks() {
+        run::run_program("echo", []);
+        run::start_program("echo", []);
+        run::program_output("echo", []);
+    }
+
+    #[test]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_pipes() {
+        let pipe_in = os::pipe();
+        let pipe_out = os::pipe();
+        let pipe_err = os::pipe();
+
+        let pid =
+            run::spawn_process(
+                "cat", [], &None, &None,
+                pipe_in.in, pipe_out.out, pipe_err.out);
+        os::close(pipe_in.in);
+        os::close(pipe_out.out);
+        os::close(pipe_err.out);
+
+        if pid == -1i32 { fail!(); }
+        let expected = ~"test";
+        writeclose(pipe_in.out, copy expected);
+        let actual = readclose(pipe_out.in);
+        readclose(pipe_err.in);
+        run::waitpid(pid);
+
+        debug!(copy expected);
+        debug!(copy actual);
+        assert_eq!(expected, actual);
+    }
+
+    #[test]
+    fn waitpid() {
+        let pid = run::spawn_process("false", [],
+                                     &None, &None,
+                                     0i32, 0i32, 0i32);
+        let status = run::waitpid(pid);
+        assert_eq!(status, 1);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn waitpid_non_existant_pid() {
+        run::waitpid(123456789); // assume that this pid doesn't exist
+    }
+}
diff --git a/src/libstd/semver.rs b/src/libstd/semver.rs
deleted file mode 100644
index 09855c9334e..00000000000
--- a/src/libstd/semver.rs
+++ /dev/null
@@ -1,394 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Semver parsing and logic
-
-use core::char;
-use core::cmp;
-use core::io::{ReaderUtil};
-use core::io;
-use core::option::{Option, Some, None};
-use core::str;
-use core::to_str::ToStr;
-use core::uint;
-
-#[deriving(Eq)]
-pub enum Identifier {
-    Numeric(uint),
-    AlphaNumeric(~str)
-}
-
-impl cmp::Ord for Identifier {
-    #[inline(always)]
-    fn lt(&self, other: &Identifier) -> bool {
-        match (self, other) {
-            (&Numeric(a), &Numeric(b)) => a < b,
-            (&Numeric(_), _) => true,
-            (&AlphaNumeric(ref a), &AlphaNumeric(ref b)) => *a < *b,
-            (&AlphaNumeric(_), _) => false
-        }
-    }
-    #[inline(always)]
-    fn le(&self, other: &Identifier) -> bool {
-        ! (other < self)
-    }
-    #[inline(always)]
-    fn gt(&self, other: &Identifier) -> bool {
-        other < self
-    }
-    #[inline(always)]
-    fn ge(&self, other: &Identifier) -> bool {
-        ! (self < other)
-    }
-}
-
-impl ToStr for Identifier {
-    #[inline(always)]
-    fn to_str(&self) -> ~str {
-        match self {
-            &Numeric(n) => n.to_str(),
-            &AlphaNumeric(ref s) => s.to_str()
-        }
-    }
-}
-
-
-#[deriving(Eq)]
-pub struct Version {
-    major: uint,
-    minor: uint,
-    patch: uint,
-    pre: ~[Identifier],
-    build: ~[Identifier],
-}
-
-impl ToStr for Version {
-    #[inline(always)]
-    fn to_str(&self) -> ~str {
-        let s = fmt!("%u.%u.%u", self.major, self.minor, self.patch);
-        let s = if self.pre.is_empty() {
-            s
-        } else {
-            s + "-" + str::connect(self.pre.map(|i| i.to_str()), ".")
-        };
-        if self.build.is_empty() {
-            s
-        } else {
-            s + "+" + str::connect(self.build.map(|i| i.to_str()), ".")
-        }
-    }
-}
-
-impl cmp::Ord for Version {
-    #[inline(always)]
-    fn lt(&self, other: &Version) -> bool {
-
-        self.major < other.major ||
-
-            (self.major == other.major &&
-             self.minor < other.minor) ||
-
-            (self.major == other.major &&
-             self.minor == other.minor &&
-             self.patch < other.patch) ||
-
-            (self.major == other.major &&
-             self.minor == other.minor &&
-             self.patch == other.patch &&
-             // NB: semver spec says 0.0.0-pre < 0.0.0
-             // but the version of ord defined for vec
-             // says that [] < [pre], so we alter it
-             // here.
-             (match (self.pre.len(), other.pre.len()) {
-                 (0, 0) => false,
-                 (0, _) => false,
-                 (_, 0) => true,
-                 (_, _) => self.pre < other.pre
-             })) ||
-
-            (self.major == other.major &&
-             self.minor == other.minor &&
-             self.patch == other.patch &&
-             self.pre == other.pre &&
-             self.build < other.build)
-    }
-
-    #[inline(always)]
-    fn le(&self, other: &Version) -> bool {
-        ! (other < self)
-    }
-    #[inline(always)]
-    fn gt(&self, other: &Version) -> bool {
-        other < self
-    }
-    #[inline(always)]
-    fn ge(&self, other: &Version) -> bool {
-        ! (self < other)
-    }
-}
-
-condition! {
-    bad_parse: () -> ();
-}
-
-fn take_nonempty_prefix(rdr: @io::Reader,
-                        ch: char,
-                        pred: &fn(char) -> bool) -> (~str, char) {
-    let mut buf = ~"";
-    let mut ch = ch;
-    while pred(ch) {
-        str::push_char(&mut buf, ch);
-        ch = rdr.read_char();
-    }
-    if buf.is_empty() {
-        bad_parse::cond.raise(())
-    }
-    debug!("extracted nonempty prefix: %s", buf);
-    (buf, ch)
-}
-
-fn take_num(rdr: @io::Reader, ch: char) -> (uint, char) {
-    let (s, ch) = take_nonempty_prefix(rdr, ch, char::is_digit);
-    match uint::from_str(s) {
-        None => { bad_parse::cond.raise(()); (0, ch) },
-        Some(i) => (i, ch)
-    }
-}
-
-fn take_ident(rdr: @io::Reader, ch: char) -> (Identifier, char) {
-    let (s,ch) = take_nonempty_prefix(rdr, ch, char::is_alphanumeric);
-    if s.all(char::is_digit) {
-        match uint::from_str(s) {
-            None => { bad_parse::cond.raise(()); (Numeric(0), ch) },
-            Some(i) => (Numeric(i), ch)
-        }
-    } else {
-        (AlphaNumeric(s), ch)
-    }
-}
-
-fn expect(ch: char, c: char) {
-    if ch != c {
-        bad_parse::cond.raise(())
-    }
-}
-
-fn parse_reader(rdr: @io::Reader) -> Version {
-    let (major, ch) = take_num(rdr, rdr.read_char());
-    expect(ch, '.');
-    let (minor, ch) = take_num(rdr, rdr.read_char());
-    expect(ch, '.');
-    let (patch, ch) = take_num(rdr, rdr.read_char());
-
-    let mut pre = ~[];
-    let mut build = ~[];
-
-    let mut ch = ch;
-    if ch == '-' {
-        loop {
-            let (id, c) = take_ident(rdr, rdr.read_char());
-            pre.push(id);
-            ch = c;
-            if ch != '.' { break; }
-        }
-    }
-
-    if ch == '+' {
-        loop {
-            let (id, c) = take_ident(rdr, rdr.read_char());
-            build.push(id);
-            ch = c;
-            if ch != '.' { break; }
-        }
-    }
-
-    Version {
-        major: major,
-        minor: minor,
-        patch: patch,
-        pre: pre,
-        build: build,
-    }
-}
-
-
-pub fn parse(s: &str) -> Option<Version> {
-    if !s.is_ascii() {
-        return None;
-    }
-    let s = s.trim();
-    let mut bad = false;
-    do bad_parse::cond.trap(|_| { debug!("bad"); bad = true }).in {
-        do io::with_str_reader(s) |rdr| {
-            let v = parse_reader(rdr);
-            if bad || v.to_str() != s.to_owned() {
-                None
-            } else {
-                Some(v)
-            }
-        }
-    }
-}
-
-#[test]
-fn test_parse() {
-    assert_eq!(parse(""), None);
-    assert_eq!(parse("  "), None);
-    assert_eq!(parse("1"), None);
-    assert_eq!(parse("1.2"), None);
-    assert_eq!(parse("1.2"), None);
-    assert_eq!(parse("1"), None);
-    assert_eq!(parse("1.2"), None);
-    assert_eq!(parse("1.2.3-"), None);
-    assert_eq!(parse("a.b.c"), None);
-    assert_eq!(parse("1.2.3 abc"), None);
-
-    assert!(parse("1.2.3") == Some(Version {
-        major: 1u,
-        minor: 2u,
-        patch: 3u,
-        pre: ~[],
-        build: ~[],
-    }));
-    assert!(parse("  1.2.3  ") == Some(Version {
-        major: 1u,
-        minor: 2u,
-        patch: 3u,
-        pre: ~[],
-        build: ~[],
-    }));
-    assert!(parse("1.2.3-alpha1") == Some(Version {
-        major: 1u,
-        minor: 2u,
-        patch: 3u,
-        pre: ~[AlphaNumeric(~"alpha1")],
-        build: ~[]
-    }));
-    assert!(parse("  1.2.3-alpha1  ") == Some(Version {
-        major: 1u,
-        minor: 2u,
-        patch: 3u,
-        pre: ~[AlphaNumeric(~"alpha1")],
-        build: ~[]
-    }));
-    assert!(parse("1.2.3+build5") == Some(Version {
-        major: 1u,
-        minor: 2u,
-        patch: 3u,
-        pre: ~[],
-        build: ~[AlphaNumeric(~"build5")]
-    }));
-    assert!(parse("  1.2.3+build5  ") == Some(Version {
-        major: 1u,
-        minor: 2u,
-        patch: 3u,
-        pre: ~[],
-        build: ~[AlphaNumeric(~"build5")]
-    }));
-    assert!(parse("1.2.3-alpha1+build5") == Some(Version {
-        major: 1u,
-        minor: 2u,
-        patch: 3u,
-        pre: ~[AlphaNumeric(~"alpha1")],
-        build: ~[AlphaNumeric(~"build5")]
-    }));
-    assert!(parse("  1.2.3-alpha1+build5  ") == Some(Version {
-        major: 1u,
-        minor: 2u,
-        patch: 3u,
-        pre: ~[AlphaNumeric(~"alpha1")],
-        build: ~[AlphaNumeric(~"build5")]
-    }));
-    assert!(parse("1.2.3-1.alpha1.9+build5.7.3aedf  ") == Some(Version {
-        major: 1u,
-        minor: 2u,
-        patch: 3u,
-        pre: ~[Numeric(1),AlphaNumeric(~"alpha1"),Numeric(9)],
-        build: ~[AlphaNumeric(~"build5"),
-                 Numeric(7),
-                 AlphaNumeric(~"3aedf")]
-    }));
-
-}
-
-#[test]
-fn test_eq() {
-    assert_eq!(parse("1.2.3"), parse("1.2.3"));
-    assert_eq!(parse("1.2.3-alpha1"), parse("1.2.3-alpha1"));
-}
-
-#[test]
-fn test_ne() {
-    assert!(parse("0.0.0")       != parse("0.0.1"));
-    assert!(parse("0.0.0")       != parse("0.1.0"));
-    assert!(parse("0.0.0")       != parse("1.0.0"));
-    assert!(parse("1.2.3-alpha") != parse("1.2.3-beta"));
-}
-
-#[test]
-fn test_lt() {
-    assert!(parse("0.0.0")        < parse("1.2.3-alpha2"));
-    assert!(parse("1.0.0")        < parse("1.2.3-alpha2"));
-    assert!(parse("1.2.0")        < parse("1.2.3-alpha2"));
-    assert!(parse("1.2.3-alpha1") < parse("1.2.3"));
-    assert!(parse("1.2.3-alpha1") < parse("1.2.3-alpha2"));
-    assert!(!(parse("1.2.3-alpha2") < parse("1.2.3-alpha2")));
-}
-
-#[test]
-fn test_le() {
-    assert!(parse("0.0.0")        <= parse("1.2.3-alpha2"));
-    assert!(parse("1.0.0")        <= parse("1.2.3-alpha2"));
-    assert!(parse("1.2.0")        <= parse("1.2.3-alpha2"));
-    assert!(parse("1.2.3-alpha1") <= parse("1.2.3-alpha2"));
-    assert!(parse("1.2.3-alpha2") <= parse("1.2.3-alpha2"));
-}
-
-#[test]
-fn test_gt() {
-    assert!(parse("1.2.3-alpha2") > parse("0.0.0"));
-    assert!(parse("1.2.3-alpha2") > parse("1.0.0"));
-    assert!(parse("1.2.3-alpha2") > parse("1.2.0"));
-    assert!(parse("1.2.3-alpha2") > parse("1.2.3-alpha1"));
-    assert!(parse("1.2.3")        > parse("1.2.3-alpha2"));
-    assert!(!(parse("1.2.3-alpha2") > parse("1.2.3-alpha2")));
-}
-
-#[test]
-fn test_ge() {
-    assert!(parse("1.2.3-alpha2") >= parse("0.0.0"));
-    assert!(parse("1.2.3-alpha2") >= parse("1.0.0"));
-    assert!(parse("1.2.3-alpha2") >= parse("1.2.0"));
-    assert!(parse("1.2.3-alpha2") >= parse("1.2.3-alpha1"));
-    assert!(parse("1.2.3-alpha2") >= parse("1.2.3-alpha2"));
-}
-
-#[test]
-fn test_spec_order() {
-
-    let vs = ["1.0.0-alpha",
-              "1.0.0-alpha.1",
-              "1.0.0-beta.2",
-              "1.0.0-beta.11",
-              "1.0.0-rc.1",
-              "1.0.0-rc.1+build.1",
-              "1.0.0",
-              "1.0.0+0.3.7",
-              "1.3.7+build",
-              "1.3.7+build.2.b8f12d7",
-              "1.3.7+build.11.e0f985a"];
-    let mut i = 1;
-    while i < vs.len() {
-        let a = parse(vs[i-1]).get();
-        let b = parse(vs[i]).get();
-        assert!(a < b);
-        i += 1;
-    }
-}
diff --git a/src/libstd/serialize.rs b/src/libstd/serialize.rs
deleted file mode 100644
index c270f46751f..00000000000
--- a/src/libstd/serialize.rs
+++ /dev/null
@@ -1,907 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Support code for encoding and decoding types.
-
-/*
-Core encoding and decoding interfaces.
-*/
-
-#[forbid(non_camel_case_types)];
-
-use core::hashmap::{HashMap, HashSet};
-use core::trie::{TrieMap, TrieSet};
-use deque::Deque;
-use dlist::DList;
-use treemap::{TreeMap, TreeSet};
-
-pub trait Encoder {
-    // Primitive types:
-    fn emit_nil(&mut self);
-    fn emit_uint(&mut self, v: uint);
-    fn emit_u64(&mut self, v: u64);
-    fn emit_u32(&mut self, v: u32);
-    fn emit_u16(&mut self, v: u16);
-    fn emit_u8(&mut self, v: u8);
-    fn emit_int(&mut self, v: int);
-    fn emit_i64(&mut self, v: i64);
-    fn emit_i32(&mut self, v: i32);
-    fn emit_i16(&mut self, v: i16);
-    fn emit_i8(&mut self, v: i8);
-    fn emit_bool(&mut self, v: bool);
-    fn emit_float(&mut self, v: float);
-    fn emit_f64(&mut self, v: f64);
-    fn emit_f32(&mut self, v: f32);
-    fn emit_char(&mut self, v: char);
-    fn emit_str(&mut self, v: &str);
-
-    // Compound types:
-    fn emit_enum(&mut self, name: &str, f: &fn(&mut Self));
-
-    fn emit_enum_variant(&mut self,
-                         v_name: &str,
-                         v_id: uint,
-                         len: uint,
-                         f: &fn(&mut Self));
-    fn emit_enum_variant_arg(&mut self, a_idx: uint, f: &fn(&mut Self));
-
-    fn emit_enum_struct_variant(&mut self,
-                                v_name: &str,
-                                v_id: uint,
-                                len: uint,
-                                f: &fn(&mut Self));
-    fn emit_enum_struct_variant_field(&mut self,
-                                      f_name: &str,
-                                      f_idx: uint,
-                                      f: &fn(&mut Self));
-
-    fn emit_struct(&mut self, name: &str, len: uint, f: &fn(&mut Self));
-    fn emit_struct_field(&mut self,
-                         f_name: &str,
-                         f_idx: uint,
-                         f: &fn(&mut Self));
-
-    fn emit_tuple(&mut self, len: uint, f: &fn(&mut Self));
-    fn emit_tuple_arg(&mut self, idx: uint, f: &fn(&mut Self));
-
-    fn emit_tuple_struct(&mut self, name: &str, len: uint, f: &fn(&mut Self));
-    fn emit_tuple_struct_arg(&mut self, f_idx: uint, f: &fn(&mut Self));
-
-    // Specialized types:
-    fn emit_option(&mut self, f: &fn(&mut Self));
-    fn emit_option_none(&mut self);
-    fn emit_option_some(&mut self, f: &fn(&mut Self));
-
-    fn emit_seq(&mut self, len: uint, f: &fn(this: &mut Self));
-    fn emit_seq_elt(&mut self, idx: uint, f: &fn(this: &mut Self));
-
-    fn emit_map(&mut self, len: uint, f: &fn(&mut Self));
-    fn emit_map_elt_key(&mut self, idx: uint, f: &fn(&mut Self));
-    fn emit_map_elt_val(&mut self, idx: uint, f: &fn(&mut Self));
-}
-
-pub trait Decoder {
-    // Primitive types:
-    fn read_nil(&mut self) -> ();
-    fn read_uint(&mut self) -> uint;
-    fn read_u64(&mut self) -> u64;
-    fn read_u32(&mut self) -> u32;
-    fn read_u16(&mut self) -> u16;
-    fn read_u8(&mut self) -> u8;
-    fn read_int(&mut self) -> int;
-    fn read_i64(&mut self) -> i64;
-    fn read_i32(&mut self) -> i32;
-    fn read_i16(&mut self) -> i16;
-    fn read_i8(&mut self) -> i8;
-    fn read_bool(&mut self) -> bool;
-    fn read_f64(&mut self) -> f64;
-    fn read_f32(&mut self) -> f32;
-    fn read_float(&mut self) -> float;
-    fn read_char(&mut self) -> char;
-    fn read_str(&mut self) -> ~str;
-
-    // Compound types:
-    fn read_enum<T>(&mut self, name: &str, f: &fn(&mut Self) -> T) -> T;
-
-    fn read_enum_variant<T>(&mut self,
-                            names: &[&str],
-                            f: &fn(&mut Self, uint) -> T)
-                            -> T;
-    fn read_enum_variant_arg<T>(&mut self,
-                                a_idx: uint,
-                                f: &fn(&mut Self) -> T)
-                                -> T;
-
-    fn read_enum_struct_variant<T>(&mut self,
-                                   names: &[&str],
-                                   f: &fn(&mut Self, uint) -> T)
-                                   -> T;
-    fn read_enum_struct_variant_field<T>(&mut self,
-                                         &f_name: &str,
-                                         f_idx: uint,
-                                         f: &fn(&mut Self) -> T)
-                                         -> T;
-
-    fn read_struct<T>(&mut self,
-                      s_name: &str,
-                      len: uint,
-                      f: &fn(&mut Self) -> T)
-                      -> T;
-    fn read_struct_field<T>(&mut self,
-                            f_name: &str,
-                            f_idx: uint,
-                            f: &fn(&mut Self) -> T)
-                            -> T;
-
-    fn read_tuple<T>(&mut self, f: &fn(&mut Self, uint) -> T) -> T;
-    fn read_tuple_arg<T>(&mut self, a_idx: uint, f: &fn(&mut Self) -> T) -> T;
-
-    fn read_tuple_struct<T>(&mut self,
-                            s_name: &str,
-                            f: &fn(&mut Self, uint) -> T)
-                            -> T;
-    fn read_tuple_struct_arg<T>(&mut self,
-                                a_idx: uint,
-                                f: &fn(&mut Self) -> T)
-                                -> T;
-
-    // Specialized types:
-    fn read_option<T>(&mut self, f: &fn(&mut Self, bool) -> T) -> T;
-
-    fn read_seq<T>(&mut self, f: &fn(&mut Self, uint) -> T) -> T;
-    fn read_seq_elt<T>(&mut self, idx: uint, f: &fn(&mut Self) -> T) -> T;
-
-    fn read_map<T>(&mut self, f: &fn(&mut Self, uint) -> T) -> T;
-    fn read_map_elt_key<T>(&mut self, idx: uint, f: &fn(&mut Self) -> T) -> T;
-    fn read_map_elt_val<T>(&mut self, idx: uint, f: &fn(&mut Self) -> T) -> T;
-}
-
-pub trait Encodable<S:Encoder> {
-    fn encode(&self, s: &mut S);
-}
-
-pub trait Decodable<D:Decoder> {
-    fn decode(d: &mut D) -> Self;
-}
-
-impl<S:Encoder> Encodable<S> for uint {
-    fn encode(&self, s: &mut S) {
-        s.emit_uint(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for uint {
-    fn decode(d: &mut D) -> uint {
-        d.read_uint()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for u8 {
-    fn encode(&self, s: &mut S) {
-        s.emit_u8(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for u8 {
-    fn decode(d: &mut D) -> u8 {
-        d.read_u8()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for u16 {
-    fn encode(&self, s: &mut S) {
-        s.emit_u16(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for u16 {
-    fn decode(d: &mut D) -> u16 {
-        d.read_u16()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for u32 {
-    fn encode(&self, s: &mut S) {
-        s.emit_u32(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for u32 {
-    fn decode(d: &mut D) -> u32 {
-        d.read_u32()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for u64 {
-    fn encode(&self, s: &mut S) {
-        s.emit_u64(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for u64 {
-    fn decode(d: &mut D) -> u64 {
-        d.read_u64()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for int {
-    fn encode(&self, s: &mut S) {
-        s.emit_int(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for int {
-    fn decode(d: &mut D) -> int {
-        d.read_int()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for i8 {
-    fn encode(&self, s: &mut S) {
-        s.emit_i8(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for i8 {
-    fn decode(d: &mut D) -> i8 {
-        d.read_i8()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for i16 {
-    fn encode(&self, s: &mut S) {
-        s.emit_i16(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for i16 {
-    fn decode(d: &mut D) -> i16 {
-        d.read_i16()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for i32 {
-    fn encode(&self, s: &mut S) {
-        s.emit_i32(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for i32 {
-    fn decode(d: &mut D) -> i32 {
-        d.read_i32()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for i64 {
-    fn encode(&self, s: &mut S) {
-        s.emit_i64(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for i64 {
-    fn decode(d: &mut D) -> i64 {
-        d.read_i64()
-    }
-}
-
-impl<'self, S:Encoder> Encodable<S> for &'self str {
-    fn encode(&self, s: &mut S) {
-        s.emit_str(*self)
-    }
-}
-
-impl<S:Encoder> Encodable<S> for ~str {
-    fn encode(&self, s: &mut S) {
-        s.emit_str(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for ~str {
-    fn decode(d: &mut D) -> ~str {
-        d.read_str()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for @str {
-    fn encode(&self, s: &mut S) {
-        s.emit_str(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for @str {
-    fn decode(d: &mut D) -> @str {
-        d.read_str().to_managed()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for float {
-    fn encode(&self, s: &mut S) {
-        s.emit_float(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for float {
-    fn decode(d: &mut D) -> float {
-        d.read_float()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for f32 {
-    fn encode(&self, s: &mut S) {
-        s.emit_f32(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for f32 {
-    fn decode(d: &mut D) -> f32 {
-        d.read_f32()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for f64 {
-    fn encode(&self, s: &mut S) {
-        s.emit_f64(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for f64 {
-    fn decode(d: &mut D) -> f64 {
-        d.read_f64()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for bool {
-    fn encode(&self, s: &mut S) {
-        s.emit_bool(*self)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for bool {
-    fn decode(d: &mut D) -> bool {
-        d.read_bool()
-    }
-}
-
-impl<S:Encoder> Encodable<S> for () {
-    fn encode(&self, s: &mut S) {
-        s.emit_nil()
-    }
-}
-
-impl<D:Decoder> Decodable<D> for () {
-    fn decode(d: &mut D) -> () {
-        d.read_nil()
-    }
-}
-
-impl<'self, S:Encoder,T:Encodable<S>> Encodable<S> for &'self T {
-    fn encode(&self, s: &mut S) {
-        (**self).encode(s)
-    }
-}
-
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for ~T {
-    fn encode(&self, s: &mut S) {
-        (**self).encode(s)
-    }
-}
-
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for ~T {
-    fn decode(d: &mut D) -> ~T {
-        ~Decodable::decode(d)
-    }
-}
-
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for @T {
-    fn encode(&self, s: &mut S) {
-        (**self).encode(s)
-    }
-}
-
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for @T {
-    fn decode(d: &mut D) -> @T {
-        @Decodable::decode(d)
-    }
-}
-
-impl<'self, S:Encoder,T:Encodable<S>> Encodable<S> for &'self [T] {
-    fn encode(&self, s: &mut S) {
-        do s.emit_seq(self.len()) |s| {
-            for self.eachi |i, e| {
-                s.emit_seq_elt(i, |s| e.encode(s))
-            }
-        }
-    }
-}
-
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for ~[T] {
-    fn encode(&self, s: &mut S) {
-        do s.emit_seq(self.len()) |s| {
-            for self.eachi |i, e| {
-                s.emit_seq_elt(i, |s| e.encode(s))
-            }
-        }
-    }
-}
-
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for ~[T] {
-    fn decode(d: &mut D) -> ~[T] {
-        do d.read_seq |d, len| {
-            do vec::from_fn(len) |i| {
-                d.read_seq_elt(i, |d| Decodable::decode(d))
-            }
-        }
-    }
-}
-
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for @[T] {
-    fn encode(&self, s: &mut S) {
-        do s.emit_seq(self.len()) |s| {
-            for self.eachi |i, e| {
-                s.emit_seq_elt(i, |s| e.encode(s))
-            }
-        }
-    }
-}
-
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for @[T] {
-    fn decode(d: &mut D) -> @[T] {
-        do d.read_seq |d, len| {
-            do at_vec::from_fn(len) |i| {
-                d.read_seq_elt(i, |d| Decodable::decode(d))
-            }
-        }
-    }
-}
-
-impl<S:Encoder,T:Encodable<S>> Encodable<S> for Option<T> {
-    fn encode(&self, s: &mut S) {
-        do s.emit_option |s| {
-            match *self {
-                None => s.emit_option_none(),
-                Some(ref v) => s.emit_option_some(|s| v.encode(s)),
-            }
-        }
-    }
-}
-
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for Option<T> {
-    fn decode(d: &mut D) -> Option<T> {
-        do d.read_option |d, b| {
-            if b {
-                Some(Decodable::decode(d))
-            } else {
-                None
-            }
-        }
-    }
-}
-
-impl<S:Encoder,T0:Encodable<S>,T1:Encodable<S>> Encodable<S> for (T0, T1) {
-    fn encode(&self, s: &mut S) {
-        match *self {
-            (ref t0, ref t1) => {
-                do s.emit_seq(2) |s| {
-                    s.emit_seq_elt(0, |s| t0.encode(s));
-                    s.emit_seq_elt(1, |s| t1.encode(s));
-                }
-            }
-        }
-    }
-}
-
-impl<D:Decoder,T0:Decodable<D>,T1:Decodable<D>> Decodable<D> for (T0, T1) {
-    fn decode(d: &mut D) -> (T0, T1) {
-        do d.read_seq |d, len| {
-            assert_eq!(len, 2);
-            (
-                d.read_seq_elt(0, |d| Decodable::decode(d)),
-                d.read_seq_elt(1, |d| Decodable::decode(d))
-            )
-        }
-    }
-}
-
-impl<
-    S: Encoder,
-    T0: Encodable<S>,
-    T1: Encodable<S>,
-    T2: Encodable<S>
-> Encodable<S> for (T0, T1, T2) {
-    fn encode(&self, s: &mut S) {
-        match *self {
-            (ref t0, ref t1, ref t2) => {
-                do s.emit_seq(3) |s| {
-                    s.emit_seq_elt(0, |s| t0.encode(s));
-                    s.emit_seq_elt(1, |s| t1.encode(s));
-                    s.emit_seq_elt(2, |s| t2.encode(s));
-                }
-            }
-        }
-    }
-}
-
-impl<
-    D: Decoder,
-    T0: Decodable<D>,
-    T1: Decodable<D>,
-    T2: Decodable<D>
-> Decodable<D> for (T0, T1, T2) {
-    fn decode(d: &mut D) -> (T0, T1, T2) {
-        do d.read_seq |d, len| {
-            assert_eq!(len, 3);
-            (
-                d.read_seq_elt(0, |d| Decodable::decode(d)),
-                d.read_seq_elt(1, |d| Decodable::decode(d)),
-                d.read_seq_elt(2, |d| Decodable::decode(d))
-            )
-        }
-    }
-}
-
-impl<
-    S: Encoder,
-    T0: Encodable<S>,
-    T1: Encodable<S>,
-    T2: Encodable<S>,
-    T3: Encodable<S>
-> Encodable<S> for (T0, T1, T2, T3) {
-    fn encode(&self, s: &mut S) {
-        match *self {
-            (ref t0, ref t1, ref t2, ref t3) => {
-                do s.emit_seq(4) |s| {
-                    s.emit_seq_elt(0, |s| t0.encode(s));
-                    s.emit_seq_elt(1, |s| t1.encode(s));
-                    s.emit_seq_elt(2, |s| t2.encode(s));
-                    s.emit_seq_elt(3, |s| t3.encode(s));
-                }
-            }
-        }
-    }
-}
-
-impl<
-    D: Decoder,
-    T0: Decodable<D>,
-    T1: Decodable<D>,
-    T2: Decodable<D>,
-    T3: Decodable<D>
-> Decodable<D> for (T0, T1, T2, T3) {
-    fn decode(d: &mut D) -> (T0, T1, T2, T3) {
-        do d.read_seq |d, len| {
-            assert_eq!(len, 4);
-            (
-                d.read_seq_elt(0, |d| Decodable::decode(d)),
-                d.read_seq_elt(1, |d| Decodable::decode(d)),
-                d.read_seq_elt(2, |d| Decodable::decode(d)),
-                d.read_seq_elt(3, |d| Decodable::decode(d))
-            )
-        }
-    }
-}
-
-impl<
-    S: Encoder,
-    T0: Encodable<S>,
-    T1: Encodable<S>,
-    T2: Encodable<S>,
-    T3: Encodable<S>,
-    T4: Encodable<S>
-> Encodable<S> for (T0, T1, T2, T3, T4) {
-    fn encode(&self, s: &mut S) {
-        match *self {
-            (ref t0, ref t1, ref t2, ref t3, ref t4) => {
-                do s.emit_seq(5) |s| {
-                    s.emit_seq_elt(0, |s| t0.encode(s));
-                    s.emit_seq_elt(1, |s| t1.encode(s));
-                    s.emit_seq_elt(2, |s| t2.encode(s));
-                    s.emit_seq_elt(3, |s| t3.encode(s));
-                    s.emit_seq_elt(4, |s| t4.encode(s));
-                }
-            }
-        }
-    }
-}
-
-impl<
-    D: Decoder,
-    T0: Decodable<D>,
-    T1: Decodable<D>,
-    T2: Decodable<D>,
-    T3: Decodable<D>,
-    T4: Decodable<D>
-> Decodable<D> for (T0, T1, T2, T3, T4) {
-    fn decode(d: &mut D) -> (T0, T1, T2, T3, T4) {
-        do d.read_seq |d, len| {
-            assert_eq!(len, 5);
-            (
-                d.read_seq_elt(0, |d| Decodable::decode(d)),
-                d.read_seq_elt(1, |d| Decodable::decode(d)),
-                d.read_seq_elt(2, |d| Decodable::decode(d)),
-                d.read_seq_elt(3, |d| Decodable::decode(d)),
-                d.read_seq_elt(4, |d| Decodable::decode(d))
-            )
-        }
-    }
-}
-
-impl<
-    S: Encoder,
-    T: Encodable<S> + Copy
-> Encodable<S> for @mut DList<T> {
-    fn encode(&self, s: &mut S) {
-        do s.emit_seq(self.size) |s| {
-            let mut i = 0;
-            for self.each |e| {
-                s.emit_seq_elt(i, |s| e.encode(s));
-                i += 1;
-            }
-        }
-    }
-}
-
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for @mut DList<T> {
-    fn decode(d: &mut D) -> @mut DList<T> {
-        let list = DList();
-        do d.read_seq |d, len| {
-            for uint::range(0, len) |i| {
-                list.push(d.read_seq_elt(i, |d| Decodable::decode(d)));
-            }
-        }
-        list
-    }
-}
-
-impl<
-    S: Encoder,
-    T: Encodable<S>
-> Encodable<S> for Deque<T> {
-    fn encode(&self, s: &mut S) {
-        do s.emit_seq(self.len()) |s| {
-            for self.eachi |i, e| {
-                s.emit_seq_elt(i, |s| e.encode(s));
-            }
-        }
-    }
-}
-
-impl<D:Decoder,T:Decodable<D>> Decodable<D> for Deque<T> {
-    fn decode(d: &mut D) -> Deque<T> {
-        let mut deque = Deque::new();
-        do d.read_seq |d, len| {
-            for uint::range(0, len) |i| {
-                deque.add_back(d.read_seq_elt(i, |d| Decodable::decode(d)));
-            }
-        }
-        deque
-    }
-}
-
-impl<
-    E: Encoder,
-    K: Encodable<E> + Hash + IterBytes + Eq,
-    V: Encodable<E>
-> Encodable<E> for HashMap<K, V> {
-    fn encode(&self, e: &mut E) {
-        do e.emit_map(self.len()) |e| {
-            let mut i = 0;
-            for self.each |key, val| {
-                e.emit_map_elt_key(i, |e| key.encode(e));
-                e.emit_map_elt_val(i, |e| val.encode(e));
-                i += 1;
-            }
-        }
-    }
-}
-
-impl<
-    D: Decoder,
-    K: Decodable<D> + Hash + IterBytes + Eq,
-    V: Decodable<D>
-> Decodable<D> for HashMap<K, V> {
-    fn decode(d: &mut D) -> HashMap<K, V> {
-        do d.read_map |d, len| {
-            let mut map = HashMap::with_capacity(len);
-            for uint::range(0, len) |i| {
-                let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
-                let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
-                map.insert(key, val);
-            }
-            map
-        }
-    }
-}
-
-impl<
-    S: Encoder,
-    T: Encodable<S> + Hash + IterBytes + Eq
-> Encodable<S> for HashSet<T> {
-    fn encode(&self, s: &mut S) {
-        do s.emit_seq(self.len()) |s| {
-            let mut i = 0;
-            for self.each |e| {
-                s.emit_seq_elt(i, |s| e.encode(s));
-                i += 1;
-            }
-        }
-    }
-}
-
-impl<
-    D: Decoder,
-    T: Decodable<D> + Hash + IterBytes + Eq
-> Decodable<D> for HashSet<T> {
-    fn decode(d: &mut D) -> HashSet<T> {
-        do d.read_seq |d, len| {
-            let mut set = HashSet::with_capacity(len);
-            for uint::range(0, len) |i| {
-                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
-            }
-            set
-        }
-    }
-}
-
-impl<
-    E: Encoder,
-    V: Encodable<E>
-> Encodable<E> for TrieMap<V> {
-    fn encode(&self, e: &mut E) {
-        do e.emit_map(self.len()) |e| {
-            let mut i = 0;
-            for self.each |key, val| {
-                e.emit_map_elt_key(i, |e| key.encode(e));
-                e.emit_map_elt_val(i, |e| val.encode(e));
-                i += 1;
-            }
-        }
-    }
-}
-
-impl<
-    D: Decoder,
-    V: Decodable<D>
-> Decodable<D> for TrieMap<V> {
-    fn decode(d: &mut D) -> TrieMap<V> {
-        do d.read_map |d, len| {
-            let mut map = TrieMap::new();
-            for uint::range(0, len) |i| {
-                let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
-                let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
-                map.insert(key, val);
-            }
-            map
-        }
-    }
-}
-
-impl<S: Encoder> Encodable<S> for TrieSet {
-    fn encode(&self, s: &mut S) {
-        do s.emit_seq(self.len()) |s| {
-            let mut i = 0;
-            for self.each |e| {
-                s.emit_seq_elt(i, |s| e.encode(s));
-                i += 1;
-            }
-        }
-    }
-}
-
-impl<D: Decoder> Decodable<D> for TrieSet {
-    fn decode(d: &mut D) -> TrieSet {
-        do d.read_seq |d, len| {
-            let mut set = TrieSet::new();
-            for uint::range(0, len) |i| {
-                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
-            }
-            set
-        }
-    }
-}
-
-impl<
-    E: Encoder,
-    K: Encodable<E> + Eq + TotalOrd,
-    V: Encodable<E> + Eq
-> Encodable<E> for TreeMap<K, V> {
-    fn encode(&self, e: &mut E) {
-        do e.emit_map(self.len()) |e| {
-            let mut i = 0;
-            for self.each |key, val| {
-                e.emit_map_elt_key(i, |e| key.encode(e));
-                e.emit_map_elt_val(i, |e| val.encode(e));
-                i += 1;
-            }
-        }
-    }
-}
-
-impl<
-    D: Decoder,
-    K: Decodable<D> + Eq + TotalOrd,
-    V: Decodable<D> + Eq
-> Decodable<D> for TreeMap<K, V> {
-    fn decode(d: &mut D) -> TreeMap<K, V> {
-        do d.read_map |d, len| {
-            let mut map = TreeMap::new();
-            for uint::range(0, len) |i| {
-                let key = d.read_map_elt_key(i, |d| Decodable::decode(d));
-                let val = d.read_map_elt_val(i, |d| Decodable::decode(d));
-                map.insert(key, val);
-            }
-            map
-        }
-    }
-}
-
-impl<
-    S: Encoder,
-    T: Encodable<S> + Eq + TotalOrd
-> Encodable<S> for TreeSet<T> {
-    fn encode(&self, s: &mut S) {
-        do s.emit_seq(self.len()) |s| {
-            let mut i = 0;
-            for self.each |e| {
-                s.emit_seq_elt(i, |s| e.encode(s));
-                i += 1;
-            }
-        }
-    }
-}
-
-impl<
-    D: Decoder,
-    T: Decodable<D> + Eq + TotalOrd
-> Decodable<D> for TreeSet<T> {
-    fn decode(d: &mut D) -> TreeSet<T> {
-        do d.read_seq |d, len| {
-            let mut set = TreeSet::new();
-            for uint::range(0, len) |i| {
-                set.insert(d.read_seq_elt(i, |d| Decodable::decode(d)));
-            }
-            set
-        }
-    }
-}
-
-// ___________________________________________________________________________
-// Helper routines
-//
-// In some cases, these should eventually be coded as traits.
-
-pub trait EncoderHelpers {
-    fn emit_from_vec<T>(&mut self, v: &[T], f: &fn(&mut Self, v: &T));
-}
-
-impl<S:Encoder> EncoderHelpers for S {
-    fn emit_from_vec<T>(&mut self, v: &[T], f: &fn(&mut S, &T)) {
-        do self.emit_seq(v.len()) |this| {
-            for v.eachi |i, e| {
-                do this.emit_seq_elt(i) |this| {
-                    f(this, e)
-                }
-            }
-        }
-    }
-}
-
-pub trait DecoderHelpers {
-    fn read_to_vec<T>(&mut self, f: &fn(&mut Self) -> T) -> ~[T];
-}
-
-impl<D:Decoder> DecoderHelpers for D {
-    fn read_to_vec<T>(&mut self, f: &fn(&mut D) -> T) -> ~[T] {
-        do self.read_seq |this, len| {
-            do vec::from_fn(len) |i| {
-                this.read_seq_elt(i, |this| f(this))
-            }
-        }
-    }
-}
diff --git a/src/libstd/sha1.rs b/src/libstd/sha1.rs
deleted file mode 100644
index d7051d73469..00000000000
--- a/src/libstd/sha1.rs
+++ /dev/null
@@ -1,414 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
- * An implementation of the SHA-1 cryptographic hash.
- *
- * First create a `sha1` object using the `sha1` constructor, then
- * feed it input using the `input` or `input_str` methods, which may be
- * called any number of times.
- *
- * After the entire input has been fed to the hash read the result using
- * the `result` or `result_str` methods.
- *
- * The `sha1` object may be reused to create multiple hashes by calling
- * the `reset` method.
- */
-
-use core::str;
-use core::uint;
-use core::vec;
-
-/*
- * A SHA-1 implementation derived from Paul E. Jones's reference
- * implementation, which is written for clarity, not speed. At some
- * point this will want to be rewritten.
- */
-
-/// The SHA-1 interface
-trait Sha1 {
-    /// Provide message input as bytes
-    fn input(&mut self, &const [u8]);
-    /// Provide message input as string
-    fn input_str(&mut self, &str);
-    /**
-     * Read the digest as a vector of 20 bytes. After calling this no further
-     * input may be provided until reset is called.
-     */
-    fn result(&mut self) -> ~[u8];
-    /**
-     * Read the digest as a hex string. After calling this no further
-     * input may be provided until reset is called.
-     */
-    fn result_str(&mut self) -> ~str;
-    /// Reset the SHA-1 state for reuse
-    fn reset(&mut self);
-}
-
-// Some unexported constants
-static digest_buf_len: uint = 5u;
-static msg_block_len: uint = 64u;
-static work_buf_len: uint = 80u;
-static k0: u32 = 0x5A827999u32;
-static k1: u32 = 0x6ED9EBA1u32;
-static k2: u32 = 0x8F1BBCDCu32;
-static k3: u32 = 0xCA62C1D6u32;
-
-
-/// Construct a `sha` object
-pub fn sha1() -> @Sha1 {
-    struct Sha1State
-        { h: ~[u32],
-          len_low: u32,
-          len_high: u32,
-          msg_block: ~[u8],
-          msg_block_idx: uint,
-          computed: bool,
-          work_buf: @mut ~[u32]};
-
-    fn add_input(st: &mut Sha1State, msg: &const [u8]) {
-        assert!((!st.computed));
-        for vec::each_const(msg) |element| {
-            st.msg_block[st.msg_block_idx] = *element;
-            st.msg_block_idx += 1u;
-            st.len_low += 8u32;
-            if st.len_low == 0u32 {
-                st.len_high += 1u32;
-                if st.len_high == 0u32 {
-                    // FIXME: Need better failure mode (#2346)
-                    fail!();
-                }
-            }
-            if st.msg_block_idx == msg_block_len { process_msg_block(st); }
-        }
-    }
-    fn process_msg_block(st: &mut Sha1State) {
-        assert_eq!(st.h.len(), digest_buf_len);
-        assert_eq!(vec::uniq_len(st.work_buf), work_buf_len);
-        let mut t: int; // Loop counter
-        let w = st.work_buf;
-
-        // Initialize the first 16 words of the vector w
-        t = 0;
-        while t < 16 {
-            let mut tmp;
-            tmp = (st.msg_block[t * 4] as u32) << 24u32;
-            tmp = tmp | (st.msg_block[t * 4 + 1] as u32) << 16u32;
-            tmp = tmp | (st.msg_block[t * 4 + 2] as u32) << 8u32;
-            tmp = tmp | (st.msg_block[t * 4 + 3] as u32);
-            w[t] = tmp;
-            t += 1;
-        }
-
-        // Initialize the rest of vector w
-        while t < 80 {
-            let val = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16];
-            w[t] = circular_shift(1u32, val);
-            t += 1;
-        }
-        let mut a = st.h[0];
-        let mut b = st.h[1];
-        let mut c = st.h[2];
-        let mut d = st.h[3];
-        let mut e = st.h[4];
-        let mut temp: u32;
-        t = 0;
-        while t < 20 {
-            temp = circular_shift(5u32, a) + (b & c | !b & d) + e + w[t] + k0;
-            e = d;
-            d = c;
-            c = circular_shift(30u32, b);
-            b = a;
-            a = temp;
-            t += 1;
-        }
-        while t < 40 {
-            temp = circular_shift(5u32, a) + (b ^ c ^ d) + e + w[t] + k1;
-            e = d;
-            d = c;
-            c = circular_shift(30u32, b);
-            b = a;
-            a = temp;
-            t += 1;
-        }
-        while t < 60 {
-            temp =
-                circular_shift(5u32, a) + (b & c | b & d | c & d) + e + w[t] +
-                    k2;
-            e = d;
-            d = c;
-            c = circular_shift(30u32, b);
-            b = a;
-            a = temp;
-            t += 1;
-        }
-        while t < 80 {
-            temp = circular_shift(5u32, a) + (b ^ c ^ d) + e + w[t] + k3;
-            e = d;
-            d = c;
-            c = circular_shift(30u32, b);
-            b = a;
-            a = temp;
-            t += 1;
-        }
-        st.h[0] = st.h[0] + a;
-        st.h[1] = st.h[1] + b;
-        st.h[2] = st.h[2] + c;
-        st.h[3] = st.h[3] + d;
-        st.h[4] = st.h[4] + e;
-        st.msg_block_idx = 0u;
-    }
-    fn circular_shift(bits: u32, word: u32) -> u32 {
-        return word << bits | word >> 32u32 - bits;
-    }
-    fn mk_result(st: &mut Sha1State) -> ~[u8] {
-        if !(*st).computed { pad_msg(st); (*st).computed = true; }
-        let mut rs: ~[u8] = ~[];
-        for vec::each_mut((*st).h) |ptr_hpart| {
-            let hpart = *ptr_hpart;
-            let a = (hpart >> 24u32 & 0xFFu32) as u8;
-            let b = (hpart >> 16u32 & 0xFFu32) as u8;
-            let c = (hpart >> 8u32 & 0xFFu32) as u8;
-            let d = (hpart & 0xFFu32) as u8;
-            rs = vec::append(copy rs, [a, b, c, d]);
-        }
-        return rs;
-    }
-
-    /*
-     * According to the standard, the message must be padded to an even
-     * 512 bits.  The first padding bit must be a '1'.  The last 64 bits
-     * represent the length of the original message.  All bits in between
-     * should be 0.  This function will pad the message according to those
-     * rules by filling the msg_block vector accordingly.  It will also
-     * call process_msg_block() appropriately.  When it returns, it
-     * can be assumed that the message digest has been computed.
-     */
-    fn pad_msg(st: &mut Sha1State) {
-        assert_eq!(vec::len((*st).msg_block), msg_block_len);
-
-        /*
-         * Check to see if the current message block is too small to hold
-         * the initial padding bits and length.  If so, we will pad the
-         * block, process it, and then continue padding into a second block.
-         */
-        if (*st).msg_block_idx > 55u {
-            (*st).msg_block[(*st).msg_block_idx] = 0x80u8;
-            (*st).msg_block_idx += 1u;
-            while (*st).msg_block_idx < msg_block_len {
-                (*st).msg_block[(*st).msg_block_idx] = 0u8;
-                (*st).msg_block_idx += 1u;
-            }
-            process_msg_block(st);
-        } else {
-            (*st).msg_block[(*st).msg_block_idx] = 0x80u8;
-            (*st).msg_block_idx += 1u;
-        }
-        while (*st).msg_block_idx < 56u {
-            (*st).msg_block[(*st).msg_block_idx] = 0u8;
-            (*st).msg_block_idx += 1u;
-        }
-
-        // Store the message length as the last 8 octets
-        (*st).msg_block[56] = ((*st).len_high >> 24u32 & 0xFFu32) as u8;
-        (*st).msg_block[57] = ((*st).len_high >> 16u32 & 0xFFu32) as u8;
-        (*st).msg_block[58] = ((*st).len_high >> 8u32 & 0xFFu32) as u8;
-        (*st).msg_block[59] = ((*st).len_high & 0xFFu32) as u8;
-        (*st).msg_block[60] = ((*st).len_low >> 24u32 & 0xFFu32) as u8;
-        (*st).msg_block[61] = ((*st).len_low >> 16u32 & 0xFFu32) as u8;
-        (*st).msg_block[62] = ((*st).len_low >> 8u32 & 0xFFu32) as u8;
-        (*st).msg_block[63] = ((*st).len_low & 0xFFu32) as u8;
-        process_msg_block(st);
-    }
-
-    impl Sha1 for Sha1State {
-        fn reset(&mut self) {
-            assert_eq!(self.h.len(), digest_buf_len);
-            self.len_low = 0u32;
-            self.len_high = 0u32;
-            self.msg_block_idx = 0u;
-            self.h[0] = 0x67452301u32;
-            self.h[1] = 0xEFCDAB89u32;
-            self.h[2] = 0x98BADCFEu32;
-            self.h[3] = 0x10325476u32;
-            self.h[4] = 0xC3D2E1F0u32;
-            self.computed = false;
-        }
-        fn input(&mut self, msg: &const [u8]) { add_input(self, msg); }
-        fn input_str(&mut self, msg: &str) {
-            let bs = str::to_bytes(msg);
-            add_input(self, bs);
-        }
-        fn result(&mut self) -> ~[u8] { return mk_result(self); }
-        fn result_str(&mut self) -> ~str {
-            let rr = mk_result(self);
-            let mut s = ~"";
-            for rr.each |b| {
-                let hex = uint::to_str_radix(*b as uint, 16u);
-                if hex.len() == 1 {
-                    s += "0";
-                }
-                s += hex;
-            }
-            return s;
-        }
-    }
-    let st = Sha1State {
-         h: vec::from_elem(digest_buf_len, 0u32),
-         len_low: 0u32,
-         len_high: 0u32,
-         msg_block: vec::from_elem(msg_block_len, 0u8),
-         msg_block_idx: 0u,
-         computed: false,
-         work_buf: @mut vec::from_elem(work_buf_len, 0u32)
-    };
-    let mut sh = @st as @Sha1;
-    sh.reset();
-    return sh;
-}
-
-#[cfg(test)]
-mod tests {
-    use sha1;
-
-    use core::str;
-    use core::vec;
-
-    #[test]
-    fn test() {
-        struct Test {
-            input: ~str,
-            output: ~[u8],
-            output_str: ~str,
-        }
-
-        fn a_million_letter_a() -> ~str {
-            let mut i = 0;
-            let mut rs = ~"";
-            while i < 100000 {
-                str::push_str(&mut rs, ~"aaaaaaaaaa");
-                i += 1;
-            }
-            return rs;
-        }
-        // Test messages from FIPS 180-1
-
-        let fips_180_1_tests = ~[
-            Test {
-                input: ~"abc",
-                output: ~[
-                    0xA9u8, 0x99u8, 0x3Eu8, 0x36u8,
-                    0x47u8, 0x06u8, 0x81u8, 0x6Au8,
-                    0xBAu8, 0x3Eu8, 0x25u8, 0x71u8,
-                    0x78u8, 0x50u8, 0xC2u8, 0x6Cu8,
-                    0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8,
-                ],
-                output_str: ~"a9993e364706816aba3e25717850c26c9cd0d89d"
-            },
-            Test {
-                input:
-                     ~"abcdbcdecdefdefgefghfghighij" +
-                     ~"hijkijkljklmklmnlmnomnopnopq",
-                output: ~[
-                    0x84u8, 0x98u8, 0x3Eu8, 0x44u8,
-                    0x1Cu8, 0x3Bu8, 0xD2u8, 0x6Eu8,
-                    0xBAu8, 0xAEu8, 0x4Au8, 0xA1u8,
-                    0xF9u8, 0x51u8, 0x29u8, 0xE5u8,
-                    0xE5u8, 0x46u8, 0x70u8, 0xF1u8,
-                ],
-                output_str: ~"84983e441c3bd26ebaae4aa1f95129e5e54670f1"
-            },
-            Test {
-                input: a_million_letter_a(),
-                output: ~[
-                    0x34u8, 0xAAu8, 0x97u8, 0x3Cu8,
-                    0xD4u8, 0xC4u8, 0xDAu8, 0xA4u8,
-                    0xF6u8, 0x1Eu8, 0xEBu8, 0x2Bu8,
-                    0xDBu8, 0xADu8, 0x27u8, 0x31u8,
-                    0x65u8, 0x34u8, 0x01u8, 0x6Fu8,
-                ],
-                output_str: ~"34aa973cd4c4daa4f61eeb2bdbad27316534016f"
-            },
-        ];
-        // Examples from wikipedia
-
-        let wikipedia_tests = ~[
-            Test {
-                input: ~"The quick brown fox jumps over the lazy dog",
-                output: ~[
-                    0x2fu8, 0xd4u8, 0xe1u8, 0xc6u8,
-                    0x7au8, 0x2du8, 0x28u8, 0xfcu8,
-                    0xedu8, 0x84u8, 0x9eu8, 0xe1u8,
-                    0xbbu8, 0x76u8, 0xe7u8, 0x39u8,
-                    0x1bu8, 0x93u8, 0xebu8, 0x12u8,
-                ],
-                output_str: ~"2fd4e1c67a2d28fced849ee1bb76e7391b93eb12",
-            },
-            Test {
-                input: ~"The quick brown fox jumps over the lazy cog",
-                output: ~[
-                    0xdeu8, 0x9fu8, 0x2cu8, 0x7fu8,
-                    0xd2u8, 0x5eu8, 0x1bu8, 0x3au8,
-                    0xfau8, 0xd3u8, 0xe8u8, 0x5au8,
-                    0x0bu8, 0xd1u8, 0x7du8, 0x9bu8,
-                    0x10u8, 0x0du8, 0xb4u8, 0xb3u8,
-                ],
-                output_str: ~"de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3",
-            },
-        ];
-        let tests = fips_180_1_tests + wikipedia_tests;
-        fn check_vec_eq(v0: ~[u8], v1: ~[u8]) {
-            assert_eq!(vec::len::<u8>(v0), vec::len::<u8>(v1));
-            let len = vec::len::<u8>(v0);
-            let mut i = 0u;
-            while i < len {
-                let a = v0[i];
-                let b = v1[i];
-                assert_eq!(a, b);
-                i += 1u;
-            }
-        }
-        // Test that it works when accepting the message all at once
-
-        let mut sh = sha1::sha1();
-        for tests.each |t| {
-            sh.input_str(t.input);
-            let out = sh.result();
-            check_vec_eq(copy t.output, out);
-
-            let out_str = sh.result_str();
-            assert_eq!(out_str.len(), 40);
-            assert!(out_str == t.output_str);
-
-            sh.reset();
-        }
-
-
-        // Test that it works when accepting the message in pieces
-        for tests.each |t| {
-            let len = str::len(t.input);
-            let mut left = len;
-            while left > 0u {
-                let take = (left + 1u) / 2u;
-                sh.input_str(str::slice(t.input, len - left,
-                             take + len - left).to_owned());
-                left = left - take;
-            }
-            let out = sh.result();
-            check_vec_eq(copy t.output, out);
-
-            let out_str = sh.result_str();
-            assert_eq!(out_str.len(), 40);
-            assert!(out_str == t.output_str);
-
-            sh.reset();
-        }
-    }
-}
diff --git a/src/libstd/smallintmap.rs b/src/libstd/smallintmap.rs
deleted file mode 100644
index aa8372bab78..00000000000
--- a/src/libstd/smallintmap.rs
+++ /dev/null
@@ -1,516 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
- * A simple map based on a vector for small integer keys. Space requirements
- * are O(highest integer key).
- */
-
-use core::container::{Container, Mutable, Map, Set};
-use core::old_iter::BaseIter;
-use core::old_iter;
-use core::option::{Some, None};
-use core::util::replace;
-
-pub struct SmallIntMap<T> {
-    priv v: ~[Option<T>],
-}
-
-impl<V> Container for SmallIntMap<V> {
-    /// Return the number of elements in the map
-    fn len(&const self) -> uint {
-        let mut sz = 0;
-        for uint::range(0, vec::uniq_len(&const self.v)) |i| {
-            match self.v[i] {
-                Some(_) => sz += 1,
-                None => {}
-            }
-        }
-        sz
-    }
-
-    /// Return true if the map contains no elements
-    fn is_empty(&const self) -> bool { self.len() == 0 }
-}
-
-impl<V> Mutable for SmallIntMap<V> {
-    /// Clear the map, removing all key-value pairs.
-    fn clear(&mut self) { self.v.clear() }
-}
-
-impl<V> Map<uint, V> for SmallIntMap<V> {
-    /// Return true if the map contains a value for the specified key
-    fn contains_key(&self, key: &uint) -> bool {
-        self.find(key).is_some()
-    }
-
-    /// Visit all key-value pairs in order
-    fn each<'a>(&'a self, it: &fn(&uint, &'a V) -> bool) -> bool {
-        for uint::range(0, self.v.len()) |i| {
-            match self.v[i] {
-              Some(ref elt) => if !it(&i, elt) { return false; },
-              None => ()
-            }
-        }
-        return true;
-    }
-
-    /// Visit all keys in order
-    fn each_key(&self, blk: &fn(key: &uint) -> bool) -> bool {
-        self.each(|k, _| blk(k))
-    }
-
-    /// Visit all values in order
-    fn each_value<'a>(&'a self, blk: &fn(value: &'a V) -> bool) -> bool {
-        self.each(|_, v| blk(v))
-    }
-
-    /// Iterate over the map and mutate the contained values
-    fn mutate_values(&mut self, it: &fn(&uint, &mut V) -> bool) -> bool {
-        for uint::range(0, self.v.len()) |i| {
-            match self.v[i] {
-              Some(ref mut elt) => if !it(&i, elt) { return false; },
-              None => ()
-            }
-        }
-        return true;
-    }
-
-    /// Return a reference to the value corresponding to the key
-    fn find<'a>(&'a self, key: &uint) -> Option<&'a V> {
-        if *key < self.v.len() {
-            match self.v[*key] {
-              Some(ref value) => Some(value),
-              None => None
-            }
-        } else {
-            None
-        }
-    }
-
-    /// Return a mutable reference to the value corresponding to the key
-    fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut V> {
-        if *key < self.v.len() {
-            match self.v[*key] {
-              Some(ref mut value) => Some(value),
-              None => None
-            }
-        } else {
-            None
-        }
-    }
-
-    /// Insert a key-value pair into the map. An existing value for a
-    /// key is replaced by the new value. Return true if the key did
-    /// not already exist in the map.
-    fn insert(&mut self, key: uint, value: V) -> bool {
-        let exists = self.contains_key(&key);
-        let len = self.v.len();
-        if len <= key {
-            vec::grow_fn(&mut self.v, key - len + 1, |_| None);
-        }
-        self.v[key] = Some(value);
-        !exists
-    }
-
-    /// Remove a key-value pair from the map. Return true if the key
-    /// was present in the map, otherwise false.
-    fn remove(&mut self, key: &uint) -> bool {
-        self.pop(key).is_some()
-    }
-
-    /// Insert a key-value pair from the map. If the key already had a value
-    /// present in the map, that value is returned. Otherwise None is returned.
-    fn swap(&mut self, key: uint, value: V) -> Option<V> {
-        match self.find_mut(&key) {
-            Some(loc) => { return Some(replace(loc, value)); }
-            None => ()
-        }
-        self.insert(key, value);
-        return None;
-    }
-
-    /// Removes a key from the map, returning the value at the key if the key
-    /// was previously in the map.
-    fn pop(&mut self, key: &uint) -> Option<V> {
-        if *key >= self.v.len() {
-            return None;
-        }
-        replace(&mut self.v[*key], None)
-    }
-}
-
-pub impl<V> SmallIntMap<V> {
-    /// Create an empty SmallIntMap
-    fn new() -> SmallIntMap<V> { SmallIntMap{v: ~[]} }
-
-    /// Visit all key-value pairs in reverse order
-    fn each_reverse<'a>(&'a self, it: &fn(uint, &'a V) -> bool) -> bool {
-        for uint::range_rev(self.v.len(), 0) |i| {
-            match self.v[i - 1] {
-              Some(ref elt) => if !it(i - 1, elt) { return false; },
-              None => ()
-            }
-        }
-        return true;
-    }
-
-    fn get<'a>(&'a self, key: &uint) -> &'a V {
-        self.find(key).expect("key not present")
-    }
-}
-
-pub impl<V:Copy> SmallIntMap<V> {
-    fn update_with_key(&mut self, key: uint, val: V,
-                       ff: &fn(uint, V, V) -> V) -> bool {
-        let new_val = match self.find(&key) {
-            None => val,
-            Some(orig) => ff(key, *orig, val)
-        };
-        self.insert(key, new_val)
-    }
-
-    fn update(&mut self, key: uint, newval: V, ff: &fn(V, V) -> V) -> bool {
-        self.update_with_key(key, newval, |_k, v, v1| ff(v,v1))
-    }
-}
-
-pub struct SmallIntSet {
-    priv map: SmallIntMap<()>
-}
-
-impl Container for SmallIntSet {
-    /// Return the number of elements in the map
-    fn len(&const self) -> uint {
-        self.map.len()
-    }
-
-    /// Return true if the map contains no elements
-    fn is_empty(&const self) -> bool { self.len() == 0 }
-}
-
-impl Mutable for SmallIntSet {
-    /// Clear the map, removing all key-value pairs.
-    fn clear(&mut self) { self.map.clear() }
-}
-
-impl BaseIter<uint> for SmallIntSet {
-    /// Visit all values in order
-    fn each(&self, f: &fn(&uint) -> bool) -> bool { self.map.each_key(f) }
-    fn size_hint(&self) -> Option<uint> { Some(self.len()) }
-}
-
-impl Set<uint> for SmallIntSet {
-    /// Return true if the set contains a value
-    fn contains(&self, value: &uint) -> bool { self.map.contains_key(value) }
-
-    /// Add a value to the set. Return true if the value was not already
-    /// present in the set.
-    fn insert(&mut self, value: uint) -> bool { self.map.insert(value, ()) }
-
-    /// Remove a value from the set. Return true if the value was
-    /// present in the set.
-    fn remove(&mut self, value: &uint) -> bool { self.map.remove(value) }
-
-    /// Return true if the set has no elements in common with `other`.
-    /// This is equivalent to checking for an empty uintersection.
-    fn is_disjoint(&self, other: &SmallIntSet) -> bool {
-        old_iter::all(self, |v| !other.contains(v))
-    }
-
-    /// Return true if the set is a subset of another
-    fn is_subset(&self, other: &SmallIntSet) -> bool {
-        old_iter::all(self, |v| other.contains(v))
-    }
-
-    /// Return true if the set is a superset of another
-    fn is_superset(&self, other: &SmallIntSet) -> bool {
-        other.is_subset(self)
-    }
-
-    /// Visit the values representing the difference
-    fn difference(&self, other: &SmallIntSet, f: &fn(&uint) -> bool) -> bool {
-        self.each(|v| other.contains(v) || f(v))
-    }
-
-    /// Visit the values representing the symmetric difference
-    fn symmetric_difference(&self,
-                            other: &SmallIntSet,
-                            f: &fn(&uint) -> bool) -> bool {
-        self.difference(other, f) && other.difference(self, f)
-    }
-
-    /// Visit the values representing the uintersection
-    fn intersection(&self, other: &SmallIntSet, f: &fn(&uint) -> bool) -> bool {
-        self.each(|v| !other.contains(v) || f(v))
-    }
-
-    /// Visit the values representing the union
-    fn union(&self, other: &SmallIntSet, f: &fn(&uint) -> bool) -> bool {
-        self.each(f) && other.each(|v| self.contains(v) || f(v))
-    }
-}
-
-pub impl SmallIntSet {
-    /// Create an empty SmallIntSet
-    fn new() -> SmallIntSet { SmallIntSet{map: SmallIntMap::new()} }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::SmallIntMap;
-
-    #[test]
-    fn test_find_mut() {
-        let mut m = SmallIntMap::new();
-        assert!(m.insert(1, 12));
-        assert!(m.insert(2, 8));
-        assert!(m.insert(5, 14));
-        let new = 100;
-        match m.find_mut(&5) {
-            None => fail!(), Some(x) => *x = new
-        }
-        assert_eq!(m.find(&5), Some(&new));
-    }
-
-    #[test]
-    fn test_len() {
-        let mut map = SmallIntMap::new();
-        assert_eq!(map.len(), 0);
-        assert!(map.is_empty());
-        assert!(map.insert(5, 20));
-        assert_eq!(map.len(), 1);
-        assert!(!map.is_empty());
-        assert!(map.insert(11, 12));
-        assert_eq!(map.len(), 2);
-        assert!(!map.is_empty());
-        assert!(map.insert(14, 22));
-        assert_eq!(map.len(), 3);
-        assert!(!map.is_empty());
-    }
-
-    #[test]
-    fn test_clear() {
-        let mut map = SmallIntMap::new();
-        assert!(map.insert(5, 20));
-        assert!(map.insert(11, 12));
-        assert!(map.insert(14, 22));
-        map.clear();
-        assert!(map.is_empty());
-        assert!(map.find(&5).is_none());
-        assert!(map.find(&11).is_none());
-        assert!(map.find(&14).is_none());
-    }
-
-    #[test]
-    fn test_insert_with_key() {
-        let mut map = SmallIntMap::new();
-
-        // given a new key, initialize it with this new count, given
-        // given an existing key, add more to its count
-        fn addMoreToCount(_k: uint, v0: uint, v1: uint) -> uint {
-            v0 + v1
-        }
-
-        fn addMoreToCount_simple(v0: uint, v1: uint) -> uint {
-            v0 + v1
-        }
-
-        // count integers
-        map.update(3, 1, addMoreToCount_simple);
-        map.update_with_key(9, 1, addMoreToCount);
-        map.update(3, 7, addMoreToCount_simple);
-        map.update_with_key(5, 3, addMoreToCount);
-        map.update_with_key(3, 2, addMoreToCount);
-
-        // check the total counts
-        assert_eq!(map.find(&3).get(), &10);
-        assert_eq!(map.find(&5).get(), &3);
-        assert_eq!(map.find(&9).get(), &1);
-
-        // sadly, no sevens were counted
-        assert!(map.find(&7).is_none());
-    }
-
-    #[test]
-    fn test_swap() {
-        let mut m = SmallIntMap::new();
-        assert_eq!(m.swap(1, 2), None);
-        assert_eq!(m.swap(1, 3), Some(2));
-        assert_eq!(m.swap(1, 4), Some(3));
-    }
-
-    #[test]
-    fn test_pop() {
-        let mut m = SmallIntMap::new();
-        m.insert(1, 2);
-        assert_eq!(m.pop(&1), Some(2));
-        assert_eq!(m.pop(&1), None);
-    }
-}
-
-#[cfg(test)]
-mod test_set {
-    use super::SmallIntSet;
-
-    #[test]
-    fn test_disjoint() {
-        let mut xs = SmallIntSet::new();
-        let mut ys = SmallIntSet::new();
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(xs.insert(5));
-        assert!(ys.insert(11));
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(xs.insert(7));
-        assert!(xs.insert(19));
-        assert!(xs.insert(4));
-        assert!(ys.insert(2));
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(ys.insert(7));
-        assert!(!xs.is_disjoint(&ys));
-        assert!(!ys.is_disjoint(&xs));
-    }
-
-    #[test]
-    fn test_subset_and_superset() {
-        let mut a = SmallIntSet::new();
-        assert!(a.insert(0));
-        assert!(a.insert(5));
-        assert!(a.insert(11));
-        assert!(a.insert(7));
-
-        let mut b = SmallIntSet::new();
-        assert!(b.insert(0));
-        assert!(b.insert(7));
-        assert!(b.insert(19));
-        assert!(b.insert(250));
-        assert!(b.insert(11));
-        assert!(b.insert(200));
-
-        assert!(!a.is_subset(&b));
-        assert!(!a.is_superset(&b));
-        assert!(!b.is_subset(&a));
-        assert!(!b.is_superset(&a));
-
-        assert!(b.insert(5));
-
-        assert!(a.is_subset(&b));
-        assert!(!a.is_superset(&b));
-        assert!(!b.is_subset(&a));
-        assert!(b.is_superset(&a));
-    }
-
-    #[test]
-    fn test_intersection() {
-        let mut a = SmallIntSet::new();
-        let mut b = SmallIntSet::new();
-
-        assert!(a.insert(11));
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(77));
-        assert!(a.insert(103));
-        assert!(a.insert(5));
-
-        assert!(b.insert(2));
-        assert!(b.insert(11));
-        assert!(b.insert(77));
-        assert!(b.insert(5));
-        assert!(b.insert(3));
-
-        let mut i = 0;
-        let expected = [3, 5, 11, 77];
-        for a.intersection(&b) |x| {
-            assert!(vec::contains(expected, x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_difference() {
-        let mut a = SmallIntSet::new();
-        let mut b = SmallIntSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-
-        assert!(b.insert(3));
-        assert!(b.insert(9));
-
-        let mut i = 0;
-        let expected = [1, 5, 11];
-        for a.difference(&b) |x| {
-            assert!(vec::contains(expected, x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_symmetric_difference() {
-        let mut a = SmallIntSet::new();
-        let mut b = SmallIntSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-
-        assert!(b.insert(3));
-        assert!(b.insert(9));
-        assert!(b.insert(14));
-        assert!(b.insert(22));
-
-        let mut i = 0;
-        let expected = [1, 5, 11, 14, 22];
-        for a.symmetric_difference(&b) |x| {
-            assert!(vec::contains(expected, x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_union() {
-        let mut a = SmallIntSet::new();
-        let mut b = SmallIntSet::new();
-
-        assert!(a.insert(1));
-        assert!(a.insert(3));
-        assert!(a.insert(5));
-        assert!(a.insert(9));
-        assert!(a.insert(11));
-        assert!(a.insert(16));
-        assert!(a.insert(19));
-        assert!(a.insert(24));
-
-        assert!(b.insert(1));
-        assert!(b.insert(5));
-        assert!(b.insert(9));
-        assert!(b.insert(13));
-        assert!(b.insert(19));
-
-        let mut i = 0;
-        let expected = [1, 3, 5, 9, 11, 13, 16, 19, 24];
-        for a.union(&b) |x| {
-            assert!(vec::contains(expected, x));
-            i += 1
-        }
-        assert_eq!(i, expected.len());
-    }
-}
diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs
deleted file mode 100644
index d896fa8c096..00000000000
--- a/src/libstd/sort.rs
+++ /dev/null
@@ -1,1221 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Sorting methods
-
-use core::cmp::{Eq, Ord};
-use core::vec::len;
-use core::vec;
-use core::util::swap;
-
-type Le<'self, T> = &'self fn(v1: &T, v2: &T) -> bool;
-
-/**
- * Merge sort. Returns a new vector containing the sorted list.
- *
- * Has worst case O(n log n) performance, best case O(n), but
- * is not space efficient. This is a stable sort.
- */
-pub fn merge_sort<T:Copy>(v: &[T], le: Le<T>) -> ~[T] {
-    type Slice = (uint, uint);
-
-    return merge_sort_(v, (0u, len(v)), le);
-
-    fn merge_sort_<T:Copy>(v: &[T], slice: Slice, le: Le<T>)
-        -> ~[T] {
-        let begin = slice.first();
-        let end = slice.second();
-
-        let v_len = end - begin;
-        if v_len == 0 { return ~[]; }
-        if v_len == 1 { return ~[v[begin]]; }
-
-        let mid = v_len / 2 + begin;
-        let a = (begin, mid);
-        let b = (mid, end);
-        return merge(le, merge_sort_(v, a, le), merge_sort_(v, b, le));
-    }
-
-    fn merge<T:Copy>(le: Le<T>, a: &[T], b: &[T]) -> ~[T] {
-        let mut rs = vec::with_capacity(len(a) + len(b));
-        let a_len = len(a);
-        let mut a_ix = 0;
-        let b_len = len(b);
-        let mut b_ix = 0;
-        while a_ix < a_len && b_ix < b_len {
-            if le(&a[a_ix], &b[b_ix]) {
-                rs.push(a[a_ix]);
-                a_ix += 1;
-            } else { rs.push(b[b_ix]); b_ix += 1; }
-        }
-        rs.push_all(vec::slice(a, a_ix, a_len));
-        rs.push_all(vec::slice(b, b_ix, b_len));
-        rs
-    }
-}
-
-fn part<T>(arr: &mut [T], left: uint,
-           right: uint, pivot: uint, compare_func: Le<T>) -> uint {
-    vec::swap(arr, pivot, right);
-    let mut storage_index: uint = left;
-    let mut i: uint = left;
-    while i < right {
-        if compare_func(&arr[i], &arr[right]) {
-            vec::swap(arr, i, storage_index);
-            storage_index += 1;
-        }
-        i += 1;
-    }
-    vec::swap(arr, storage_index, right);
-    return storage_index;
-}
-
-fn qsort<T>(arr: &mut [T], left: uint,
-            right: uint, compare_func: Le<T>) {
-    if right > left {
-        let pivot = (left + right) / 2u;
-        let new_pivot = part::<T>(arr, left, right, pivot, compare_func);
-        if new_pivot != 0u {
-            // Need to do this check before recursing due to overflow
-            qsort::<T>(arr, left, new_pivot - 1u, compare_func);
-        }
-        qsort::<T>(arr, new_pivot + 1u, right, compare_func);
-    }
-}
-
-/**
- * Quicksort. Sorts a mut vector in place.
- *
- * Has worst case O(n^2) performance, average case O(n log n).
- * This is an unstable sort.
- */
-pub fn quick_sort<T>(arr: &mut [T], compare_func: Le<T>) {
-    if len::<T>(arr) == 0u { return; }
-    qsort::<T>(arr, 0u, len::<T>(arr) - 1u, compare_func);
-}
-
-fn qsort3<T:Copy + Ord + Eq>(arr: &mut [T], left: int, right: int) {
-    if right <= left { return; }
-    let v: T = arr[right];
-    let mut i: int = left - 1;
-    let mut j: int = right;
-    let mut p: int = i;
-    let mut q: int = j;
-    loop {
-        i += 1;
-        while arr[i] < v { i += 1; }
-        j -= 1;
-        while v < arr[j] {
-            if j == left { break; }
-            j -= 1;
-        }
-        if i >= j { break; }
-        vec::swap(arr, i as uint, j as uint);
-        if arr[i] == v {
-            p += 1;
-            vec::swap(arr, p as uint, i as uint);
-        }
-        if v == arr[j] {
-            q -= 1;
-            vec::swap(arr, j as uint, q as uint);
-        }
-    }
-    vec::swap(arr, i as uint, right as uint);
-    j = i - 1;
-    i += 1;
-    let mut k: int = left;
-    while k < p {
-        vec::swap(arr, k as uint, j as uint);
-        k += 1;
-        j -= 1;
-        if k == len::<T>(arr) as int { break; }
-    }
-    k = right - 1;
-    while k > q {
-        vec::swap(arr, i as uint, k as uint);
-        k -= 1;
-        i += 1;
-        if k == 0 { break; }
-    }
-    qsort3::<T>(arr, left, j);
-    qsort3::<T>(arr, i, right);
-}
-
-/**
- * Fancy quicksort. Sorts a mut vector in place.
- *
- * Based on algorithm presented by ~[Sedgewick and Bentley]
- * (http://www.cs.princeton.edu/~rs/talks/QuicksortIsOptimal.pdf).
- * According to these slides this is the algorithm of choice for
- * 'randomly ordered keys, abstract compare' & 'small number of key values'.
- *
- * This is an unstable sort.
- */
-pub fn quick_sort3<T:Copy + Ord + Eq>(arr: &mut [T]) {
-    if arr.len() <= 1 { return; }
-    let len = arr.len(); // FIXME(#5074) nested calls
-    qsort3(arr, 0, (len - 1) as int);
-}
-
-pub trait Sort {
-    fn qsort(self);
-}
-
-impl<'self, T:Copy + Ord + Eq> Sort for &'self mut [T] {
-    fn qsort(self) { quick_sort3(self); }
-}
-
-static MIN_MERGE: uint = 64;
-static MIN_GALLOP: uint = 7;
-static INITIAL_TMP_STORAGE: uint = 128;
-
-pub fn tim_sort<T:Copy + Ord>(array: &mut [T]) {
-    let size = array.len();
-    if size < 2 {
-        return;
-    }
-
-    if size < MIN_MERGE {
-        let init_run_len = count_run_ascending(array);
-        binarysort(array, init_run_len);
-        return;
-    }
-
-    let mut ms = MergeState();
-    let min_run = min_run_length(size);
-
-    let mut idx = 0;
-    let mut remaining = size;
-    loop {
-        let run_len: uint = {
-            // This scope contains the slice `arr` here:
-            let arr = vec::mut_slice(array, idx, size);
-            let mut run_len: uint = count_run_ascending(arr);
-
-            if run_len < min_run {
-                let force = if remaining <= min_run {remaining} else {min_run};
-                let slice = vec::mut_slice(arr, 0, force);
-                binarysort(slice, run_len);
-                run_len = force;
-            }
-
-            run_len
-        };
-
-        ms.push_run(idx, run_len);
-        ms.merge_collapse(array);
-
-        idx += run_len;
-        remaining -= run_len;
-        if remaining == 0 { break; }
-    }
-
-    ms.merge_force_collapse(array);
-}
-
-fn binarysort<T:Copy + Ord>(array: &mut [T], start: uint) {
-    let size = array.len();
-    let mut start = start;
-    assert!(start <= size);
-
-    if start == 0 { start += 1; }
-
-    while start < size {
-        let pivot = array[start];
-        let mut left = 0;
-        let mut right = start;
-        assert!(left <= right);
-
-        while left < right {
-            let mid = (left + right) >> 1;
-            if pivot < array[mid] {
-                right = mid;
-            } else {
-                left = mid+1;
-            }
-        }
-        assert_eq!(left, right);
-        let n = start-left;
-
-        shift_vec(array, left+1, left, n);
-        array[left] = pivot;
-        start += 1;
-    }
-}
-
-// Reverse the order of elements in a slice, in place
-fn reverse_slice<T>(v: &mut [T], start: uint, end:uint) {
-    let mut i = start;
-    while i < end / 2 {
-        vec::swap(v, i, end - i - 1);
-        i += 1;
-    }
-}
-
-fn min_run_length(n: uint) -> uint {
-    let mut n = n;
-    let mut r = 0;   // becomes 1 if any 1 bits are shifted off
-
-    while n >= MIN_MERGE {
-        r |= n & 1;
-        n >>= 1;
-    }
-    return n + r;
-}
-
-fn count_run_ascending<T:Copy + Ord>(array: &mut [T]) -> uint {
-    let size = array.len();
-    assert!(size > 0);
-    if size == 1 { return 1; }
-
-    let mut run = 2;
-    if array[1] < array[0] {
-        while run < size && array[run] < array[run-1] {
-            run += 1;
-        }
-        reverse_slice(array, 0, run);
-    } else {
-        while run < size && array[run] >= array[run-1] {
-            run += 1;
-        }
-    }
-
-    return run;
-}
-
-fn gallop_left<T:Copy + Ord>(key: &T,
-                             array: &[T],
-                             hint: uint)
-                          -> uint {
-    let size = array.len();
-    assert!(size != 0 && hint < size);
-
-    let mut last_ofs = 0;
-    let mut ofs = 1;
-
-    if *key > array[hint] {
-        // Gallop right until array[hint+last_ofs] < key <= array[hint+ofs]
-        let max_ofs = size - hint;
-        while ofs < max_ofs && *key > array[hint+ofs] {
-            last_ofs = ofs;
-            ofs = (ofs << 1) + 1;
-            if ofs < last_ofs { ofs = max_ofs; } // uint overflow guard
-        }
-        if ofs > max_ofs { ofs = max_ofs; }
-
-        last_ofs += hint;
-        ofs += hint;
-    } else {
-        let max_ofs = hint + 1;
-        while ofs < max_ofs && *key <= array[hint-ofs] {
-            last_ofs = ofs;
-            ofs = (ofs << 1) + 1;
-            if ofs < last_ofs { ofs = max_ofs; } // uint overflow guard
-        }
-
-        if ofs > max_ofs { ofs = max_ofs; }
-
-        let tmp = last_ofs;
-        last_ofs = hint - ofs;
-        ofs = hint - tmp;
-    }
-    assert!((last_ofs < ofs || last_ofs+1 < ofs+1) && ofs <= size);
-
-    last_ofs += 1;
-    while last_ofs < ofs {
-        let m = last_ofs + ((ofs - last_ofs) >> 1);
-        if *key > array[m] {
-            last_ofs = m+1;
-        } else {
-            ofs = m;
-        }
-    }
-    assert_eq!(last_ofs, ofs);
-    return ofs;
-}
-
-fn gallop_right<T:Copy + Ord>(key: &T,
-                              array: &[T],
-                              hint: uint)
-                           -> uint {
-    let size = array.len();
-    assert!(size != 0 && hint < size);
-
-    let mut last_ofs = 0;
-    let mut ofs = 1;
-
-    if *key >= array[hint] {
-        // Gallop right until array[hint+last_ofs] <= key < array[hint+ofs]
-        let max_ofs = size - hint;
-        while ofs < max_ofs && *key >= array[hint+ofs] {
-            last_ofs = ofs;
-            ofs = (ofs << 1) + 1;
-            if ofs < last_ofs { ofs = max_ofs; }
-        }
-        if ofs > max_ofs { ofs = max_ofs; }
-
-        last_ofs += hint;
-        ofs += hint;
-    } else {
-        // Gallop left until array[hint-ofs] <= key < array[hint-last_ofs]
-        let max_ofs = hint + 1;
-        while ofs < max_ofs && *key < array[hint-ofs] {
-            last_ofs = ofs;
-            ofs = (ofs << 1) + 1;
-            if ofs < last_ofs { ofs = max_ofs; }
-        }
-        if ofs > max_ofs { ofs = max_ofs; }
-
-        let tmp = last_ofs;
-        last_ofs = hint - ofs;
-        ofs = hint - tmp;
-    }
-
-    assert!((last_ofs < ofs || last_ofs+1 < ofs+1) && ofs <= size);
-
-    last_ofs += 1;
-    while last_ofs < ofs {
-        let m = last_ofs + ((ofs - last_ofs) >> 1);
-
-        if *key >= array[m] {
-            last_ofs = m + 1;
-        } else {
-            ofs = m;
-        }
-    }
-    assert_eq!(last_ofs, ofs);
-    return ofs;
-}
-
-struct RunState {
-    base: uint,
-    len: uint,
-}
-
-struct MergeState<T> {
-    min_gallop: uint,
-    runs: ~[RunState],
-}
-
-// Fixme (#3853) Move into MergeState
-fn MergeState<T>() -> MergeState<T> {
-    MergeState {
-        min_gallop: MIN_GALLOP,
-        runs: ~[],
-    }
-}
-
-impl<T:Copy + Ord> MergeState<T> {
-    fn push_run(&mut self, run_base: uint, run_len: uint) {
-        let tmp = RunState{base: run_base, len: run_len};
-        self.runs.push(tmp);
-    }
-
-    fn merge_at(&mut self, n: uint, array: &mut [T]) {
-        let size = self.runs.len();
-        assert!(size >= 2);
-        assert!(n == size-2 || n == size-3);
-
-        let mut b1 = self.runs[n].base;
-        let mut l1 = self.runs[n].len;
-        let b2 = self.runs[n+1].base;
-        let l2 = self.runs[n+1].len;
-
-        assert!(l1 > 0 && l2 > 0);
-        assert_eq!(b1 + l1, b2);
-
-        self.runs[n].len = l1 + l2;
-        if n == size-3 {
-            self.runs[n+1].base = self.runs[n+2].base;
-            self.runs[n+1].len = self.runs[n+2].len;
-        }
-
-        let k = { // constrain lifetime of slice below
-            let slice = vec::slice(array, b1, b1+l1);
-            gallop_right(&array[b2], slice, 0)
-        };
-        b1 += k;
-        l1 -= k;
-        if l1 != 0 {
-            let l2 = { // constrain lifetime of slice below
-                let slice = vec::slice(array, b2, b2+l2);
-                gallop_left(&array[b1+l1-1],slice,l2-1)
-            };
-            if l2 > 0 {
-                if l1 <= l2 {
-                    self.merge_lo(array, b1, l1, b2, l2);
-                } else {
-                    self.merge_hi(array, b1, l1, b2, l2);
-                }
-            }
-        }
-        self.runs.pop();
-    }
-
-    fn merge_lo(&mut self, array: &mut [T], base1: uint, len1: uint,
-                base2: uint, len2: uint) {
-        assert!(len1 != 0 && len2 != 0 && base1+len1 == base2);
-
-        let mut tmp = ~[];
-        for uint::range(base1, base1+len1) |i| {
-            tmp.push(array[i]);
-        }
-
-        let mut c1 = 0;
-        let mut c2 = base2;
-        let mut dest = base1;
-        let mut len1 = len1;
-        let mut len2 = len2;
-
-        vec::swap(array, dest, c2);
-        dest += 1; c2 += 1; len2 -= 1;
-
-        if len2 == 0 {
-            copy_vec(array, dest, tmp.slice(0, len1));
-            return;
-        }
-        if len1 == 1 {
-            shift_vec(array, dest, c2, len2);
-            swap(&mut tmp[c1], &mut array[dest+len2]);
-            return;
-        }
-
-        let mut min_gallop = self.min_gallop;
-        loop {
-            let mut count1 = 0;
-            let mut count2 = 0;
-            let mut break_outer = false;
-
-            loop {
-                assert!(len1 > 1 && len2 != 0);
-                if array[c2] < tmp[c1] {
-                    vec::swap(array, dest, c2);
-                    dest += 1; c2 += 1; len2 -= 1;
-                    count2 += 1; count1 = 0;
-                    if len2 == 0 {
-                        break_outer = true;
-                    }
-                } else {
-                    swap(&mut array[dest], &mut tmp[c1]);
-                    dest += 1; c1 += 1; len1 -= 1;
-                    count1 += 1; count2 = 0;
-                    if len1 == 1 {
-                        break_outer = true;
-                    }
-                }
-                if break_outer || ((count1 | count2) >= min_gallop) {
-                    break;
-                }
-            }
-            if break_outer { break; }
-
-            // Start to gallop
-            loop {
-                assert!(len1 > 1 && len2 != 0);
-
-                count1 = {
-                    let tmp_view = vec::slice(tmp, c1, c1+len1);
-                    gallop_right(&array[c2], tmp_view, 0)
-                };
-                if count1 != 0 {
-                    copy_vec(array, dest, tmp.slice(c1, c1+count1));
-                    dest += count1; c1 += count1; len1 -= count1;
-                    if len1 <= 1 { break_outer = true; break; }
-                }
-                vec::swap(array, dest, c2);
-                dest += 1; c2 += 1; len2 -= 1;
-                if len2 == 0 { break_outer = true; break; }
-
-                count2 = {
-                    let tmp_view = vec::slice(array, c2, c2+len2);
-                    gallop_left(&tmp[c1], tmp_view, 0)
-                };
-                if count2 != 0 {
-                    shift_vec(array, dest, c2, count2);
-                    dest += count2; c2 += count2; len2 -= count2;
-                    if len2 == 0 { break_outer = true; break; }
-                }
-                swap(&mut array[dest], &mut tmp[c1]);
-                dest += 1; c1 += 1; len1 -= 1;
-                if len1 == 1 { break_outer = true; break; }
-                min_gallop -= 1;
-                if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) {
-                    break;
-                }
-            }
-            if break_outer { break; }
-            if min_gallop < 0 { min_gallop = 0; }
-            min_gallop += 2; // Penalize for leaving gallop
-        }
-        self.min_gallop = if min_gallop < 1 { 1 } else { min_gallop };
-
-        if len1 == 1 {
-            assert!(len2 > 0);
-            shift_vec(array, dest, c2, len2);
-            swap(&mut array[dest+len2], &mut tmp[c1]);
-        } else if len1 == 0 {
-            fail!("Comparison violates its contract!");
-        } else {
-            assert_eq!(len2, 0);
-            assert!(len1 > 1);
-            copy_vec(array, dest, tmp.slice(c1, c1+len1));
-        }
-    }
-
-    fn merge_hi(&mut self, array: &mut [T], base1: uint, len1: uint,
-                base2: uint, len2: uint) {
-        assert!(len1 != 1 && len2 != 0 && base1 + len1 == base2);
-
-        let mut tmp = ~[];
-        for uint::range(base2, base2+len2) |i| {
-            tmp.push(array[i]);
-        }
-
-        let mut c1 = base1 + len1 - 1;
-        let mut c2 = len2 - 1;
-        let mut dest = base2 + len2 - 1;
-        let mut len1 = len1;
-        let mut len2 = len2;
-
-        vec::swap(array, dest, c1);
-        dest -= 1; c1 -= 1; len1 -= 1;
-
-        if len1 == 0 {
-            copy_vec(array, dest-(len2-1), tmp.slice(0, len2));
-            return;
-        }
-        if len2 == 1 {
-            dest -= len1;
-            c1 -= len1;
-            shift_vec(array, dest+1, c1+1, len1);
-            swap(&mut array[dest], &mut tmp[c2]);
-            return;
-        }
-
-        let mut min_gallop = self.min_gallop;
-        loop {
-            let mut count1 = 0;
-            let mut count2 = 0;
-            let mut break_outer = false;
-
-            loop {
-                assert!(len1 != 0 && len2 > 1);
-                if tmp[c2] < array[c1] {
-                    vec::swap(array, dest, c1);
-                    dest -= 1; c1 -= 1; len1 -= 1;
-                    count1 += 1; count2 = 0;
-                    if len1 == 0 {
-                        break_outer = true;
-                    }
-                } else {
-                    swap(&mut array[dest], &mut tmp[c2]);
-                    dest -= 1; c2 -= 1; len2 -= 1;
-                    count2 += 1; count1 = 0;
-                    if len2 == 1 {
-                        break_outer = true;
-                    }
-                }
-                if break_outer || ((count1 | count2) >= min_gallop) {
-                    break;
-                }
-            }
-            if break_outer { break; }
-
-            // Start to gallop
-            loop {
-                assert!(len2 > 1 && len1 != 0);
-
-                { // constrain scope of tmp_view:
-                    let tmp_view = vec::mut_slice (array, base1, base1+len1);
-                    count1 = len1 - gallop_right(
-                        &tmp[c2], tmp_view, len1-1);
-                }
-
-                if count1 != 0 {
-                    dest -= count1; c1 -= count1; len1 -= count1;
-                    shift_vec(array, dest+1, c1+1, count1);
-                    if len1 == 0 { break_outer = true; break; }
-                }
-
-                swap(&mut array[dest], &mut tmp[c2]);
-                dest -= 1; c2 -= 1; len2 -= 1;
-                if len2 == 1 { break_outer = true; break; }
-
-                let count2;
-                { // constrain scope of tmp_view
-                    let tmp_view = vec::mut_slice(tmp, 0, len2);
-                    count2 = len2 - gallop_left(&array[c1],
-                                                tmp_view,
-                                                len2-1);
-                }
-
-                if count2 != 0 {
-                    dest -= count2; c2 -= count2; len2 -= count2;
-                    copy_vec(array, dest+1, tmp.slice(c2+1, c2+1+count2));
-                    if len2 <= 1 { break_outer = true; break; }
-                }
-                vec::swap(array, dest, c1);
-                dest -= 1; c1 -= 1; len1 -= 1;
-                if len1 == 0 { break_outer = true; break; }
-                min_gallop -= 1;
-                if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) {
-                    break;
-                }
-            }
-
-            if break_outer { break; }
-            if min_gallop < 0 { min_gallop = 0; }
-            min_gallop += 2; // Penalize for leaving gallop
-        }
-        self.min_gallop = if min_gallop < 1 { 1 } else { min_gallop };
-
-        if len2 == 1 {
-            assert!(len1 > 0);
-            dest -= len1;
-            c1 -= len1;
-            shift_vec(array, dest+1, c1+1, len1);
-            swap(&mut array[dest], &mut tmp[c2]);
-        } else if len2 == 0 {
-            fail!("Comparison violates its contract!");
-        } else {
-            assert_eq!(len1, 0);
-            assert!(len2 != 0);
-            copy_vec(array, dest-(len2-1), tmp.slice(0, len2));
-        }
-    }
-
-    fn merge_collapse(&mut self, array: &mut [T]) {
-        while self.runs.len() > 1 {
-            let mut n = self.runs.len()-2;
-            if n > 0 &&
-                self.runs[n-1].len <= self.runs[n].len + self.runs[n+1].len
-            {
-                if self.runs[n-1].len < self.runs[n+1].len { n -= 1; }
-            } else if self.runs[n].len <= self.runs[n+1].len {
-                /* keep going */
-            } else {
-                break;
-            }
-            self.merge_at(n, array);
-        }
-    }
-
-    fn merge_force_collapse(&mut self, array: &mut [T]) {
-        while self.runs.len() > 1 {
-            let mut n = self.runs.len()-2;
-            if n > 0 {
-                if self.runs[n-1].len < self.runs[n+1].len {
-                    n -= 1;
-                }
-            }
-            self.merge_at(n, array);
-        }
-    }
-}
-
-#[inline(always)]
-fn copy_vec<T:Copy>(dest: &mut [T],
-                    s1: uint,
-                    from: &[T]) {
-    assert!(s1+from.len() <= dest.len());
-
-    for from.eachi |i, v| {
-        dest[s1+i] = *v;
-    }
-}
-
-#[inline(always)]
-fn shift_vec<T:Copy>(dest: &mut [T],
-                     s1: uint,
-                     s2: uint,
-                     len: uint) {
-    assert!(s1+len <= dest.len());
-
-    let tmp = dest.slice(s2, s2+len).to_vec();
-    copy_vec(dest, s1, tmp);
-}
-
-#[cfg(test)]
-mod test_qsort3 {
-    use sort::*;
-
-    use core::vec;
-
-    fn check_sort(v1: &mut [int], v2: &mut [int]) {
-        let len = vec::len::<int>(v1);
-        quick_sort3::<int>(v1);
-        let mut i = 0;
-        while i < len {
-            assert_eq!(v2[i], v1[i]);
-            i += 1;
-        }
-    }
-
-    #[test]
-    fn test() {
-        {
-            let mut v1 = ~[3, 7, 4, 5, 2, 9, 5, 8];
-            let mut v2 = ~[2, 3, 4, 5, 5, 7, 8, 9];
-            check_sort(v1, v2);
-        }
-        {
-            let mut v1 = ~[1, 1, 1];
-            let mut v2 = ~[1, 1, 1];
-            check_sort(v1, v2);
-        }
-        {
-            let mut v1: ~[int] = ~[];
-            let mut v2: ~[int] = ~[];
-            check_sort(v1, v2);
-        }
-        { let mut v1 = ~[9]; let mut v2 = ~[9]; check_sort(v1, v2); }
-        {
-            let mut v1 = ~[9, 3, 3, 3, 9];
-            let mut v2 = ~[3, 3, 3, 9, 9];
-            check_sort(v1, v2);
-        }
-    }
-}
-
-#[cfg(test)]
-mod test_qsort {
-    use sort::*;
-
-    use core::int;
-    use core::vec;
-
-    fn check_sort(v1: &mut [int], v2: &mut [int]) {
-        let len = vec::len::<int>(v1);
-        fn leual(a: &int, b: &int) -> bool { *a <= *b }
-        quick_sort::<int>(v1, leual);
-        let mut i = 0u;
-        while i < len {
-            // debug!(v2[i]);
-            assert_eq!(v2[i], v1[i]);
-            i += 1;
-        }
-    }
-
-    #[test]
-    fn test() {
-        {
-            let mut v1 = ~[3, 7, 4, 5, 2, 9, 5, 8];
-            let mut v2 = ~[2, 3, 4, 5, 5, 7, 8, 9];
-            check_sort(v1, v2);
-        }
-        {
-            let mut v1 = ~[1, 1, 1];
-            let mut v2 = ~[1, 1, 1];
-            check_sort(v1, v2);
-        }
-        {
-            let mut v1: ~[int] = ~[];
-            let mut v2: ~[int] = ~[];
-            check_sort(v1, v2);
-        }
-        { let mut v1 = ~[9]; let mut v2 = ~[9]; check_sort(v1, v2); }
-        {
-            let mut v1 = ~[9, 3, 3, 3, 9];
-            let mut v2 = ~[3, 3, 3, 9, 9];
-            check_sort(v1, v2);
-        }
-    }
-
-    // Regression test for #750
-    #[test]
-    fn test_simple() {
-        let mut names = ~[2, 1, 3];
-
-        let expected = ~[1, 2, 3];
-
-        do quick_sort(names) |x, y| { int::le(*x, *y) };
-
-        let immut_names = names;
-
-        let pairs = vec::zip_slice(expected, immut_names);
-        for pairs.each |p| {
-            let (a, b) = *p;
-            debug!("%d %d", a, b);
-            assert_eq!(a, b);
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-
-    use sort::*;
-
-    use core::vec;
-
-    fn check_sort(v1: &[int], v2: &[int]) {
-        let len = vec::len::<int>(v1);
-        pub fn le(a: &int, b: &int) -> bool { *a <= *b }
-        let f = le;
-        let v3 = merge_sort::<int>(v1, f);
-        let mut i = 0u;
-        while i < len {
-            debug!(v3[i]);
-            assert_eq!(v3[i], v2[i]);
-            i += 1;
-        }
-    }
-
-    #[test]
-    fn test() {
-        {
-            let v1 = ~[3, 7, 4, 5, 2, 9, 5, 8];
-            let v2 = ~[2, 3, 4, 5, 5, 7, 8, 9];
-            check_sort(v1, v2);
-        }
-        { let v1 = ~[1, 1, 1]; let v2 = ~[1, 1, 1]; check_sort(v1, v2); }
-        { let v1:~[int] = ~[]; let v2:~[int] = ~[]; check_sort(v1, v2); }
-        { let v1 = ~[9]; let v2 = ~[9]; check_sort(v1, v2); }
-        {
-            let v1 = ~[9, 3, 3, 3, 9];
-            let v2 = ~[3, 3, 3, 9, 9];
-            check_sort(v1, v2);
-        }
-    }
-
-    #[test]
-    fn test_merge_sort_mutable() {
-        pub fn le(a: &int, b: &int) -> bool { *a <= *b }
-        let mut v1 = ~[3, 2, 1];
-        let v2 = merge_sort(v1, le);
-        assert_eq!(v2, ~[1, 2, 3]);
-    }
-
-    #[test]
-    fn test_merge_sort_stability() {
-        // tjc: funny that we have to use parens
-        fn ile(x: &(&'static str), y: &(&'static str)) -> bool
-        {
-            // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
-            // to_ascii_consume and to_str_consume to not do a unnecessary copy.
-            // (Actually, could just remove the to_str_* call, but needs an deriving(Ord) on
-            // Ascii)
-            let x = x.to_ascii().to_lower().to_str_ascii();
-            let y = y.to_ascii().to_lower().to_str_ascii();
-            x <= y
-        }
-
-        let names1 = ~["joe bob", "Joe Bob", "Jack Brown", "JOE Bob",
-                       "Sally Mae", "JOE BOB", "Alex Andy"];
-        let names2 = ~["Alex Andy", "Jack Brown", "joe bob", "Joe Bob",
-                       "JOE Bob", "JOE BOB", "Sally Mae"];
-        let names3 = merge_sort(names1, ile);
-        assert_eq!(names3, names2);
-    }
-}
-
-#[cfg(test)]
-mod test_tim_sort {
-    use sort::tim_sort;
-    use core::rand::RngUtil;
-
-    struct CVal {
-        val: float,
-    }
-
-    impl Ord for CVal {
-        fn lt(&self, other: &CVal) -> bool {
-            let mut rng = rand::rng();
-            if rng.gen::<float>() > 0.995 {
-                fail!("It's happening!!!");
-            }
-            (*self).val < other.val
-        }
-        fn le(&self, other: &CVal) -> bool { (*self).val <= other.val }
-        fn gt(&self, other: &CVal) -> bool { (*self).val > other.val }
-        fn ge(&self, other: &CVal) -> bool { (*self).val >= other.val }
-    }
-
-    fn check_sort(v1: &mut [int], v2: &mut [int]) {
-        let len = vec::len::<int>(v1);
-        tim_sort::<int>(v1);
-        let mut i = 0u;
-        while i < len {
-            // debug!(v2[i]);
-            assert_eq!(v2[i], v1[i]);
-            i += 1u;
-        }
-    }
-
-    #[test]
-    fn test() {
-        {
-            let mut v1 = ~[3, 7, 4, 5, 2, 9, 5, 8];
-            let mut v2 = ~[2, 3, 4, 5, 5, 7, 8, 9];
-            check_sort(v1, v2);
-        }
-        {
-            let mut v1 = ~[1, 1, 1];
-            let mut v2 = ~[1, 1, 1];
-            check_sort(v1, v2);
-        }
-        {
-            let mut v1: ~[int] = ~[];
-            let mut v2: ~[int] = ~[];
-            check_sort(v1, v2);
-        }
-        { let mut v1 = ~[9]; let mut v2 = ~[9]; check_sort(v1, v2); }
-        {
-            let mut v1 = ~[9, 3, 3, 3, 9];
-            let mut v2 = ~[3, 3, 3, 9, 9];
-            check_sort(v1, v2);
-        }
-    }
-
-    #[test]
-    #[should_fail]
-    #[cfg(unix)]
-    fn crash_test() {
-        let mut rng = rand::rng();
-        let mut arr = do vec::from_fn(1000) |_i| {
-            CVal { val: rng.gen() }
-        };
-
-        tim_sort(arr);
-        fail!("Guarantee the fail");
-    }
-
-    struct DVal { val: uint }
-
-    impl Ord for DVal {
-        fn lt(&self, _x: &DVal) -> bool { true }
-        fn le(&self, _x: &DVal) -> bool { true }
-        fn gt(&self, _x: &DVal) -> bool { true }
-        fn ge(&self, _x: &DVal) -> bool { true }
-    }
-
-    #[test]
-    fn test_bad_Ord_impl() {
-        let mut rng = rand::rng();
-        let mut arr = do vec::from_fn(500) |_i| {
-            DVal { val: rng.gen() }
-        };
-
-        tim_sort(arr);
-    }
-}
-
-#[cfg(test)]
-mod big_tests {
-    use sort::*;
-    use core::rand::RngUtil;
-
-    #[test]
-    fn test_unique() {
-        let low = 5;
-        let high = 10;
-        tabulate_unique(low, high);
-    }
-
-    #[test]
-    fn test_managed() {
-        let low = 5;
-        let high = 10;
-        tabulate_managed(low, high);
-    }
-
-    fn multiplyVec<T:Copy>(arr: &[T], num: uint) -> ~[T] {
-        let size = arr.len();
-        let res = do vec::from_fn(num) |i| {
-            arr[i % size]
-        };
-        res
-    }
-
-    fn makeRange(n: uint) -> ~[uint] {
-        let one = do vec::from_fn(n) |i| { i };
-        let mut two = copy one;
-        vec::reverse(two);
-        vec::append(two, one)
-    }
-
-    fn tabulate_unique(lo: uint, hi: uint) {
-        fn isSorted<T:Ord>(arr: &[T]) {
-            for uint::range(0, arr.len()-1) |i| {
-                if arr[i] > arr[i+1] {
-                    fail!("Array not sorted");
-                }
-            }
-        }
-
-        let mut rng = rand::rng();
-
-        for uint::range(lo, hi) |i| {
-            let n = 1 << i;
-            let mut arr: ~[float] = do vec::from_fn(n) |_i| {
-                rng.gen()
-            };
-
-            tim_sort(arr); // *sort
-            isSorted(arr);
-
-            vec::reverse(arr);
-            tim_sort(arr); // \sort
-            isSorted(arr);
-
-            tim_sort(arr); // /sort
-            isSorted(arr);
-
-            for 3.times {
-                let i1 = rng.gen_uint_range(0, n);
-                let i2 = rng.gen_uint_range(0, n);
-                vec::swap(arr, i1, i2);
-            }
-            tim_sort(arr); // 3sort
-            isSorted(arr);
-
-            if n >= 10 {
-                let size = arr.len();
-                let mut idx = 1;
-                while idx <= 10 {
-                    arr[size-idx] = rng.gen();
-                    idx += 1;
-                }
-            }
-            tim_sort(arr); // +sort
-            isSorted(arr);
-
-            for (n/100).times {
-                let idx = rng.gen_uint_range(0, n);
-                arr[idx] = rng.gen();
-            }
-            tim_sort(arr);
-            isSorted(arr);
-
-            let mut arr = if n > 4 {
-                let part = vec::slice(arr, 0, 4);
-                multiplyVec(part, n)
-            } else { arr };
-            tim_sort(arr); // ~sort
-            isSorted(arr);
-
-            let mut arr = vec::from_elem(n, -0.5);
-            tim_sort(arr); // =sort
-            isSorted(arr);
-
-            let half = n / 2;
-            let mut arr = makeRange(half).map(|i| *i as float);
-            tim_sort(arr); // !sort
-            isSorted(arr);
-        }
-    }
-
-    fn tabulate_managed(lo: uint, hi: uint) {
-        fn isSorted<T:Ord>(arr: &[@T]) {
-            for uint::range(0, arr.len()-1) |i| {
-                if arr[i] > arr[i+1] {
-                    fail!("Array not sorted");
-                }
-            }
-        }
-
-        let mut rng = rand::rng();
-
-        for uint::range(lo, hi) |i| {
-            let n = 1 << i;
-            let arr: ~[@float] = do vec::from_fn(n) |_i| {
-                @rng.gen()
-            };
-            let mut arr = arr;
-
-            tim_sort(arr); // *sort
-            isSorted(arr);
-
-            vec::reverse(arr);
-            tim_sort(arr); // \sort
-            isSorted(arr);
-
-            tim_sort(arr); // /sort
-            isSorted(arr);
-
-            for 3.times {
-                let i1 = rng.gen_uint_range(0, n);
-                let i2 = rng.gen_uint_range(0, n);
-                vec::swap(arr, i1, i2);
-            }
-            tim_sort(arr); // 3sort
-            isSorted(arr);
-
-            if n >= 10 {
-                let size = arr.len();
-                let mut idx = 1;
-                while idx <= 10 {
-                    arr[size-idx] = @rng.gen();
-                    idx += 1;
-                }
-            }
-            tim_sort(arr); // +sort
-            isSorted(arr);
-
-            for (n/100).times {
-                let idx = rng.gen_uint_range(0, n);
-                arr[idx] = @rng.gen();
-            }
-            tim_sort(arr);
-            isSorted(arr);
-
-            let mut arr = if n > 4 {
-                let part = vec::slice(arr, 0, 4);
-                multiplyVec(part, n)
-            } else { arr };
-            tim_sort(arr); // ~sort
-            isSorted(arr);
-
-            let mut arr = vec::from_elem(n, @(-0.5));
-            tim_sort(arr); // =sort
-            isSorted(arr);
-
-            let half = n / 2;
-            let mut arr = makeRange(half).map(|i| @(*i as float));
-            tim_sort(arr); // !sort
-            isSorted(arr);
-        }
-    }
-
-    struct LVal<'self> {
-        val: uint,
-        key: &'self fn(@uint),
-    }
-
-    #[unsafe_destructor]
-    impl<'self> Drop for LVal<'self> {
-        fn finalize(&self) {
-            let x = unsafe { local_data::local_data_get(self.key) };
-            match x {
-                Some(@y) => {
-                    unsafe {
-                        local_data::local_data_set(self.key, @(y+1));
-                    }
-                }
-                _ => fail!("Expected key to work"),
-            }
-        }
-    }
-
-    impl<'self> Ord for LVal<'self> {
-        fn lt<'a>(&self, other: &'a LVal<'self>) -> bool {
-            (*self).val < other.val
-        }
-        fn le<'a>(&self, other: &'a LVal<'self>) -> bool {
-            (*self).val <= other.val
-        }
-        fn gt<'a>(&self, other: &'a LVal<'self>) -> bool {
-            (*self).val > other.val
-        }
-        fn ge<'a>(&self, other: &'a LVal<'self>) -> bool {
-            (*self).val >= other.val
-        }
-    }
-}
diff --git a/src/libstd/stackwalk.rs b/src/libstd/stackwalk.rs
new file mode 100644
index 00000000000..784656718d0
--- /dev/null
+++ b/src/libstd/stackwalk.rs
@@ -0,0 +1,81 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[doc(hidden)]; // FIXME #3538
+
+use cast::transmute;
+use unstable::intrinsics;
+
+pub type Word = uint;
+
+pub struct Frame {
+    fp: *Word
+}
+
+pub fn Frame(fp: *Word) -> Frame {
+    Frame {
+        fp: fp
+    }
+}
+
+pub fn walk_stack(visit: &fn(Frame) -> bool) -> bool {
+
+    debug!("beginning stack walk");
+
+    do frame_address |frame_pointer| {
+        let mut frame_address: *Word = unsafe {
+            transmute(frame_pointer)
+        };
+        loop {
+            let fr = Frame(frame_address);
+
+            debug!("frame: %x", unsafe { transmute(fr.fp) });
+            visit(fr);
+
+            unsafe {
+                let next_fp: **Word = transmute(frame_address);
+                frame_address = *next_fp;
+                if *frame_address == 0u {
+                    debug!("encountered task_start_wrapper. ending walk");
+                    // This is the task_start_wrapper_frame. There is
+                    // no stack beneath it and it is a foreign frame.
+                    break;
+                }
+            }
+        }
+    }
+    return true;
+}
+
+#[test]
+fn test_simple() {
+    for walk_stack |_frame| {
+    }
+}
+
+#[test]
+fn test_simple_deep() {
+    fn run(i: int) {
+        if i == 0 { return }
+
+        for walk_stack |_frame| {
+            // Would be nice to test something here...
+        }
+        run(i - 1);
+    }
+
+    run(10);
+}
+
+fn frame_address(f: &fn(x: *u8)) {
+    unsafe {
+        intrinsics::frame_address(f)
+    }
+}
diff --git a/src/libstd/stats.rs b/src/libstd/stats.rs
deleted file mode 100644
index 25323b4e1db..00000000000
--- a/src/libstd/stats.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use core::vec;
-use core::f64;
-use core::cmp;
-use core::num;
-use sort;
-
-// NB: this can probably be rewritten in terms of num::Num
-// to be less f64-specific.
-
-pub trait Stats {
-    fn sum(self) -> f64;
-    fn min(self) -> f64;
-    fn max(self) -> f64;
-    fn mean(self) -> f64;
-    fn median(self) -> f64;
-    fn var(self) -> f64;
-    fn std_dev(self) -> f64;
-    fn std_dev_pct(self) -> f64;
-    fn median_abs_dev(self) -> f64;
-    fn median_abs_dev_pct(self) -> f64;
-}
-
-impl<'self> Stats for &'self [f64] {
-    fn sum(self) -> f64 {
-        vec::foldl(0.0, self, |p,q| p + *q)
-    }
-
-    fn min(self) -> f64 {
-        assert!(self.len() != 0);
-        vec::foldl(self[0], self, |p,q| cmp::min(p, *q))
-    }
-
-    fn max(self) -> f64 {
-        assert!(self.len() != 0);
-        vec::foldl(self[0], self, |p,q| cmp::max(p, *q))
-    }
-
-    fn mean(self) -> f64 {
-        assert!(self.len() != 0);
-        self.sum() / (self.len() as f64)
-    }
-
-    fn median(self) -> f64 {
-        assert!(self.len() != 0);
-        let mut tmp = vec::to_owned(self);
-        sort::tim_sort(tmp);
-        if tmp.len() & 1 == 0 {
-            let m = tmp.len() / 2;
-            (tmp[m] + tmp[m-1]) / 2.0
-        } else {
-            tmp[tmp.len() / 2]
-        }
-    }
-
-    fn var(self) -> f64 {
-        if self.len() == 0 {
-            0.0
-        } else {
-            let mean = self.mean();
-            let mut v = 0.0;
-            for self.each |s| {
-                let x = *s - mean;
-                v += x*x;
-            }
-            v/(self.len() as f64)
-        }
-    }
-
-    fn std_dev(self) -> f64 {
-        f64::sqrt(self.var())
-    }
-
-    fn std_dev_pct(self) -> f64 {
-        (self.std_dev() / self.mean()) * 100.0
-    }
-
-    fn median_abs_dev(self) -> f64 {
-        let med = self.median();
-        let abs_devs = self.map(|v| num::abs(med - *v));
-        abs_devs.median()
-    }
-
-    fn median_abs_dev_pct(self) -> f64 {
-        (self.median_abs_dev() / self.median()) * 100.0
-    }
-}
diff --git a/src/libstd/std.rc b/src/libstd/std.rc
deleted file mode 100644
index 72f06f0befa..00000000000
--- a/src/libstd/std.rc
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
-
-The Rust standard library.
-
-The Rust standand library provides a number of useful features that are
-not required in or otherwise suitable for the core library.
-
-*/
-
-#[link(name = "std",
-       vers = "0.7-pre",
-       uuid = "122bed0b-c19b-4b82-b0b7-7ae8aead7297",
-       url = "https://github.com/mozilla/rust/tree/master/src/libstd")];
-
-#[comment = "The Rust standard library"];
-#[license = "MIT/ASL2"];
-#[crate_type = "lib"];
-
-#[deny(non_camel_case_types)];
-
-pub mod uv_ll;
-
-// General io and system-services modules
-
-pub mod net;
-pub mod net_ip;
-pub mod net_tcp;
-pub mod net_url;
-
-// libuv modules
-pub mod uv;
-pub mod uv_iotask;
-pub mod uv_global_loop;
-
-
-// Utility modules
-
-pub mod c_vec;
-pub mod timer;
-pub mod io_util;
-pub mod rc;
-
-// Concurrency
-
-pub mod sync;
-pub mod arc;
-pub mod comm;
-pub mod future;
-pub mod task_pool;
-pub mod flatpipes;
-
-// Collections
-
-pub mod bitv;
-pub mod deque;
-pub mod fun_treemap;
-pub mod list;
-pub mod priority_queue;
-pub mod rope;
-pub mod smallintmap;
-
-pub mod sort;
-
-pub mod dlist;
-pub mod treemap;
-
-// And ... other stuff
-
-pub mod ebml;
-pub mod dbg;
-pub mod getopts;
-pub mod json;
-pub mod sha1;
-pub mod md4;
-pub mod tempfile;
-pub mod term;
-pub mod time;
-pub mod arena;
-pub mod par;
-pub mod base64;
-pub mod rl;
-pub mod workcache;
-#[path="num/bigint.rs"]
-pub mod bigint;
-#[path="num/rational.rs"]
-pub mod rational;
-#[path="num/complex.rs"]
-pub mod complex;
-pub mod stats;
-pub mod semver;
-pub mod fileinput;
-pub mod flate;
-
-#[cfg(unicode)]
-mod unicode;
-
-
-// Compiler support modules
-
-pub mod test;
-pub mod serialize;
-
-// A curious inner-module that's not exported that contains the binding
-// 'std' so that macro-expanded references to std::serialize and such
-// can be resolved within libcore.
-#[doc(hidden)] // FIXME #3538
-pub mod std {
-    pub use serialize;
-    pub use test;
-}
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
new file mode 100644
index 00000000000..53169554ec5
--- /dev/null
+++ b/src/libstd/str.rs
@@ -0,0 +1,4036 @@
+// 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.
+
+/*!
+ * String manipulation
+ *
+ * Strings are a packed UTF-8 representation of text, stored as null
+ * terminated buffers of u8 bytes.  Strings should be indexed in bytes,
+ * for efficiency, but UTF-8 unsafe operations should be avoided.  For
+ * some heavy-duty uses, try std::rope.
+ */
+
+use at_vec;
+use cast::transmute;
+use cast;
+use char;
+use clone::Clone;
+use cmp::{TotalOrd, Ordering, Less, Equal, Greater};
+use container::Container;
+use iter::Times;
+use iterator::Iterator;
+use libc;
+use option::{None, Option, Some};
+use old_iter::{BaseIter, EqIter};
+use ptr;
+use ptr::Ptr;
+use str;
+use to_str::ToStr;
+use uint;
+use vec;
+use vec::{OwnedVector, OwnedCopyableVector};
+
+#[cfg(not(test))] use cmp::{Eq, Ord, Equiv, TotalEq};
+
+/*
+Section: Creating a string
+*/
+
+/**
+ * Convert a vector of bytes to a new UTF-8 string
+ *
+ * # Failure
+ *
+ * Fails if invalid UTF-8
+ */
+pub fn from_bytes(vv: &const [u8]) -> ~str {
+    assert!(is_utf8(vv));
+    return unsafe { raw::from_bytes(vv) };
+}
+
+/**
+ * Convert a vector of bytes to a UTF-8 string.
+ * The vector needs to be one byte longer than the string, and end with a 0 byte.
+ *
+ * Compared to `from_bytes()`, this fn doesn't need to allocate a new owned str.
+ *
+ * # Failure
+ *
+ * Fails if invalid UTF-8
+ * Fails if not null terminated
+ */
+pub fn from_bytes_with_null<'a>(vv: &'a [u8]) -> &'a str {
+    assert_eq!(vv[vv.len() - 1], 0);
+    assert!(is_utf8(vv));
+    return unsafe { raw::from_bytes_with_null(vv) };
+}
+
+pub fn from_bytes_slice<'a>(vector: &'a [u8]) -> &'a str {
+    unsafe {
+        assert!(is_utf8(vector));
+        let (ptr, len): (*u8, uint) = ::cast::transmute(vector);
+        let string: &'a str = ::cast::transmute((ptr, len + 1));
+        string
+    }
+}
+
+/// Copy a slice into a new unique str
+#[inline(always)]
+pub fn to_owned(s: &str) -> ~str {
+    unsafe { raw::slice_bytes_owned(s, 0, len(s)) }
+}
+
+impl ToStr for ~str {
+    #[inline(always)]
+    fn to_str(&self) -> ~str { to_owned(*self) }
+}
+impl<'self> ToStr for &'self str {
+    #[inline(always)]
+    fn to_str(&self) -> ~str { to_owned(*self) }
+}
+impl ToStr for @str {
+    #[inline(always)]
+    fn to_str(&self) -> ~str { to_owned(*self) }
+}
+
+/**
+ * Convert a byte to a UTF-8 string
+ *
+ * # Failure
+ *
+ * Fails if invalid UTF-8
+ */
+pub fn from_byte(b: u8) -> ~str {
+    assert!(b < 128u8);
+    unsafe { ::cast::transmute(~[b, 0u8]) }
+}
+
+/// Appends a character at the end of a string
+pub fn push_char(s: &mut ~str, ch: char) {
+    unsafe {
+        let code = ch as uint;
+        let nb = if code < max_one_b { 1u }
+        else if code < max_two_b { 2u }
+        else if code < max_three_b { 3u }
+        else if code < max_four_b { 4u }
+        else if code < max_five_b { 5u }
+        else { 6u };
+        let len = len(*s);
+        let new_len = len + nb;
+        reserve_at_least(&mut *s, new_len);
+        let off = len;
+        do as_buf(*s) |buf, _len| {
+            let buf: *mut u8 = ::cast::transmute(buf);
+            match nb {
+                1u => {
+                    *ptr::mut_offset(buf, off) = code as u8;
+                }
+                2u => {
+                    *ptr::mut_offset(buf, off) = (code >> 6u & 31u | tag_two_b) as u8;
+                    *ptr::mut_offset(buf, off + 1u) = (code & 63u | tag_cont) as u8;
+                }
+                3u => {
+                    *ptr::mut_offset(buf, off) = (code >> 12u & 15u | tag_three_b) as u8;
+                    *ptr::mut_offset(buf, off + 1u) = (code >> 6u & 63u | tag_cont) as u8;
+                    *ptr::mut_offset(buf, off + 2u) = (code & 63u | tag_cont) as u8;
+                }
+                4u => {
+                    *ptr::mut_offset(buf, off) = (code >> 18u & 7u | tag_four_b) as u8;
+                    *ptr::mut_offset(buf, off + 1u) = (code >> 12u & 63u | tag_cont) as u8;
+                    *ptr::mut_offset(buf, off + 2u) = (code >> 6u & 63u | tag_cont) as u8;
+                    *ptr::mut_offset(buf, off + 3u) = (code & 63u | tag_cont) as u8;
+                }
+                5u => {
+                    *ptr::mut_offset(buf, off) = (code >> 24u & 3u | tag_five_b) as u8;
+                    *ptr::mut_offset(buf, off + 1u) = (code >> 18u & 63u | tag_cont) as u8;
+                    *ptr::mut_offset(buf, off + 2u) = (code >> 12u & 63u | tag_cont) as u8;
+                    *ptr::mut_offset(buf, off + 3u) = (code >> 6u & 63u | tag_cont) as u8;
+                    *ptr::mut_offset(buf, off + 4u) = (code & 63u | tag_cont) as u8;
+                }
+                6u => {
+                    *ptr::mut_offset(buf, off) = (code >> 30u & 1u | tag_six_b) as u8;
+                    *ptr::mut_offset(buf, off + 1u) = (code >> 24u & 63u | tag_cont) as u8;
+                    *ptr::mut_offset(buf, off + 2u) = (code >> 18u & 63u | tag_cont) as u8;
+                    *ptr::mut_offset(buf, off + 3u) = (code >> 12u & 63u | tag_cont) as u8;
+                    *ptr::mut_offset(buf, off + 4u) = (code >> 6u & 63u | tag_cont) as u8;
+                    *ptr::mut_offset(buf, off + 5u) = (code & 63u | tag_cont) as u8;
+                }
+                _ => {}
+            }
+        }
+        raw::set_len(s, new_len);
+    }
+}
+
+/// Convert a char to a string
+pub fn from_char(ch: char) -> ~str {
+    let mut buf = ~"";
+    push_char(&mut buf, ch);
+    buf
+}
+
+/// Convert a vector of chars to a string
+pub fn from_chars(chs: &[char]) -> ~str {
+    let mut buf = ~"";
+    reserve(&mut buf, chs.len());
+    for chs.each |ch| {
+        push_char(&mut buf, *ch);
+    }
+    buf
+}
+
+/// Appends a string slice to the back of a string, without overallocating
+#[inline(always)]
+pub fn push_str_no_overallocate(lhs: &mut ~str, rhs: &str) {
+    unsafe {
+        let llen = lhs.len();
+        let rlen = rhs.len();
+        reserve(&mut *lhs, llen + rlen);
+        do as_buf(*lhs) |lbuf, _llen| {
+            do as_buf(rhs) |rbuf, _rlen| {
+                let dst = ptr::offset(lbuf, llen);
+                let dst = ::cast::transmute_mut_unsafe(dst);
+                ptr::copy_memory(dst, rbuf, rlen);
+            }
+        }
+        raw::set_len(lhs, llen + rlen);
+    }
+}
+
+/// Appends a string slice to the back of a string
+#[inline(always)]
+pub fn push_str(lhs: &mut ~str, rhs: &str) {
+    unsafe {
+        let llen = lhs.len();
+        let rlen = rhs.len();
+        reserve_at_least(&mut *lhs, llen + rlen);
+        do as_buf(*lhs) |lbuf, _llen| {
+            do as_buf(rhs) |rbuf, _rlen| {
+                let dst = ptr::offset(lbuf, llen);
+                let dst = ::cast::transmute_mut_unsafe(dst);
+                ptr::copy_memory(dst, rbuf, rlen);
+            }
+        }
+        raw::set_len(lhs, llen + rlen);
+    }
+}
+
+/// Concatenate two strings together
+#[inline(always)]
+pub fn append(lhs: ~str, rhs: &str) -> ~str {
+    let mut v = lhs;
+    push_str_no_overallocate(&mut v, rhs);
+    v
+}
+
+/// Concatenate a vector of strings
+pub fn concat(v: &[~str]) -> ~str {
+    if v.is_empty() { return ~""; }
+
+    let mut len = 0;
+    for v.each |ss| {
+        len += ss.len();
+    }
+    let mut s = ~"";
+
+    reserve(&mut s, len);
+
+    unsafe {
+        do as_buf(s) |buf, _len| {
+            let mut buf = ::cast::transmute_mut_unsafe(buf);
+            for v.each |ss| {
+                do as_buf(*ss) |ssbuf, sslen| {
+                    let sslen = sslen - 1;
+                    ptr::copy_memory(buf, ssbuf, sslen);
+                    buf = buf.offset(sslen);
+                }
+            }
+        }
+        raw::set_len(&mut s, len);
+    }
+    s
+}
+
+/// Concatenate a vector of strings, placing a given separator between each
+pub fn connect(v: &[~str], sep: &str) -> ~str {
+    if v.is_empty() { return ~""; }
+
+    // concat is faster
+    if sep.is_empty() { return concat(v); }
+
+    // this is wrong without the guarantee that v is non-empty
+    let mut len = sep.len() * (v.len() - 1);
+    for v.each |ss| {
+        len += ss.len();
+    }
+    let mut s = ~"", first = true;
+
+    reserve(&mut s, len);
+
+    unsafe {
+        do as_buf(s) |buf, _len| {
+            do as_buf(sep) |sepbuf, seplen| {
+                let seplen = seplen - 1;
+                let mut buf = ::cast::transmute_mut_unsafe(buf);
+                for v.each |ss| {
+                    do as_buf(*ss) |ssbuf, sslen| {
+                        let sslen = sslen - 1;
+                        if first {
+                            first = false;
+                        } else {
+                            ptr::copy_memory(buf, sepbuf, seplen);
+                            buf = buf.offset(seplen);
+                        }
+                        ptr::copy_memory(buf, ssbuf, sslen);
+                        buf = buf.offset(sslen);
+                    }
+                }
+            }
+        }
+        raw::set_len(&mut s, len);
+    }
+    s
+}
+
+/// Concatenate a vector of strings, placing a given separator between each
+pub fn connect_slices(v: &[&str], sep: &str) -> ~str {
+    if v.is_empty() { return ~""; }
+
+    // this is wrong without the guarantee that v is non-empty
+    let mut len = sep.len() * (v.len() - 1);
+    for v.each |ss| {
+        len += ss.len();
+    }
+    let mut s = ~"", first = true;
+
+    reserve(&mut s, len);
+
+    unsafe {
+        do as_buf(s) |buf, _len| {
+            do as_buf(sep) |sepbuf, seplen| {
+                let seplen = seplen - 1;
+                let mut buf = ::cast::transmute_mut_unsafe(buf);
+                for v.each |ss| {
+                    do as_buf(*ss) |ssbuf, sslen| {
+                        let sslen = sslen - 1;
+                        if first {
+                            first = false;
+                        } else if seplen > 0 {
+                            ptr::copy_memory(buf, sepbuf, seplen);
+                            buf = buf.offset(seplen);
+                        }
+                        ptr::copy_memory(buf, ssbuf, sslen);
+                        buf = buf.offset(sslen);
+                    }
+                }
+            }
+        }
+        raw::set_len(&mut s, len);
+    }
+    s
+}
+
+/// Given a string, make a new string with repeated copies of it
+pub fn repeat(ss: &str, nn: uint) -> ~str {
+    do as_buf(ss) |buf, len| {
+        let mut ret = ~"";
+        // ignore the NULL terminator
+        let len = len - 1;
+        reserve(&mut ret, nn * len);
+
+        unsafe {
+            do as_buf(ret) |rbuf, _len| {
+                let mut rbuf = ::cast::transmute_mut_unsafe(rbuf);
+
+                for nn.times {
+                    ptr::copy_memory(rbuf, buf, len);
+                    rbuf = rbuf.offset(len);
+                }
+            }
+            raw::set_len(&mut ret, nn * len);
+        }
+        ret
+    }
+}
+
+/*
+Section: Adding to and removing from a string
+*/
+
+/**
+ * Remove the final character from a string and return it
+ *
+ * # Failure
+ *
+ * If the string does not contain any characters
+ */
+pub fn pop_char(s: &mut ~str) -> char {
+    let end = len(*s);
+    assert!(end > 0u);
+    let CharRange {ch, next} = char_range_at_reverse(*s, end);
+    unsafe { raw::set_len(s, next); }
+    return ch;
+}
+
+/**
+ * Remove the first character from a string and return it
+ *
+ * # Failure
+ *
+ * If the string does not contain any characters
+ */
+pub fn shift_char(s: &mut ~str) -> char {
+    let CharRange {ch, next} = char_range_at(*s, 0u);
+    *s = unsafe { raw::slice_bytes_owned(*s, next, len(*s)) };
+    return ch;
+}
+
+/**
+ * Removes the first character from a string slice and returns it. This does
+ * not allocate a new string; instead, it mutates a slice to point one
+ * character beyond the character that was shifted.
+ *
+ * # Failure
+ *
+ * If the string does not contain any characters
+ */
+#[inline]
+pub fn slice_shift_char<'a>(s: &'a str) -> (char, &'a str) {
+    let CharRange {ch, next} = char_range_at(s, 0u);
+    let next_s = unsafe { raw::slice_bytes(s, next, len(s)) };
+    return (ch, next_s);
+}
+
+/// Prepend a char to a string
+pub fn unshift_char(s: &mut ~str, ch: char) {
+    // This could be more efficient.
+    let mut new_str = ~"";
+    new_str.push_char(ch);
+    new_str.push_str(*s);
+    *s = new_str;
+}
+
+/**
+ * Returns a string with leading `chars_to_trim` removed.
+ *
+ * # Arguments
+ *
+ * * s - A string
+ * * chars_to_trim - A vector of chars
+ *
+ */
+pub fn trim_left_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str {
+    if chars_to_trim.is_empty() { return s; }
+
+    match find(s, |c| !chars_to_trim.contains(&c)) {
+      None => "",
+      Some(first) => unsafe { raw::slice_bytes(s, first, s.len()) }
+    }
+}
+
+/**
+ * Returns a string with trailing `chars_to_trim` removed.
+ *
+ * # Arguments
+ *
+ * * s - A string
+ * * chars_to_trim - A vector of chars
+ *
+ */
+pub fn trim_right_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str {
+    if chars_to_trim.is_empty() { return s; }
+
+    match rfind(s, |c| !chars_to_trim.contains(&c)) {
+      None => "",
+      Some(last) => {
+        let next = char_range_at(s, last).next;
+        unsafe { raw::slice_bytes(s, 0u, next) }
+      }
+    }
+}
+
+/**
+ * Returns a string with leading and trailing `chars_to_trim` removed.
+ *
+ * # Arguments
+ *
+ * * s - A string
+ * * chars_to_trim - A vector of chars
+ *
+ */
+pub fn trim_chars<'a>(s: &'a str, chars_to_trim: &[char]) -> &'a str {
+    trim_left_chars(trim_right_chars(s, chars_to_trim), chars_to_trim)
+}
+
+/// Returns a string with leading whitespace removed
+pub fn trim_left<'a>(s: &'a str) -> &'a str {
+    match find(s, |c| !char::is_whitespace(c)) {
+      None => "",
+      Some(first) => unsafe { raw::slice_bytes(s, first, len(s)) }
+    }
+}
+
+/// Returns a string with trailing whitespace removed
+pub fn trim_right<'a>(s: &'a str) -> &'a str {
+    match rfind(s, |c| !char::is_whitespace(c)) {
+      None => "",
+      Some(last) => {
+        let next = char_range_at(s, last).next;
+        unsafe { raw::slice_bytes(s, 0u, next) }
+      }
+    }
+}
+
+/// Returns a string with leading and trailing whitespace removed
+pub fn trim<'a>(s: &'a str) -> &'a str { trim_left(trim_right(s)) }
+
+/*
+Section: Transforming strings
+*/
+
+/**
+ * Converts a string to a unique vector of bytes
+ *
+ * The result vector is not null-terminated.
+ */
+pub fn to_bytes(s: &str) -> ~[u8] {
+    unsafe {
+        let mut v: ~[u8] = ::cast::transmute(to_owned(s));
+        vec::raw::set_len(&mut v, len(s));
+        v
+    }
+}
+
+/// Work with the string as a byte slice, not including trailing null.
+#[inline(always)]
+pub fn byte_slice<T>(s: &str, f: &fn(v: &[u8]) -> T) -> T {
+    do as_buf(s) |p,n| {
+        unsafe { vec::raw::buf_as_slice(p, n-1u, f) }
+    }
+}
+
+/// Work with the string as a byte slice, not including trailing null, without
+/// a callback.
+#[inline(always)]
+pub fn byte_slice_no_callback<'a>(s: &'a str) -> &'a [u8] {
+    unsafe {
+        cast::transmute(s)
+    }
+}
+
+/// Convert a string to a unique vector of characters
+pub fn to_chars(s: &str) -> ~[char] {
+    let mut buf = ~[];
+    for each_char(s) |c| {
+        buf.push(c);
+    }
+    buf
+}
+
+/**
+ * Take a substring of another.
+ *
+ * Returns a slice pointing at `n` characters starting from byte offset
+ * `begin`.
+ */
+pub fn substr<'a>(s: &'a str, begin: uint, n: uint) -> &'a str {
+    slice(s, begin, begin + count_bytes(s, begin, n))
+}
+
+/**
+ * Returns a slice of the given string from the byte range [`begin`..`end`)
+ *
+ * Fails when `begin` and `end` do not point to valid characters or beyond
+ * the last character of the string
+ */
+pub fn slice<'a>(s: &'a str, begin: uint, end: uint) -> &'a str {
+    assert!(is_char_boundary(s, begin));
+    assert!(is_char_boundary(s, end));
+    unsafe { raw::slice_bytes(s, begin, end) }
+}
+
+/// Splits a string into substrings at each occurrence of a given character
+pub fn each_split_char<'a>(s: &'a str, sep: char,
+                           it: &fn(&'a str) -> bool) -> bool {
+    each_split_char_inner(s, sep, len(s), true, true, it)
+}
+
+/// Like `each_split_char`, but a trailing empty string is omitted
+pub fn each_split_char_no_trailing<'a>(s: &'a str,
+                                       sep: char,
+                                       it: &fn(&'a str) -> bool) -> bool {
+    each_split_char_inner(s, sep, len(s), true, false, it)
+}
+
+/**
+ * Splits a string into substrings at each occurrence of a given
+ * character up to 'count' times.
+ *
+ * The character must be a valid UTF-8/ASCII character
+ */
+pub fn each_splitn_char<'a>(s: &'a str,
+                            sep: char,
+                            count: uint,
+                            it: &fn(&'a str) -> bool) -> bool {
+    each_split_char_inner(s, sep, count, true, true, it)
+}
+
+/// Like `each_split_char`, but omits empty strings
+pub fn each_split_char_nonempty<'a>(s: &'a str,
+                                    sep: char,
+                                    it: &fn(&'a str) -> bool) -> bool {
+    each_split_char_inner(s, sep, len(s), false, false, it)
+}
+
+fn each_split_char_inner<'a>(s: &'a str,
+                             sep: char,
+                             count: uint,
+                             allow_empty: bool,
+                             allow_trailing_empty: bool,
+                             it: &fn(&'a str) -> bool) -> bool {
+    if sep < 128u as char {
+        let b = sep as u8, l = len(s);
+        let mut done = 0u;
+        let mut i = 0u, start = 0u;
+        while i < l && done < count {
+            if s[i] == b {
+                if allow_empty || start < i {
+                    if !it( unsafe{ raw::slice_bytes(s, start, i) } ) {
+                        return false;
+                    }
+                }
+                start = i + 1u;
+                done += 1u;
+            }
+            i += 1u;
+        }
+        // only slice a non-empty trailing substring
+        if allow_trailing_empty || start < l {
+            if !it( unsafe{ raw::slice_bytes(s, start, l) } ) { return false; }
+        }
+        return true;
+    }
+    return each_split_inner(s, |cur| cur == sep, count,
+                            allow_empty, allow_trailing_empty, it)
+}
+
+/// Splits a string into substrings using a character function
+pub fn each_split<'a>(s: &'a str,
+                      sepfn: &fn(char) -> bool,
+                      it: &fn(&'a str) -> bool) -> bool {
+    each_split_inner(s, sepfn, len(s), true, true, it)
+}
+
+/// Like `each_split`, but a trailing empty string is omitted
+pub fn each_split_no_trailing<'a>(s: &'a str,
+                                  sepfn: &fn(char) -> bool,
+                                  it: &fn(&'a str) -> bool) -> bool {
+    each_split_inner(s, sepfn, len(s), true, false, it)
+}
+
+/**
+ * Splits a string into substrings using a character function, cutting at
+ * most `count` times.
+ */
+pub fn each_splitn<'a>(s: &'a str,
+                       sepfn: &fn(char) -> bool,
+                       count: uint,
+                       it: &fn(&'a str) -> bool) -> bool {
+    each_split_inner(s, sepfn, count, true, true, it)
+}
+
+/// Like `each_split`, but omits empty strings
+pub fn each_split_nonempty<'a>(s: &'a str,
+                               sepfn: &fn(char) -> bool,
+                               it: &fn(&'a str) -> bool) -> bool {
+    each_split_inner(s, sepfn, len(s), false, false, it)
+}
+
+fn each_split_inner<'a>(s: &'a str,
+                        sepfn: &fn(cc: char) -> bool,
+                        count: uint,
+                        allow_empty: bool,
+                        allow_trailing_empty: bool,
+                        it: &fn(&'a str) -> bool) -> bool {
+    let l = len(s);
+    let mut i = 0u, start = 0u, done = 0u;
+    while i < l && done < count {
+        let CharRange {ch, next} = char_range_at(s, i);
+        if sepfn(ch) {
+            if allow_empty || start < i {
+                if !it( unsafe{ raw::slice_bytes(s, start, i) } ) {
+                    return false;
+                }
+            }
+            start = next;
+            done += 1u;
+        }
+        i = next;
+    }
+    if allow_trailing_empty || start < l {
+        if !it( unsafe{ raw::slice_bytes(s, start, l) } ) { return false; }
+    }
+    return true;
+}
+
+// See Issue #1932 for why this is a naive search
+fn iter_matches<'a,'b>(s: &'a str, sep: &'b str,
+                       f: &fn(uint, uint) -> bool) -> bool {
+    let sep_len = len(sep), l = len(s);
+    assert!(sep_len > 0u);
+    let mut i = 0u, match_start = 0u, match_i = 0u;
+
+    while i < l {
+        if s[i] == sep[match_i] {
+            if match_i == 0u { match_start = i; }
+            match_i += 1u;
+            // Found a match
+            if match_i == sep_len {
+                if !f(match_start, i + 1u) { return false; }
+                match_i = 0u;
+            }
+            i += 1u;
+        } else {
+            // Failed match, backtrack
+            if match_i > 0u {
+                match_i = 0u;
+                i = match_start + 1u;
+            } else {
+                i += 1u;
+            }
+        }
+    }
+    return true;
+}
+
+fn iter_between_matches<'a,'b>(s: &'a str,
+                               sep: &'b str,
+                               f: &fn(uint, uint) -> bool) -> bool {
+    let mut last_end = 0u;
+    for iter_matches(s, sep) |from, to| {
+        if !f(last_end, from) { return false; }
+        last_end = to;
+    }
+    return f(last_end, len(s));
+}
+
+/**
+ * Splits a string into a vector of the substrings separated by a given string
+ *
+ * # Example
+ *
+ * ~~~
+ * let mut v = ~[];
+ * for each_split_str(".XXX.YYY.", ".") |subs| { v.push(subs); }
+ * assert!(v == ["", "XXX", "YYY", ""]);
+ * ~~~
+ */
+pub fn each_split_str<'a,'b>(s: &'a str,
+                             sep: &'b str,
+                             it: &fn(&'a str) -> bool) -> bool {
+    for iter_between_matches(s, sep) |from, to| {
+        if !it( unsafe { raw::slice_bytes(s, from, to) } ) { return false; }
+    }
+    return true;
+}
+
+pub fn each_split_str_nonempty<'a,'b>(s: &'a str,
+                                      sep: &'b str,
+                                      it: &fn(&'a str) -> bool) -> bool {
+    for iter_between_matches(s, sep) |from, to| {
+        if to > from {
+            if !it( unsafe { raw::slice_bytes(s, from, to) } ) { return false; }
+        }
+    }
+    return true;
+}
+
+/// Levenshtein Distance between two strings
+pub fn levdistance(s: &str, t: &str) -> uint {
+
+    let slen = s.len();
+    let tlen = t.len();
+
+    if slen == 0 { return tlen; }
+    if tlen == 0 { return slen; }
+
+    let mut dcol = vec::from_fn(tlen + 1, |x| x);
+
+    for s.each_chari |i, sc| {
+
+        let mut current = i;
+        dcol[0] = current + 1;
+
+        for t.each_chari |j, tc| {
+
+            let next = dcol[j + 1];
+
+            if sc == tc {
+                dcol[j + 1] = current;
+            } else {
+                dcol[j + 1] = ::cmp::min(current, next);
+                dcol[j + 1] = ::cmp::min(dcol[j + 1], dcol[j]) + 1;
+            }
+
+            current = next;
+        }
+    }
+
+    return dcol[tlen];
+}
+
+/**
+ * Splits a string into substrings separated by LF ('\n').
+ */
+pub fn each_line<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool {
+    each_split_char_no_trailing(s, '\n', it)
+}
+
+/**
+ * Splits a string into substrings separated by LF ('\n')
+ * and/or CR LF ("\r\n")
+ */
+pub fn each_line_any<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool {
+    for each_line(s) |s| {
+        let l = s.len();
+        if l > 0u && s[l - 1u] == '\r' as u8 {
+            if !it( unsafe { raw::slice_bytes(s, 0, l - 1) } ) { return false; }
+        } else {
+            if !it( s ) { return false; }
+        }
+    }
+    return true;
+}
+
+/// Splits a string into substrings separated by whitespace
+pub fn each_word<'a>(s: &'a str, it: &fn(&'a str) -> bool) -> bool {
+    each_split_nonempty(s, char::is_whitespace, it)
+}
+
+/** Splits a string into substrings with possibly internal whitespace,
+ *  each of them at most `lim` bytes long. The substrings have leading and trailing
+ *  whitespace removed, and are only cut at whitespace boundaries.
+ *
+ *  #Failure:
+ *
+ *  Fails during iteration if the string contains a non-whitespace
+ *  sequence longer than the limit.
+ */
+pub fn _each_split_within<'a>(ss: &'a str,
+                              lim: uint,
+                              it: &fn(&'a str) -> bool) -> bool {
+    // Just for fun, let's write this as an state machine:
+
+    enum SplitWithinState {
+        A,  // leading whitespace, initial state
+        B,  // words
+        C,  // internal and trailing whitespace
+    }
+    enum Whitespace {
+        Ws, // current char is whitespace
+        Cr  // current char is not whitespace
+    }
+    enum LengthLimit {
+        UnderLim, // current char makes current substring still fit in limit
+        OverLim   // current char makes current substring no longer fit in limit
+    }
+
+    let mut slice_start = 0;
+    let mut last_start = 0;
+    let mut last_end = 0;
+    let mut state = A;
+
+    let mut cont = true;
+    let slice: &fn() = || { cont = it(slice(ss, slice_start, last_end)) };
+
+    let machine: &fn(uint, char) -> bool = |i, c| {
+        let whitespace = if char::is_whitespace(c)       { Ws }       else { Cr };
+        let limit      = if (i - slice_start + 1) <= lim { UnderLim } else { OverLim };
+
+        state = match (state, whitespace, limit) {
+            (A, Ws, _)        => { A }
+            (A, Cr, _)        => { slice_start = i; last_start = i; B }
+
+            (B, Cr, UnderLim) => { B }
+            (B, Cr, OverLim)  if (i - last_start + 1) > lim
+                              => fail!("word starting with %? longer than limit!",
+                                       self::slice(ss, last_start, i + 1)),
+            (B, Cr, OverLim)  => { slice(); slice_start = last_start; B }
+            (B, Ws, UnderLim) => { last_end = i; C }
+            (B, Ws, OverLim)  => { last_end = i; slice(); A }
+
+            (C, Cr, UnderLim) => { last_start = i; B }
+            (C, Cr, OverLim)  => { slice(); slice_start = i; last_start = i; last_end = i; B }
+            (C, Ws, OverLim)  => { slice(); A }
+            (C, Ws, UnderLim) => { C }
+        };
+
+        cont
+    };
+
+    str::each_chari(ss, machine);
+
+    // Let the automaton 'run out' by supplying trailing whitespace
+    let mut fake_i = ss.len();
+    while cont && match state { B | C => true, A => false } {
+        machine(fake_i, ' ');
+        fake_i += 1;
+    }
+    return cont;
+}
+
+pub fn each_split_within<'a>(ss: &'a str,
+                             lim: uint,
+                             it: &fn(&'a str) -> bool) -> bool {
+    _each_split_within(ss, lim, it)
+}
+
+/**
+ * Replace all occurrences of one string with another
+ *
+ * # Arguments
+ *
+ * * s - The string containing substrings to replace
+ * * from - The string to replace
+ * * to - The replacement string
+ *
+ * # Return value
+ *
+ * The original string with all occurances of `from` replaced with `to`
+ */
+pub fn replace(s: &str, from: &str, to: &str) -> ~str {
+    let mut result = ~"", first = true;
+    for iter_between_matches(s, from) |start, end| {
+        if first {
+            first = false;
+        } else {
+            push_str(&mut result, to);
+        }
+        push_str(&mut result, unsafe{raw::slice_bytes(s, start, end)});
+    }
+    result
+}
+
+/*
+Section: Comparing strings
+*/
+
+/// Bytewise slice equality
+#[cfg(not(test))]
+#[lang="str_eq"]
+#[inline]
+pub fn eq_slice(a: &str, b: &str) -> bool {
+    do as_buf(a) |ap, alen| {
+        do as_buf(b) |bp, blen| {
+            if (alen != blen) { false }
+            else {
+                unsafe {
+                    libc::memcmp(ap as *libc::c_void,
+                                 bp as *libc::c_void,
+                                 (alen - 1) as libc::size_t) == 0
+                }
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+#[inline]
+pub fn eq_slice(a: &str, b: &str) -> bool {
+    do as_buf(a) |ap, alen| {
+        do as_buf(b) |bp, blen| {
+            if (alen != blen) { false }
+            else {
+                unsafe {
+                    libc::memcmp(ap as *libc::c_void,
+                                 bp as *libc::c_void,
+                                 (alen - 1) as libc::size_t) == 0
+                }
+            }
+        }
+    }
+}
+
+/// Bytewise string equality
+#[cfg(not(test))]
+#[lang="uniq_str_eq"]
+#[inline]
+pub fn eq(a: &~str, b: &~str) -> bool {
+    eq_slice(*a, *b)
+}
+
+#[cfg(test)]
+#[inline]
+pub fn eq(a: &~str, b: &~str) -> bool {
+    eq_slice(*a, *b)
+}
+
+#[inline]
+fn cmp(a: &str, b: &str) -> Ordering {
+    let low = uint::min(a.len(), b.len());
+
+    for uint::range(0, low) |idx| {
+        match a[idx].cmp(&b[idx]) {
+          Greater => return Greater,
+          Less => return Less,
+          Equal => ()
+        }
+    }
+
+    a.len().cmp(&b.len())
+}
+
+#[cfg(not(test))]
+impl<'self> TotalOrd for &'self str {
+    #[inline]
+    fn cmp(&self, other: & &'self str) -> Ordering { cmp(*self, *other) }
+}
+
+#[cfg(not(test))]
+impl TotalOrd for ~str {
+    #[inline]
+    fn cmp(&self, other: &~str) -> Ordering { cmp(*self, *other) }
+}
+
+#[cfg(not(test))]
+impl TotalOrd for @str {
+    #[inline]
+    fn cmp(&self, other: &@str) -> Ordering { cmp(*self, *other) }
+}
+
+/// Bytewise slice less than
+#[inline]
+fn lt(a: &str, b: &str) -> bool {
+    let (a_len, b_len) = (a.len(), b.len());
+    let end = uint::min(a_len, b_len);
+
+    let mut i = 0;
+    while i < end {
+        let (c_a, c_b) = (a[i], b[i]);
+        if c_a < c_b { return true; }
+        if c_a > c_b { return false; }
+        i += 1;
+    }
+
+    return a_len < b_len;
+}
+
+/// Bytewise less than or equal
+#[inline]
+pub fn le(a: &str, b: &str) -> bool {
+    !lt(b, a)
+}
+
+/// Bytewise greater than or equal
+#[inline]
+fn ge(a: &str, b: &str) -> bool {
+    !lt(a, b)
+}
+
+/// Bytewise greater than
+#[inline]
+fn gt(a: &str, b: &str) -> bool {
+    !le(a, b)
+}
+
+#[cfg(not(test))]
+impl<'self> Eq for &'self str {
+    #[inline(always)]
+    fn eq(&self, other: & &'self str) -> bool {
+        eq_slice((*self), (*other))
+    }
+    #[inline(always)]
+    fn ne(&self, other: & &'self str) -> bool { !(*self).eq(other) }
+}
+
+#[cfg(not(test))]
+impl Eq for ~str {
+    #[inline(always)]
+    fn eq(&self, other: &~str) -> bool {
+        eq_slice((*self), (*other))
+    }
+    #[inline(always)]
+    fn ne(&self, other: &~str) -> bool { !(*self).eq(other) }
+}
+
+#[cfg(not(test))]
+impl Eq for @str {
+    #[inline(always)]
+    fn eq(&self, other: &@str) -> bool {
+        eq_slice((*self), (*other))
+    }
+    #[inline(always)]
+    fn ne(&self, other: &@str) -> bool { !(*self).eq(other) }
+}
+
+#[cfg(not(test))]
+impl<'self> TotalEq for &'self str {
+    #[inline(always)]
+    fn equals(&self, other: & &'self str) -> bool {
+        eq_slice((*self), (*other))
+    }
+}
+
+#[cfg(not(test))]
+impl TotalEq for ~str {
+    #[inline(always)]
+    fn equals(&self, other: &~str) -> bool {
+        eq_slice((*self), (*other))
+    }
+}
+
+#[cfg(not(test))]
+impl TotalEq for @str {
+    #[inline(always)]
+    fn equals(&self, other: &@str) -> bool {
+        eq_slice((*self), (*other))
+    }
+}
+
+#[cfg(not(test))]
+impl Ord for ~str {
+    #[inline(always)]
+    fn lt(&self, other: &~str) -> bool { lt((*self), (*other)) }
+    #[inline(always)]
+    fn le(&self, other: &~str) -> bool { le((*self), (*other)) }
+    #[inline(always)]
+    fn ge(&self, other: &~str) -> bool { ge((*self), (*other)) }
+    #[inline(always)]
+    fn gt(&self, other: &~str) -> bool { gt((*self), (*other)) }
+}
+
+#[cfg(not(test))]
+impl<'self> Ord for &'self str {
+    #[inline(always)]
+    fn lt(&self, other: & &'self str) -> bool { lt((*self), (*other)) }
+    #[inline(always)]
+    fn le(&self, other: & &'self str) -> bool { le((*self), (*other)) }
+    #[inline(always)]
+    fn ge(&self, other: & &'self str) -> bool { ge((*self), (*other)) }
+    #[inline(always)]
+    fn gt(&self, other: & &'self str) -> bool { gt((*self), (*other)) }
+}
+
+#[cfg(not(test))]
+impl Ord for @str {
+    #[inline(always)]
+    fn lt(&self, other: &@str) -> bool { lt((*self), (*other)) }
+    #[inline(always)]
+    fn le(&self, other: &@str) -> bool { le((*self), (*other)) }
+    #[inline(always)]
+    fn ge(&self, other: &@str) -> bool { ge((*self), (*other)) }
+    #[inline(always)]
+    fn gt(&self, other: &@str) -> bool { gt((*self), (*other)) }
+}
+
+#[cfg(not(test))]
+impl<'self> Equiv<~str> for &'self str {
+    #[inline(always)]
+    fn equiv(&self, other: &~str) -> bool { eq_slice(*self, *other) }
+}
+
+/*
+Section: Iterating through strings
+*/
+
+/**
+ * Return true if a predicate matches all characters or if the string
+ * contains no characters
+ */
+pub fn all(s: &str, it: &fn(char) -> bool) -> bool {
+    all_between(s, 0u, len(s), it)
+}
+
+/**
+ * Return true if a predicate matches any character (and false if it
+ * matches none or there are no characters)
+ */
+pub fn any(ss: &str, pred: &fn(char) -> bool) -> bool {
+    !all(ss, |cc| !pred(cc))
+}
+
+/// Apply a function to each character
+pub fn map(ss: &str, ff: &fn(char) -> char) -> ~str {
+    let mut result = ~"";
+    reserve(&mut result, len(ss));
+    for ss.each_char |cc| {
+        str::push_char(&mut result, ff(cc));
+    }
+    result
+}
+
+/// Iterate over the bytes in a string
+#[inline(always)]
+pub fn each(s: &str, it: &fn(u8) -> bool) -> bool {
+    eachi(s, |_i, b| it(b))
+}
+
+/// Iterate over the bytes in a string, with indices
+#[inline(always)]
+pub fn eachi(s: &str, it: &fn(uint, u8) -> bool) -> bool {
+    let mut pos = 0;
+    let len = s.len();
+
+    while pos < len {
+        if !it(pos, s[pos]) { return false; }
+        pos += 1;
+    }
+    return true;
+}
+
+/// Iterate over the bytes in a string in reverse
+#[inline(always)]
+pub fn each_reverse(s: &str, it: &fn(u8) -> bool) -> bool {
+    eachi_reverse(s, |_i, b| it(b) )
+}
+
+/// Iterate over the bytes in a string in reverse, with indices
+#[inline(always)]
+pub fn eachi_reverse(s: &str, it: &fn(uint, u8) -> bool) -> bool {
+    let mut pos = s.len();
+    while pos > 0 {
+        pos -= 1;
+        if !it(pos, s[pos]) { return false; }
+    }
+    return true;
+}
+
+/// Iterate over each char of a string, without allocating
+#[inline(always)]
+pub fn each_char(s: &str, it: &fn(char) -> bool) -> bool {
+    let mut i = 0;
+    let len = len(s);
+    while i < len {
+        let CharRange {ch, next} = char_range_at(s, i);
+        if !it(ch) { return false; }
+        i = next;
+    }
+    return true;
+}
+
+/// Iterates over the chars in a string, with indices
+#[inline(always)]
+pub fn each_chari(s: &str, it: &fn(uint, char) -> bool) -> bool {
+    let mut pos = 0;
+    let mut ch_pos = 0u;
+    let len = s.len();
+    while pos < len {
+        let CharRange {ch, next} = char_range_at(s, pos);
+        pos = next;
+        if !it(ch_pos, ch) { return false; }
+        ch_pos += 1u;
+    }
+    return true;
+}
+
+/// Iterates over the chars in a string in reverse
+#[inline(always)]
+pub fn each_char_reverse(s: &str, it: &fn(char) -> bool) -> bool {
+    each_chari_reverse(s, |_, c| it(c))
+}
+
+// Iterates over the chars in a string in reverse, with indices
+#[inline(always)]
+pub fn each_chari_reverse(s: &str, it: &fn(uint, char) -> bool) -> bool {
+    let mut pos = s.len();
+    let mut ch_pos = s.char_len();
+    while pos > 0 {
+        let CharRange {ch, next} = char_range_at_reverse(s, pos);
+        pos = next;
+        ch_pos -= 1;
+
+        if !it(ch_pos, ch) { return false; }
+    }
+    return true;
+}
+
+/*
+Section: Searching
+*/
+
+/**
+ * Returns the byte index of the first matching character
+ *
+ * # Arguments
+ *
+ * * `s` - The string to search
+ * * `c` - The character to search for
+ *
+ * # Return value
+ *
+ * An `option` containing the byte index of the first matching character
+ * or `none` if there is no match
+ */
+pub fn find_char(s: &str, c: char) -> Option<uint> {
+    find_char_between(s, c, 0u, len(s))
+}
+
+/**
+ * Returns the byte index of the first matching character beginning
+ * from a given byte offset
+ *
+ * # Arguments
+ *
+ * * `s` - The string to search
+ * * `c` - The character to search for
+ * * `start` - The byte index to begin searching at, inclusive
+ *
+ * # Return value
+ *
+ * An `option` containing the byte index of the first matching character
+ * or `none` if there is no match
+ *
+ * # Failure
+ *
+ * `start` must be less than or equal to `len(s)`. `start` must be the
+ * index of a character boundary, as defined by `is_char_boundary`.
+ */
+pub fn find_char_from(s: &str, c: char, start: uint) -> Option<uint> {
+    find_char_between(s, c, start, len(s))
+}
+
+/**
+ * Returns the byte index of the first matching character within a given range
+ *
+ * # Arguments
+ *
+ * * `s` - The string to search
+ * * `c` - The character to search for
+ * * `start` - The byte index to begin searching at, inclusive
+ * * `end` - The byte index to end searching at, exclusive
+ *
+ * # Return value
+ *
+ * An `option` containing the byte index of the first matching character
+ * or `none` if there is no match
+ *
+ * # Failure
+ *
+ * `start` must be less than or equal to `end` and `end` must be less than
+ * or equal to `len(s)`. `start` must be the index of a character boundary,
+ * as defined by `is_char_boundary`.
+ */
+pub fn find_char_between(s: &str, c: char, start: uint, end: uint)
+    -> Option<uint> {
+    if c < 128u as char {
+        assert!(start <= end);
+        assert!(end <= len(s));
+        let mut i = start;
+        let b = c as u8;
+        while i < end {
+            if s[i] == b { return Some(i); }
+            i += 1u;
+        }
+        return None;
+    } else {
+        find_between(s, start, end, |x| x == c)
+    }
+}
+
+/**
+ * Returns the byte index of the last matching character
+ *
+ * # Arguments
+ *
+ * * `s` - The string to search
+ * * `c` - The character to search for
+ *
+ * # Return value
+ *
+ * An `option` containing the byte index of the last matching character
+ * or `none` if there is no match
+ */
+pub fn rfind_char(s: &str, c: char) -> Option<uint> {
+    rfind_char_between(s, c, len(s), 0u)
+}
+
+/**
+ * Returns the byte index of the last matching character beginning
+ * from a given byte offset
+ *
+ * # Arguments
+ *
+ * * `s` - The string to search
+ * * `c` - The character to search for
+ * * `start` - The byte index to begin searching at, exclusive
+ *
+ * # Return value
+ *
+ * An `option` containing the byte index of the last matching character
+ * or `none` if there is no match
+ *
+ * # Failure
+ *
+ * `start` must be less than or equal to `len(s)`. `start` must be
+ * the index of a character boundary, as defined by `is_char_boundary`.
+ */
+pub fn rfind_char_from(s: &str, c: char, start: uint) -> Option<uint> {
+    rfind_char_between(s, c, start, 0u)
+}
+
+/**
+ * Returns the byte index of the last matching character within a given range
+ *
+ * # Arguments
+ *
+ * * `s` - The string to search
+ * * `c` - The character to search for
+ * * `start` - The byte index to begin searching at, exclusive
+ * * `end` - The byte index to end searching at, inclusive
+ *
+ * # Return value
+ *
+ * An `option` containing the byte index of the last matching character
+ * or `none` if there is no match
+ *
+ * # Failure
+ *
+ * `end` must be less than or equal to `start` and `start` must be less than
+ * or equal to `len(s)`. `start` must be the index of a character boundary,
+ * as defined by `is_char_boundary`.
+ */
+pub fn rfind_char_between(s: &str, c: char, start: uint, end: uint) -> Option<uint> {
+    if c < 128u as char {
+        assert!(start >= end);
+        assert!(start <= len(s));
+        let mut i = start;
+        let b = c as u8;
+        while i > end {
+            i -= 1u;
+            if s[i] == b { return Some(i); }
+        }
+        return None;
+    } else {
+        rfind_between(s, start, end, |x| x == c)
+    }
+}
+
+/**
+ * Returns the byte index of the first character that satisfies
+ * the given predicate
+ *
+ * # Arguments
+ *
+ * * `s` - The string to search
+ * * `f` - The predicate to satisfy
+ *
+ * # Return value
+ *
+ * An `option` containing the byte index of the first matching character
+ * or `none` if there is no match
+ */
+pub fn find(s: &str, f: &fn(char) -> bool) -> Option<uint> {
+    find_between(s, 0u, len(s), f)
+}
+
+/**
+ * Returns the byte index of the first character that satisfies
+ * the given predicate, beginning from a given byte offset
+ *
+ * # Arguments
+ *
+ * * `s` - The string to search
+ * * `start` - The byte index to begin searching at, inclusive
+ * * `f` - The predicate to satisfy
+ *
+ * # Return value
+ *
+ * An `option` containing the byte index of the first matching charactor
+ * or `none` if there is no match
+ *
+ * # Failure
+ *
+ * `start` must be less than or equal to `len(s)`. `start` must be the
+ * index of a character boundary, as defined by `is_char_boundary`.
+ */
+pub fn find_from(s: &str, start: uint, f: &fn(char)
+    -> bool) -> Option<uint> {
+    find_between(s, start, len(s), f)
+}
+
+/**
+ * Returns the byte index of the first character that satisfies
+ * the given predicate, within a given range
+ *
+ * # Arguments
+ *
+ * * `s` - The string to search
+ * * `start` - The byte index to begin searching at, inclusive
+ * * `end` - The byte index to end searching at, exclusive
+ * * `f` - The predicate to satisfy
+ *
+ * # Return value
+ *
+ * An `option` containing the byte index of the first matching character
+ * or `none` if there is no match
+ *
+ * # Failure
+ *
+ * `start` must be less than or equal to `end` and `end` must be less than
+ * or equal to `len(s)`. `start` must be the index of a character
+ * boundary, as defined by `is_char_boundary`.
+ */
+pub fn find_between(s: &str, start: uint, end: uint, f: &fn(char) -> bool) -> Option<uint> {
+    assert!(start <= end);
+    assert!(end <= len(s));
+    assert!(is_char_boundary(s, start));
+    let mut i = start;
+    while i < end {
+        let CharRange {ch, next} = char_range_at(s, i);
+        if f(ch) { return Some(i); }
+        i = next;
+    }
+    return None;
+}
+
+/**
+ * Returns the byte index of the last character that satisfies
+ * the given predicate
+ *
+ * # Arguments
+ *
+ * * `s` - The string to search
+ * * `f` - The predicate to satisfy
+ *
+ * # Return value
+ *
+ * An option containing the byte index of the last matching character
+ * or `none` if there is no match
+ */
+pub fn rfind(s: &str, f: &fn(char) -> bool) -> Option<uint> {
+    rfind_between(s, len(s), 0u, f)
+}
+
+/**
+ * Returns the byte index of the last character that satisfies
+ * the given predicate, beginning from a given byte offset
+ *
+ * # Arguments
+ *
+ * * `s` - The string to search
+ * * `start` - The byte index to begin searching at, exclusive
+ * * `f` - The predicate to satisfy
+ *
+ * # Return value
+ *
+ * An `option` containing the byte index of the last matching character
+ * or `none` if there is no match
+ *
+ * # Failure
+ *
+ * `start` must be less than or equal to `len(s)', `start` must be the
+ * index of a character boundary, as defined by `is_char_boundary`
+ */
+pub fn rfind_from(s: &str, start: uint, f: &fn(char) -> bool) -> Option<uint> {
+    rfind_between(s, start, 0u, f)
+}
+
+/**
+ * Returns the byte index of the last character that satisfies
+ * the given predicate, within a given range
+ *
+ * # Arguments
+ *
+ * * `s` - The string to search
+ * * `start` - The byte index to begin searching at, exclusive
+ * * `end` - The byte index to end searching at, inclusive
+ * * `f` - The predicate to satisfy
+ *
+ * # Return value
+ *
+ * An `option` containing the byte index of the last matching character
+ * or `none` if there is no match
+ *
+ * # Failure
+ *
+ * `end` must be less than or equal to `start` and `start` must be less
+ * than or equal to `len(s)`. `start` must be the index of a character
+ * boundary, as defined by `is_char_boundary`
+ */
+pub fn rfind_between(s: &str, start: uint, end: uint, f: &fn(char) -> bool) -> Option<uint> {
+    assert!(start >= end);
+    assert!(start <= len(s));
+    assert!(is_char_boundary(s, start));
+    let mut i = start;
+    while i > end {
+        let CharRange {ch, next: prev} = char_range_at_reverse(s, i);
+        if f(ch) { return Some(prev); }
+        i = prev;
+    }
+    return None;
+}
+
+// Utility used by various searching functions
+fn match_at<'a,'b>(haystack: &'a str, needle: &'b str, at: uint) -> bool {
+    let mut i = at;
+    for each(needle) |c| { if haystack[i] != c { return false; } i += 1u; }
+    return true;
+}
+
+/**
+ * Returns the byte index of the first matching substring
+ *
+ * # Arguments
+ *
+ * * `haystack` - The string to search
+ * * `needle` - The string to search for
+ *
+ * # Return value
+ *
+ * An `option` containing the byte index of the first matching substring
+ * or `none` if there is no match
+ */
+pub fn find_str<'a,'b>(haystack: &'a str, needle: &'b str) -> Option<uint> {
+    find_str_between(haystack, needle, 0u, len(haystack))
+}
+
+/**
+ * Returns the byte index of the first matching substring beginning
+ * from a given byte offset
+ *
+ * # Arguments
+ *
+ * * `haystack` - The string to search
+ * * `needle` - The string to search for
+ * * `start` - The byte index to begin searching at, inclusive
+ *
+ * # Return value
+ *
+ * An `option` containing the byte index of the last matching character
+ * or `none` if there is no match
+ *
+ * # Failure
+ *
+ * `start` must be less than or equal to `len(s)`
+ */
+pub fn find_str_from<'a,'b>(haystack: &'a str,
+                            needle: &'b str,
+                            start: uint)
+                         -> Option<uint> {
+    find_str_between(haystack, needle, start, len(haystack))
+}
+
+/**
+ * Returns the byte index of the first matching substring within a given range
+ *
+ * # Arguments
+ *
+ * * `haystack` - The string to search
+ * * `needle` - The string to search for
+ * * `start` - The byte index to begin searching at, inclusive
+ * * `end` - The byte index to end searching at, exclusive
+ *
+ * # Return value
+ *
+ * An `option` containing the byte index of the first matching character
+ * or `none` if there is no match
+ *
+ * # Failure
+ *
+ * `start` must be less than or equal to `end` and `end` must be less than
+ * or equal to `len(s)`.
+ */
+pub fn find_str_between<'a,'b>(haystack: &'a str,
+                               needle: &'b str,
+                               start: uint,
+                               end:uint)
+                            -> Option<uint> {
+    // See Issue #1932 for why this is a naive search
+    assert!(end <= len(haystack));
+    let needle_len = len(needle);
+    if needle_len == 0u { return Some(start); }
+    if needle_len > end { return None; }
+
+    let mut i = start;
+    let e = end - needle_len;
+    while i <= e {
+        if match_at(haystack, needle, i) { return Some(i); }
+        i += 1u;
+    }
+    return None;
+}
+
+/**
+ * Returns true if one string contains another
+ *
+ * # Arguments
+ *
+ * * haystack - The string to look in
+ * * needle - The string to look for
+ */
+pub fn contains<'a,'b>(haystack: &'a str, needle: &'b str) -> bool {
+    find_str(haystack, needle).is_some()
+}
+
+/**
+ * Returns true if a string contains a char.
+ *
+ * # Arguments
+ *
+ * * haystack - The string to look in
+ * * needle - The char to look for
+ */
+pub fn contains_char(haystack: &str, needle: char) -> bool {
+    find_char(haystack, needle).is_some()
+}
+
+/**
+ * Returns true if one string starts with another
+ *
+ * # Arguments
+ *
+ * * haystack - The string to look in
+ * * needle - The string to look for
+ */
+pub fn starts_with<'a,'b>(haystack: &'a str, needle: &'b str) -> bool {
+    let haystack_len = len(haystack), needle_len = len(needle);
+    if needle_len == 0u { true }
+    else if needle_len > haystack_len { false }
+    else { match_at(haystack, needle, 0u) }
+}
+
+/**
+ * Returns true if one string ends with another
+ *
+ * # Arguments
+ *
+ * * haystack - The string to look in
+ * * needle - The string to look for
+ */
+pub fn ends_with<'a,'b>(haystack: &'a str, needle: &'b str) -> bool {
+    let haystack_len = len(haystack), needle_len = len(needle);
+    if needle_len == 0u { true }
+    else if needle_len > haystack_len { false }
+    else { match_at(haystack, needle, haystack_len - needle_len) }
+}
+
+/*
+Section: String properties
+*/
+
+/// Returns true if the string has length 0
+#[inline(always)]
+pub fn is_empty(s: &str) -> bool { len(s) == 0u }
+
+/**
+ * Returns true if the string contains only whitespace
+ *
+ * Whitespace characters are determined by `char::is_whitespace`
+ */
+pub fn is_whitespace(s: &str) -> bool {
+    return all(s, char::is_whitespace);
+}
+
+/**
+ * Returns true if the string contains only alphanumerics
+ *
+ * Alphanumeric characters are determined by `char::is_alphanumeric`
+ */
+fn is_alphanumeric(s: &str) -> bool {
+    return all(s, char::is_alphanumeric);
+}
+
+/// Returns the string length/size in bytes not counting the null terminator
+#[inline(always)]
+pub fn len(s: &str) -> uint {
+    do as_buf(s) |_p, n| { n - 1u }
+}
+
+/// Returns the number of characters that a string holds
+#[inline(always)]
+pub fn char_len(s: &str) -> uint { count_chars(s, 0u, len(s)) }
+
+/*
+Section: Misc
+*/
+
+/// Determines if a vector of bytes contains valid UTF-8
+pub fn is_utf8(v: &const [u8]) -> bool {
+    let mut i = 0u;
+    let total = vec::len::<u8>(v);
+    while i < total {
+        let mut chsize = utf8_char_width(v[i]);
+        if chsize == 0u { return false; }
+        if i + chsize > total { return false; }
+        i += 1u;
+        while chsize > 1u {
+            if v[i] & 192u8 != tag_cont_u8 { return false; }
+            i += 1u;
+            chsize -= 1u;
+        }
+    }
+    return true;
+}
+
+/// Determines if a vector of `u16` contains valid UTF-16
+pub fn is_utf16(v: &[u16]) -> bool {
+    let len = v.len();
+    let mut i = 0u;
+    while (i < len) {
+        let u = v[i];
+
+        if  u <= 0xD7FF_u16 || u >= 0xE000_u16 {
+            i += 1u;
+
+        } else {
+            if i+1u < len { return false; }
+            let u2 = v[i+1u];
+            if u < 0xD7FF_u16 || u > 0xDBFF_u16 { return false; }
+            if u2 < 0xDC00_u16 || u2 > 0xDFFF_u16 { return false; }
+            i += 2u;
+        }
+    }
+    return true;
+}
+
+/// Converts to a vector of `u16` encoded as UTF-16
+pub fn to_utf16(s: &str) -> ~[u16] {
+    let mut u = ~[];
+    for s.each_char |ch| {
+        // Arithmetic with u32 literals is easier on the eyes than chars.
+        let mut ch = ch as u32;
+
+        if (ch & 0xFFFF_u32) == ch {
+            // The BMP falls through (assuming non-surrogate, as it
+            // should)
+            assert!(ch <= 0xD7FF_u32 || ch >= 0xE000_u32);
+            u.push(ch as u16)
+        } else {
+            // Supplementary planes break into surrogates.
+            assert!(ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32);
+            ch -= 0x1_0000_u32;
+            let w1 = 0xD800_u16 | ((ch >> 10) as u16);
+            let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16);
+            u.push_all([w1, w2])
+        }
+    }
+    u
+}
+
+pub fn utf16_chars(v: &[u16], f: &fn(char)) {
+    let len = v.len();
+    let mut i = 0u;
+    while (i < len && v[i] != 0u16) {
+        let u = v[i];
+
+        if  u <= 0xD7FF_u16 || u >= 0xE000_u16 {
+            f(u as char);
+            i += 1u;
+
+        } else {
+            let u2 = v[i+1u];
+            assert!(u >= 0xD800_u16 && u <= 0xDBFF_u16);
+            assert!(u2 >= 0xDC00_u16 && u2 <= 0xDFFF_u16);
+            let mut c = (u - 0xD800_u16) as char;
+            c = c << 10;
+            c |= (u2 - 0xDC00_u16) as char;
+            c |= 0x1_0000_u32 as char;
+            f(c);
+            i += 2u;
+        }
+    }
+}
+
+pub fn from_utf16(v: &[u16]) -> ~str {
+    let mut buf = ~"";
+    reserve(&mut buf, v.len());
+    utf16_chars(v, |ch| push_char(&mut buf, ch));
+    buf
+}
+
+pub fn with_capacity(capacity: uint) -> ~str {
+    let mut buf = ~"";
+    reserve(&mut buf, capacity);
+    buf
+}
+
+/**
+ * As char_len but for a slice of a string
+ *
+ * # Arguments
+ *
+ * * s - A valid string
+ * * start - The position inside `s` where to start counting in bytes
+ * * end - The position where to stop counting
+ *
+ * # Return value
+ *
+ * The number of Unicode characters in `s` between the given indices.
+ */
+pub fn count_chars(s: &str, start: uint, end: uint) -> uint {
+    assert!(is_char_boundary(s, start));
+    assert!(is_char_boundary(s, end));
+    let mut i = start, len = 0u;
+    while i < end {
+        let next = char_range_at(s, i).next;
+        len += 1u;
+        i = next;
+    }
+    return len;
+}
+
+/// Counts the number of bytes taken by the first `n` chars in `s`
+/// starting from `start`.
+pub fn count_bytes<'b>(s: &'b str, start: uint, n: uint) -> uint {
+    assert!(is_char_boundary(s, start));
+    let mut end = start, cnt = n;
+    let l = len(s);
+    while cnt > 0u {
+        assert!(end < l);
+        let next = char_range_at(s, end).next;
+        cnt -= 1u;
+        end = next;
+    }
+    end - start
+}
+
+/// Given a first byte, determine how many bytes are in this UTF-8 character
+pub fn utf8_char_width(b: u8) -> uint {
+    let byte: uint = b as uint;
+    if byte < 128u { return 1u; }
+    // Not a valid start byte
+    if byte < 192u { return 0u; }
+    if byte < 224u { return 2u; }
+    if byte < 240u { return 3u; }
+    if byte < 248u { return 4u; }
+    if byte < 252u { return 5u; }
+    return 6u;
+}
+
+/**
+ * Returns false if the index points into the middle of a multi-byte
+ * character sequence.
+ */
+pub fn is_char_boundary(s: &str, index: uint) -> bool {
+    if index == len(s) { return true; }
+    let b = s[index];
+    return b < 128u8 || b >= 192u8;
+}
+
+/**
+ * Pluck a character out of a string and return the index of the next
+ * character.
+ *
+ * This function can be used to iterate over the unicode characters of a
+ * string.
+ *
+ * # Example
+ *
+ * ~~~
+ * let s = "中华Việt Nam";
+ * let i = 0u;
+ * while i < str::len(s) {
+ *     let CharRange {ch, next} = str::char_range_at(s, i);
+ *     std::io::println(fmt!("%u: %c",i,ch));
+ *     i = next;
+ * }
+ * ~~~
+ *
+ * # Example output
+ *
+ * ~~~
+ * 0: 中
+ * 3: 华
+ * 6: V
+ * 7: i
+ * 8: ệ
+ * 11: t
+ * 12:
+ * 13: N
+ * 14: a
+ * 15: m
+ * ~~~
+ *
+ * # Arguments
+ *
+ * * s - The string
+ * * i - The byte offset of the char to extract
+ *
+ * # Return value
+ *
+ * A record {ch: char, next: uint} containing the char value and the byte
+ * index of the next unicode character.
+ *
+ * # Failure
+ *
+ * If `i` is greater than or equal to the length of the string.
+ * If `i` is not the index of the beginning of a valid UTF-8 character.
+ */
+pub fn char_range_at(s: &str, i: uint) -> CharRange {
+    let b0 = s[i];
+    let w = utf8_char_width(b0);
+    assert!((w != 0u));
+    if w == 1u { return CharRange {ch: b0 as char, next: i + 1u}; }
+    let mut val = 0u;
+    let end = i + w;
+    let mut i = i + 1u;
+    while i < end {
+        let byte = s[i];
+        assert_eq!(byte & 192u8, tag_cont_u8);
+        val <<= 6u;
+        val += (byte & 63u8) as uint;
+        i += 1u;
+    }
+    // Clunky way to get the right bits from the first byte. Uses two shifts,
+    // the first to clip off the marker bits at the left of the byte, and then
+    // a second (as uint) to get it to the right position.
+    val += ((b0 << ((w + 1u) as u8)) as uint) << ((w - 1u) * 6u - w - 1u);
+    return CharRange {ch: val as char, next: i};
+}
+
+/// Plucks the character starting at the `i`th byte of a string
+pub fn char_at(s: &str, i: uint) -> char {
+    return char_range_at(s, i).ch;
+}
+
+pub struct CharRange {
+    ch: char,
+    next: uint
+}
+
+/**
+ * Given a byte position and a str, return the previous char and its position.
+ *
+ * This function can be used to iterate over a unicode string in reverse.
+ *
+ * Returns 0 for next index if called on start index 0.
+ */
+pub fn char_range_at_reverse(ss: &str, start: uint) -> CharRange {
+    let mut prev = start;
+
+    // while there is a previous byte == 10......
+    while prev > 0u && ss[prev - 1u] & 192u8 == tag_cont_u8 {
+        prev -= 1u;
+    }
+
+    // now refer to the initial byte of previous char
+    if prev > 0u {
+        prev -= 1u;
+    } else {
+        prev = 0u;
+    }
+
+
+    let ch = char_at(ss, prev);
+    return CharRange {ch:ch, next:prev};
+}
+
+/// Plucks the character ending at the `i`th byte of a string
+pub fn char_at_reverse(s: &str, i: uint) -> char {
+    char_range_at_reverse(s, i).ch
+}
+
+/**
+ * Loop through a substring, char by char
+ *
+ * # Safety note
+ *
+ * * This function does not check whether the substring is valid.
+ * * This function fails if `start` or `end` do not
+ *   represent valid positions inside `s`
+ *
+ * # Arguments
+ *
+ * * s - A string to traverse. It may be empty.
+ * * start - The byte offset at which to start in the string.
+ * * end - The end of the range to traverse
+ * * it - A block to execute with each consecutive character of `s`.
+ *        Return `true` to continue, `false` to stop.
+ *
+ * # Return value
+ *
+ * `true` If execution proceeded correctly, `false` if it was interrupted,
+ * that is if `it` returned `false` at any point.
+ */
+pub fn all_between(s: &str, start: uint, end: uint,
+                    it: &fn(char) -> bool) -> bool {
+    assert!(is_char_boundary(s, start));
+    let mut i = start;
+    while i < end {
+        let CharRange {ch, next} = char_range_at(s, i);
+        if !it(ch) { return false; }
+        i = next;
+    }
+    return true;
+}
+
+/**
+ * Loop through a substring, char by char
+ *
+ * # Safety note
+ *
+ * * This function does not check whether the substring is valid.
+ * * This function fails if `start` or `end` do not
+ *   represent valid positions inside `s`
+ *
+ * # Arguments
+ *
+ * * s - A string to traverse. It may be empty.
+ * * start - The byte offset at which to start in the string.
+ * * end - The end of the range to traverse
+ * * it - A block to execute with each consecutive character of `s`.
+ *        Return `true` to continue, `false` to stop.
+ *
+ * # Return value
+ *
+ * `true` if `it` returns `true` for any character
+ */
+pub fn any_between(s: &str, start: uint, end: uint,
+                    it: &fn(char) -> bool) -> bool {
+    !all_between(s, start, end, |c| !it(c))
+}
+
+// UTF-8 tags and ranges
+static tag_cont_u8: u8 = 128u8;
+static tag_cont: uint = 128u;
+static max_one_b: uint = 128u;
+static tag_two_b: uint = 192u;
+static max_two_b: uint = 2048u;
+static tag_three_b: uint = 224u;
+static max_three_b: uint = 65536u;
+static tag_four_b: uint = 240u;
+static max_four_b: uint = 2097152u;
+static tag_five_b: uint = 248u;
+static max_five_b: uint = 67108864u;
+static tag_six_b: uint = 252u;
+
+/**
+ * Work with the byte buffer of a string.
+ *
+ * Allows for unsafe manipulation of strings, which is useful for foreign
+ * interop.
+ *
+ * # Example
+ *
+ * ~~~
+ * let i = str::as_bytes("Hello World") { |bytes| bytes.len() };
+ * ~~~
+ */
+#[inline]
+pub fn as_bytes<T>(s: &const ~str, f: &fn(&~[u8]) -> T) -> T {
+    unsafe {
+        let v: *~[u8] = cast::transmute(copy s);
+        f(&*v)
+    }
+}
+
+/**
+ * Work with the byte buffer of a string as a byte slice.
+ *
+ * The byte slice does not include the null terminator.
+ */
+pub fn as_bytes_slice<'a>(s: &'a str) -> &'a [u8] {
+    unsafe {
+        let (ptr, len): (*u8, uint) = ::cast::transmute(s);
+        let outgoing_tuple: (*u8, uint) = (ptr, len - 1);
+        return ::cast::transmute(outgoing_tuple);
+    }
+}
+
+/**
+ * Work with the byte buffer of a string as a null-terminated C string.
+ *
+ * Allows for unsafe manipulation of strings, which is useful for foreign
+ * interop. This is similar to `str::as_buf`, but guarantees null-termination.
+ * If the given slice is not already null-terminated, this function will
+ * allocate a temporary, copy the slice, null terminate it, and pass
+ * that instead.
+ *
+ * # Example
+ *
+ * ~~~
+ * let s = str::as_c_str("PATH", { |path| libc::getenv(path) });
+ * ~~~
+ */
+#[inline]
+pub fn as_c_str<T>(s: &str, f: &fn(*libc::c_char) -> T) -> T {
+    do as_buf(s) |buf, len| {
+        // NB: len includes the trailing null.
+        assert!(len > 0);
+        if unsafe { *(ptr::offset(buf,len-1)) != 0 } {
+            as_c_str(to_owned(s), f)
+        } else {
+            f(buf as *libc::c_char)
+        }
+    }
+}
+
+/**
+ * Work with the byte buffer and length of a slice.
+ *
+ * The given length is one byte longer than the 'official' indexable
+ * length of the string. This is to permit probing the byte past the
+ * indexable area for a null byte, as is the case in slices pointing
+ * to full strings, or suffixes of them.
+ */
+#[inline(always)]
+pub fn as_buf<T>(s: &str, f: &fn(*u8, uint) -> T) -> T {
+    unsafe {
+        let v : *(*u8,uint) = transmute(&s);
+        let (buf,len) = *v;
+        f(buf, len)
+    }
+}
+
+/**
+ * Returns the byte offset of an inner slice relative to an enclosing outer slice
+ *
+ * # Example
+ *
+ * ~~~
+ * let string = "a\nb\nc";
+ * let mut lines = ~[];
+ * for each_line(string) |line| { lines.push(line) }
+ *
+ * assert!(subslice_offset(string, lines[0]) == 0); // &"a"
+ * assert!(subslice_offset(string, lines[1]) == 2); // &"b"
+ * assert!(subslice_offset(string, lines[2]) == 4); // &"c"
+ * ~~~
+ */
+#[inline(always)]
+pub fn subslice_offset(outer: &str, inner: &str) -> uint {
+    do as_buf(outer) |a, a_len| {
+        do as_buf(inner) |b, b_len| {
+            let a_start: uint, a_end: uint, b_start: uint, b_end: uint;
+            unsafe {
+                a_start = cast::transmute(a); a_end = a_len + cast::transmute(a);
+                b_start = cast::transmute(b); b_end = b_len + cast::transmute(b);
+            }
+            assert!(a_start <= b_start);
+            assert!(b_end <= a_end);
+            b_start - a_start
+        }
+    }
+}
+
+/**
+ * Reserves capacity for exactly `n` bytes in the given string, not including
+ * the null terminator.
+ *
+ * Assuming single-byte characters, the resulting string will be large
+ * enough to hold a string of length `n`. To account for the null terminator,
+ * the underlying buffer will have the size `n` + 1.
+ *
+ * If the capacity for `s` is already equal to or greater than the requested
+ * capacity, then no action is taken.
+ *
+ * # Arguments
+ *
+ * * s - A string
+ * * n - The number of bytes to reserve space for
+ */
+#[inline(always)]
+pub fn reserve(s: &mut ~str, n: uint) {
+    unsafe {
+        let v: *mut ~[u8] = cast::transmute(s);
+        vec::reserve(&mut *v, n + 1);
+    }
+}
+
+/**
+ * Reserves capacity for at least `n` bytes in the given string, not including
+ * the null terminator.
+ *
+ * Assuming single-byte characters, the resulting string will be large
+ * enough to hold a string of length `n`. To account for the null terminator,
+ * the underlying buffer will have the size `n` + 1.
+ *
+ * This function will over-allocate in order to amortize the allocation costs
+ * in scenarios where the caller may need to repeatedly reserve additional
+ * space.
+ *
+ * If the capacity for `s` is already equal to or greater than the requested
+ * capacity, then no action is taken.
+ *
+ * # Arguments
+ *
+ * * s - A string
+ * * n - The number of bytes to reserve space for
+ */
+#[inline(always)]
+pub fn reserve_at_least(s: &mut ~str, n: uint) {
+    reserve(s, uint::next_power_of_two(n + 1u) - 1u)
+}
+
+/**
+ * Returns the number of single-byte characters the string can hold without
+ * reallocating
+ */
+pub fn capacity(s: &const ~str) -> uint {
+    do as_bytes(s) |buf| {
+        let vcap = vec::capacity(buf);
+        assert!(vcap > 0u);
+        vcap - 1u
+    }
+}
+
+/// Escape each char in `s` with char::escape_default.
+pub fn escape_default(s: &str) -> ~str {
+    let mut out: ~str = ~"";
+    reserve_at_least(&mut out, str::len(s));
+    for s.each_char |c| {
+        push_str(&mut out, char::escape_default(c));
+    }
+    out
+}
+
+/// Escape each char in `s` with char::escape_unicode.
+pub fn escape_unicode(s: &str) -> ~str {
+    let mut out: ~str = ~"";
+    reserve_at_least(&mut out, str::len(s));
+    for s.each_char |c| {
+        push_str(&mut out, char::escape_unicode(c));
+    }
+    out
+}
+
+/// Unsafe operations
+pub mod raw {
+    use cast;
+    use libc;
+    use ptr;
+    use str::raw;
+    use str::{as_buf, is_utf8, len, reserve_at_least};
+    use vec;
+
+    /// Create a Rust string from a null-terminated *u8 buffer
+    pub unsafe fn from_buf(buf: *u8) -> ~str {
+        let mut curr = buf, i = 0u;
+        while *curr != 0u8 {
+            i += 1u;
+            curr = ptr::offset(buf, i);
+        }
+        return from_buf_len(buf, i);
+    }
+
+    /// Create a Rust string from a *u8 buffer of the given length
+    pub unsafe fn from_buf_len(buf: *const u8, len: uint) -> ~str {
+        let mut v: ~[u8] = vec::with_capacity(len + 1);
+        vec::as_mut_buf(v, |vbuf, _len| {
+            ptr::copy_memory(vbuf, buf as *u8, len)
+        });
+        vec::raw::set_len(&mut v, len);
+        v.push(0u8);
+
+        assert!(is_utf8(v));
+        return ::cast::transmute(v);
+    }
+
+    /// Create a Rust string from a null-terminated C string
+    pub unsafe fn from_c_str(c_str: *libc::c_char) -> ~str {
+        from_buf(::cast::transmute(c_str))
+    }
+
+    /// Create a Rust string from a `*c_char` buffer of the given length
+    pub unsafe fn from_c_str_len(c_str: *libc::c_char, len: uint) -> ~str {
+        from_buf_len(::cast::transmute(c_str), len)
+    }
+
+    /// Converts a vector of bytes to a new owned string.
+    pub unsafe fn from_bytes(v: &const [u8]) -> ~str {
+        do vec::as_const_buf(v) |buf, len| {
+            from_buf_len(buf, len)
+        }
+    }
+
+    /// Converts a vector of bytes to a string.
+    /// The byte slice needs to contain valid utf8 and needs to be one byte longer than
+    /// the string, if possible ending in a 0 byte.
+    pub unsafe fn from_bytes_with_null<'a>(v: &'a [u8]) -> &'a str {
+        cast::transmute(v)
+    }
+
+    /// Converts a byte to a string.
+    pub unsafe fn from_byte(u: u8) -> ~str { raw::from_bytes([u]) }
+
+    /// Form a slice from a *u8 buffer of the given length without copying.
+    pub unsafe fn buf_as_slice<T>(buf: *u8, len: uint,
+                              f: &fn(v: &str) -> T) -> T {
+        let v = (buf, len + 1);
+        assert!(is_utf8(::cast::transmute(v)));
+        f(::cast::transmute(v))
+    }
+
+    /**
+     * Takes a bytewise (not UTF-8) slice from a string.
+     *
+     * Returns the substring from [`begin`..`end`).
+     *
+     * # Failure
+     *
+     * If begin is greater than end.
+     * If end is greater than the length of the string.
+     */
+    pub unsafe fn slice_bytes_owned(s: &str, begin: uint, end: uint) -> ~str {
+        do as_buf(s) |sbuf, n| {
+            assert!((begin <= end));
+            assert!((end <= n));
+
+            let mut v = vec::with_capacity(end - begin + 1u);
+            do vec::as_imm_buf(v) |vbuf, _vlen| {
+                let vbuf = ::cast::transmute_mut_unsafe(vbuf);
+                let src = ptr::offset(sbuf, begin);
+                ptr::copy_memory(vbuf, src, end - begin);
+            }
+            vec::raw::set_len(&mut v, end - begin);
+            v.push(0u8);
+            ::cast::transmute(v)
+        }
+    }
+
+    /**
+     * Takes a bytewise (not UTF-8) slice from a string.
+     *
+     * Returns the substring from [`begin`..`end`).
+     *
+     * # Failure
+     *
+     * If begin is greater than end.
+     * If end is greater than the length of the string.
+     */
+    #[inline]
+    pub unsafe fn slice_bytes(s: &str, begin: uint, end: uint) -> &str {
+        do as_buf(s) |sbuf, n| {
+             assert!((begin <= end));
+             assert!((end <= n));
+
+             let tuple = (ptr::offset(sbuf, begin), end - begin + 1);
+             ::cast::transmute(tuple)
+        }
+    }
+
+    /// Appends a byte to a string. (Not UTF-8 safe).
+    pub unsafe fn push_byte(s: &mut ~str, b: u8) {
+        let new_len = s.len() + 1;
+        reserve_at_least(&mut *s, new_len);
+        do as_buf(*s) |buf, len| {
+            let buf: *mut u8 = ::cast::transmute(buf);
+            *ptr::mut_offset(buf, len) = b;
+        }
+        set_len(&mut *s, new_len);
+    }
+
+    /// Appends a vector of bytes to a string. (Not UTF-8 safe).
+    unsafe fn push_bytes(s: &mut ~str, bytes: &[u8]) {
+        let new_len = s.len() + bytes.len();
+        reserve_at_least(&mut *s, new_len);
+        for bytes.each |byte| { push_byte(&mut *s, *byte); }
+    }
+
+    /// Removes the last byte from a string and returns it. (Not UTF-8 safe).
+    pub unsafe fn pop_byte(s: &mut ~str) -> u8 {
+        let len = len(*s);
+        assert!((len > 0u));
+        let b = s[len - 1u];
+        set_len(s, len - 1u);
+        return b;
+    }
+
+    /// Removes the first byte from a string and returns it. (Not UTF-8 safe).
+    pub unsafe fn shift_byte(s: &mut ~str) -> u8 {
+        let len = len(*s);
+        assert!((len > 0u));
+        let b = s[0];
+        *s = raw::slice_bytes_owned(*s, 1u, len);
+        return b;
+    }
+
+    /// Sets the length of the string and adds the null terminator
+    #[inline]
+    pub unsafe fn set_len(v: &mut ~str, new_len: uint) {
+        let v: **mut vec::raw::VecRepr = cast::transmute(v);
+        let repr: *mut vec::raw::VecRepr = *v;
+        (*repr).unboxed.fill = new_len + 1u;
+        let null = ptr::mut_offset(cast::transmute(&((*repr).unboxed.data)),
+                                   new_len);
+        *null = 0u8;
+    }
+
+    #[test]
+    fn test_from_buf_len() {
+        unsafe {
+            let a = ~[65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
+            let b = vec::raw::to_ptr(a);
+            let c = from_buf_len(b, 3u);
+            assert_eq!(c, ~"AAA");
+        }
+    }
+
+}
+
+#[cfg(not(test))]
+pub mod traits {
+    use ops::Add;
+    use str::append;
+
+    impl<'self> Add<&'self str,~str> for ~str {
+        #[inline(always)]
+        fn add(&self, rhs: & &'self str) -> ~str {
+            append(copy *self, (*rhs))
+        }
+    }
+}
+
+#[cfg(test)]
+pub mod traits {}
+
+pub trait StrSlice<'self> {
+    fn all(&self, it: &fn(char) -> bool) -> bool;
+    fn any(&self, it: &fn(char) -> bool) -> bool;
+    fn contains<'a>(&self, needle: &'a str) -> bool;
+    fn contains_char(&self, needle: char) -> bool;
+    fn char_iter(&self) -> StrCharIterator<'self>;
+    fn each(&self, it: &fn(u8) -> bool) -> bool;
+    fn eachi(&self, it: &fn(uint, u8) -> bool) -> bool;
+    fn each_reverse(&self, it: &fn(u8) -> bool) -> bool;
+    fn eachi_reverse(&self, it: &fn(uint, u8) -> bool) -> bool;
+    fn each_char(&self, it: &fn(char) -> bool) -> bool;
+    fn each_chari(&self, it: &fn(uint, char) -> bool) -> bool;
+    fn each_char_reverse(&self, it: &fn(char) -> bool) -> bool;
+    fn each_chari_reverse(&self, it: &fn(uint, char) -> bool) -> bool;
+    fn ends_with(&self, needle: &str) -> bool;
+    fn is_empty(&self) -> bool;
+    fn is_whitespace(&self) -> bool;
+    fn is_alphanumeric(&self) -> bool;
+    fn len(&self) -> uint;
+    fn char_len(&self) -> uint;
+    fn slice(&self, begin: uint, end: uint) -> &'self str;
+    fn each_split(&self, sepfn: &fn(char) -> bool, it: &fn(&'self str) -> bool) -> bool;
+    fn each_split_char(&self, sep: char, it: &fn(&'self str) -> bool) -> bool;
+    fn each_split_str<'a>(&self, sep: &'a str, it: &fn(&'self str) -> bool) -> bool;
+    fn starts_with<'a>(&self, needle: &'a str) -> bool;
+    fn substr(&self, begin: uint, n: uint) -> &'self str;
+    fn escape_default(&self) -> ~str;
+    fn escape_unicode(&self) -> ~str;
+    fn trim(&self) -> &'self str;
+    fn trim_left(&self) -> &'self str;
+    fn trim_right(&self) -> &'self str;
+    fn trim_chars(&self, chars_to_trim: &[char]) -> &'self str;
+    fn trim_left_chars(&self, chars_to_trim: &[char]) -> &'self str;
+    fn trim_right_chars(&self, chars_to_trim: &[char]) -> &'self str;
+    fn to_owned(&self) -> ~str;
+    fn to_managed(&self) -> @str;
+    fn char_at(&self, i: uint) -> char;
+    fn char_at_reverse(&self, i: uint) -> char;
+    fn to_bytes(&self) -> ~[u8];
+}
+
+/// Extension methods for strings
+impl<'self> StrSlice<'self> for &'self str {
+    /**
+     * Return true if a predicate matches all characters or if the string
+     * contains no characters
+     */
+    #[inline]
+    fn all(&self, it: &fn(char) -> bool) -> bool { all(*self, it) }
+    /**
+     * Return true if a predicate matches any character (and false if it
+     * matches none or there are no characters)
+     */
+    #[inline]
+    fn any(&self, it: &fn(char) -> bool) -> bool { any(*self, it) }
+    /// Returns true if one string contains another
+    #[inline]
+    fn contains<'a>(&self, needle: &'a str) -> bool {
+        contains(*self, needle)
+    }
+    /// Returns true if a string contains a char
+    #[inline]
+    fn contains_char(&self, needle: char) -> bool {
+        contains_char(*self, needle)
+    }
+
+    #[inline]
+    fn char_iter(&self) -> StrCharIterator<'self> {
+        StrCharIterator {
+            index: 0,
+            string: *self
+        }
+    }
+
+    /// Iterate over the bytes in a string
+    #[inline]
+    fn each(&self, it: &fn(u8) -> bool) -> bool { each(*self, it) }
+    /// Iterate over the bytes in a string, with indices
+    #[inline]
+    fn eachi(&self, it: &fn(uint, u8) -> bool) -> bool { eachi(*self, it) }
+    /// Iterate over the bytes in a string
+    #[inline]
+    fn each_reverse(&self, it: &fn(u8) -> bool) -> bool { each_reverse(*self, it) }
+    /// Iterate over the bytes in a string, with indices
+    #[inline]
+    fn eachi_reverse(&self, it: &fn(uint, u8) -> bool) -> bool {
+        eachi_reverse(*self, it)
+    }
+    /// Iterate over the chars in a string
+    #[inline]
+    fn each_char(&self, it: &fn(char) -> bool) -> bool { each_char(*self, it) }
+    /// Iterate over the chars in a string, with indices
+    #[inline]
+    fn each_chari(&self, it: &fn(uint, char) -> bool) -> bool {
+        each_chari(*self, it)
+    }
+    /// Iterate over the chars in a string in reverse
+    #[inline]
+    fn each_char_reverse(&self, it: &fn(char) -> bool) -> bool {
+        each_char_reverse(*self, it)
+    }
+    /// Iterate over the chars in a string in reverse, with indices from the
+    /// end
+    #[inline]
+    fn each_chari_reverse(&self, it: &fn(uint, char) -> bool) -> bool {
+        each_chari_reverse(*self, it)
+    }
+    /// Returns true if one string ends with another
+    #[inline]
+    fn ends_with(&self, needle: &str) -> bool {
+        ends_with(*self, needle)
+    }
+    /// Returns true if the string has length 0
+    #[inline]
+    fn is_empty(&self) -> bool { is_empty(*self) }
+    /**
+     * Returns true if the string contains only whitespace
+     *
+     * Whitespace characters are determined by `char::is_whitespace`
+     */
+    #[inline]
+    fn is_whitespace(&self) -> bool { is_whitespace(*self) }
+    /**
+     * Returns true if the string contains only alphanumerics
+     *
+     * Alphanumeric characters are determined by `char::is_alphanumeric`
+     */
+    #[inline]
+    fn is_alphanumeric(&self) -> bool { is_alphanumeric(*self) }
+    /// Returns the size in bytes not counting the null terminator
+    #[inline(always)]
+    fn len(&self) -> uint { len(*self) }
+    /// Returns the number of characters that a string holds
+    #[inline]
+    fn char_len(&self) -> uint { char_len(*self) }
+    /**
+     * Returns a slice of the given string from the byte range
+     * [`begin`..`end`)
+     *
+     * Fails when `begin` and `end` do not point to valid characters or
+     * beyond the last character of the string
+     */
+    #[inline]
+    fn slice(&self, begin: uint, end: uint) -> &'self str {
+        slice(*self, begin, end)
+    }
+    /// Splits a string into substrings using a character function
+    #[inline]
+    fn each_split(&self, sepfn: &fn(char) -> bool, it: &fn(&'self str) -> bool) -> bool {
+        each_split(*self, sepfn, it)
+    }
+    /**
+     * Splits a string into substrings at each occurrence of a given character
+     */
+    #[inline]
+    fn each_split_char(&self, sep: char, it: &fn(&'self str) -> bool) -> bool {
+        each_split_char(*self, sep, it)
+    }
+    /**
+     * Splits a string into a vector of the substrings separated by a given
+     * string
+     */
+    #[inline]
+    fn each_split_str<'a>(&self, sep: &'a str, it: &fn(&'self str) -> bool) -> bool {
+        each_split_str(*self, sep, it)
+    }
+    /// Returns true if one string starts with another
+    #[inline]
+    fn starts_with<'a>(&self, needle: &'a str) -> bool {
+        starts_with(*self, needle)
+    }
+    /**
+     * Take a substring of another.
+     *
+     * Returns a string containing `n` characters starting at byte offset
+     * `begin`.
+     */
+    #[inline]
+    fn substr(&self, begin: uint, n: uint) -> &'self str {
+        substr(*self, begin, n)
+    }
+    /// Escape each char in `s` with char::escape_default.
+    #[inline]
+    fn escape_default(&self) -> ~str { escape_default(*self) }
+    /// Escape each char in `s` with char::escape_unicode.
+    #[inline]
+    fn escape_unicode(&self) -> ~str { escape_unicode(*self) }
+
+    /// Returns a string with leading and trailing whitespace removed
+    #[inline]
+    fn trim(&self) -> &'self str { trim(*self) }
+    /// Returns a string with leading whitespace removed
+    #[inline]
+    fn trim_left(&self) -> &'self str { trim_left(*self) }
+    /// Returns a string with trailing whitespace removed
+    #[inline]
+    fn trim_right(&self) -> &'self str { trim_right(*self) }
+
+    #[inline]
+    fn trim_chars(&self, chars_to_trim: &[char]) -> &'self str {
+        trim_chars(*self, chars_to_trim)
+    }
+    #[inline]
+    fn trim_left_chars(&self, chars_to_trim: &[char]) -> &'self str {
+        trim_left_chars(*self, chars_to_trim)
+    }
+    #[inline]
+    fn trim_right_chars(&self, chars_to_trim: &[char]) -> &'self str {
+        trim_right_chars(*self, chars_to_trim)
+    }
+
+
+    #[inline]
+    fn to_owned(&self) -> ~str { to_owned(*self) }
+
+    #[inline]
+    fn to_managed(&self) -> @str {
+        let v = at_vec::from_fn(self.len() + 1, |i| {
+            if i == self.len() { 0 } else { self[i] }
+        });
+        unsafe { ::cast::transmute(v) }
+    }
+
+    #[inline]
+    fn char_at(&self, i: uint) -> char { char_at(*self, i) }
+
+    #[inline]
+    fn char_at_reverse(&self, i: uint) -> char {
+        char_at_reverse(*self, i)
+    }
+
+    fn to_bytes(&self) -> ~[u8] { to_bytes(*self) }
+}
+
+pub trait OwnedStr {
+    fn push_str(&mut self, v: &str);
+    fn push_char(&mut self, c: char);
+}
+
+impl OwnedStr for ~str {
+    #[inline]
+    fn push_str(&mut self, v: &str) {
+        push_str(self, v);
+    }
+    #[inline]
+    fn push_char(&mut self, c: char) {
+        push_char(self, c);
+    }
+}
+
+impl Clone for ~str {
+    #[inline(always)]
+    fn clone(&self) -> ~str {
+        to_owned(*self)
+    }
+}
+
+pub struct StrCharIterator<'self> {
+    priv index: uint,
+    priv string: &'self str,
+}
+
+impl<'self> Iterator<char> for StrCharIterator<'self> {
+    #[inline]
+    fn next(&mut self) -> Option<char> {
+        if self.index < self.string.len() {
+            let CharRange {ch, next} = char_range_at(self.string, self.index);
+            self.index = next;
+            Some(ch)
+        } else {
+            None
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use container::Container;
+    use char;
+    use option::Some;
+    use libc::c_char;
+    use libc;
+    use old_iter::BaseIter;
+    use ptr;
+    use str::*;
+    use vec;
+    use vec::ImmutableVector;
+    use cmp::{TotalOrd, Less, Equal, Greater};
+
+    #[test]
+    fn test_eq() {
+        assert!((eq(&~"", &~"")));
+        assert!((eq(&~"foo", &~"foo")));
+        assert!((!eq(&~"foo", &~"bar")));
+    }
+
+    #[test]
+    fn test_eq_slice() {
+        assert!((eq_slice(slice("foobar", 0, 3), "foo")));
+        assert!((eq_slice(slice("barfoo", 3, 6), "foo")));
+        assert!((!eq_slice("foo1", "foo2")));
+    }
+
+    #[test]
+    fn test_le() {
+        assert!((le(&"", &"")));
+        assert!((le(&"", &"foo")));
+        assert!((le(&"foo", &"foo")));
+        assert!((!eq(&~"foo", &~"bar")));
+    }
+
+    #[test]
+    fn test_len() {
+        assert_eq!(len(~""), 0u);
+        assert_eq!(len(~"hello world"), 11u);
+        assert_eq!(len(~"\x63"), 1u);
+        assert_eq!(len(~"\xa2"), 2u);
+        assert_eq!(len(~"\u03c0"), 2u);
+        assert_eq!(len(~"\u2620"), 3u);
+        assert_eq!(len(~"\U0001d11e"), 4u);
+
+        assert_eq!(char_len(~""), 0u);
+        assert_eq!(char_len(~"hello world"), 11u);
+        assert_eq!(char_len(~"\x63"), 1u);
+        assert_eq!(char_len(~"\xa2"), 1u);
+        assert_eq!(char_len(~"\u03c0"), 1u);
+        assert_eq!(char_len(~"\u2620"), 1u);
+        assert_eq!(char_len(~"\U0001d11e"), 1u);
+        assert_eq!(char_len(~"ประเทศไทย中华Việt Nam"), 19u);
+    }
+
+    #[test]
+    fn test_rfind_char() {
+        assert_eq!(rfind_char(~"hello", 'l'), Some(3u));
+        assert_eq!(rfind_char(~"hello", 'o'), Some(4u));
+        assert_eq!(rfind_char(~"hello", 'h'), Some(0u));
+        assert!(rfind_char(~"hello", 'z').is_none());
+        assert_eq!(rfind_char(~"ประเทศไทย中华Việt Nam", '华'), Some(30u));
+    }
+
+    #[test]
+    fn test_pop_char() {
+        let mut data = ~"ประเทศไทย中华";
+        let cc = pop_char(&mut data);
+        assert_eq!(~"ประเทศไทย中", data);
+        assert_eq!('华', cc);
+    }
+
+    #[test]
+    fn test_pop_char_2() {
+        let mut data2 = ~"华";
+        let cc2 = pop_char(&mut data2);
+        assert_eq!(~"", data2);
+        assert_eq!('华', cc2);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_pop_char_fail() {
+        let mut data = ~"";
+        let _cc3 = pop_char(&mut data);
+    }
+
+    #[test]
+    fn test_split_char() {
+        fn t(s: &str, c: char, u: &[~str]) {
+            debug!(~"split_byte: " + s);
+            let mut v = ~[];
+            for each_split_char(s, c) |s| { v.push(s.to_owned()) }
+            debug!("split_byte to: %?", v);
+            assert!(vec::all2(v, u, |a,b| a == b));
+        }
+        t(~"abc.hello.there", '.', ~[~"abc", ~"hello", ~"there"]);
+        t(~".hello.there", '.', ~[~"", ~"hello", ~"there"]);
+        t(~"...hello.there.", '.', ~[~"", ~"", ~"", ~"hello", ~"there", ~""]);
+
+        t(~"", 'z', ~[~""]);
+        t(~"z", 'z', ~[~"",~""]);
+        t(~"ok", 'z', ~[~"ok"]);
+    }
+
+    #[test]
+    fn test_split_char_2() {
+        fn t(s: &str, c: char, u: &[~str]) {
+            debug!(~"split_byte: " + s);
+            let mut v = ~[];
+            for each_split_char(s, c) |s| { v.push(s.to_owned()) }
+            debug!("split_byte to: %?", v);
+            assert!(vec::all2(v, u, |a,b| a == b));
+        }
+        let data = ~"ประเทศไทย中华Việt Nam";
+        t(data, 'V', ~[~"ประเทศไทย中华", ~"iệt Nam"]);
+        t(data, 'ท', ~[~"ประเ", ~"ศไ", ~"ย中华Việt Nam"]);
+    }
+
+    #[test]
+    fn test_splitn_char() {
+        fn t(s: &str, c: char, n: uint, u: &[~str]) {
+            debug!(~"splitn_byte: " + s);
+            let mut v = ~[];
+            for each_splitn_char(s, c, n) |s| { v.push(s.to_owned()) }
+            debug!("split_byte to: %?", v);
+            debug!("comparing vs. %?", u);
+            assert!(vec::all2(v, u, |a,b| a == b));
+        }
+        t(~"abc.hello.there", '.', 0u, ~[~"abc.hello.there"]);
+        t(~"abc.hello.there", '.', 1u, ~[~"abc", ~"hello.there"]);
+        t(~"abc.hello.there", '.', 2u, ~[~"abc", ~"hello", ~"there"]);
+        t(~"abc.hello.there", '.', 3u, ~[~"abc", ~"hello", ~"there"]);
+        t(~".hello.there", '.', 0u, ~[~".hello.there"]);
+        t(~".hello.there", '.', 1u, ~[~"", ~"hello.there"]);
+        t(~"...hello.there.", '.', 3u, ~[~"", ~"", ~"", ~"hello.there."]);
+        t(~"...hello.there.", '.', 5u, ~[~"", ~"", ~"", ~"hello", ~"there", ~""]);
+
+        t(~"", 'z', 5u, ~[~""]);
+        t(~"z", 'z', 5u, ~[~"",~""]);
+        t(~"ok", 'z', 5u, ~[~"ok"]);
+        t(~"z", 'z', 0u, ~[~"z"]);
+        t(~"w.x.y", '.', 0u, ~[~"w.x.y"]);
+        t(~"w.x.y", '.', 1u, ~[~"w",~"x.y"]);
+    }
+
+    #[test]
+    fn test_splitn_char_2 () {
+        fn t(s: &str, c: char, n: uint, u: &[~str]) {
+            debug!(~"splitn_byte: " + s);
+            let mut v = ~[];
+            for each_splitn_char(s, c, n) |s| { v.push(s.to_owned()) }
+            debug!("split_byte to: %?", v);
+            debug!("comparing vs. %?", u);
+            assert!(vec::all2(v, u, |a,b| a == b));
+        }
+
+        t(~"ประเทศไทย中华Việt Nam", '华', 1u, ~[~"ประเทศไทย中", ~"Việt Nam"]);
+        t(~"zzXXXzYYYzWWWz", 'z', 3u, ~[~"", ~"", ~"XXX", ~"YYYzWWWz"]);
+        t(~"z", 'z', 5u, ~[~"",~""]);
+        t(~"", 'z', 5u, ~[~""]);
+        t(~"ok", 'z', 5u, ~[~"ok"]);
+    }
+
+
+    #[test]
+    fn test_splitn_char_3() {
+        fn t(s: &str, c: char, n: uint, u: &[~str]) {
+            debug!(~"splitn_byte: " + s);
+            let mut v = ~[];
+            for each_splitn_char(s, c, n) |s| { v.push(s.to_owned()) }
+            debug!("split_byte to: %?", v);
+            debug!("comparing vs. %?", u);
+            assert!(vec::all2(v, u, |a,b| a == b));
+        }
+        let data = ~"ประเทศไทย中华Việt Nam";
+        t(data, 'V', 1u, ~[~"ประเทศไทย中华", ~"iệt Nam"]);
+        t(data, 'ท', 1u, ~[~"ประเ", ~"ศไทย中华Việt Nam"]);
+    }
+
+    #[test]
+    fn test_split_char_no_trailing() {
+        fn t(s: &str, c: char, u: &[~str]) {
+            debug!(~"split_byte: " + s);
+            let mut v = ~[];
+            for each_split_char_no_trailing(s, c) |s| { v.push(s.to_owned()) }
+            debug!("split_byte to: %?", v);
+            assert!(vec::all2(v, u, |a,b| a == b));
+        }
+        t(~"abc.hello.there", '.', ~[~"abc", ~"hello", ~"there"]);
+        t(~".hello.there", '.', ~[~"", ~"hello", ~"there"]);
+        t(~"...hello.there.", '.', ~[~"", ~"", ~"", ~"hello", ~"there"]);
+
+        t(~"...hello.there.", '.', ~[~"", ~"", ~"", ~"hello", ~"there"]);
+        t(~"", 'z', ~[]);
+        t(~"z", 'z', ~[~""]);
+        t(~"ok", 'z', ~[~"ok"]);
+    }
+
+    #[test]
+    fn test_split_char_no_trailing_2() {
+        fn t(s: &str, c: char, u: &[~str]) {
+            debug!(~"split_byte: " + s);
+            let mut v = ~[];
+            for each_split_char_no_trailing(s, c) |s| { v.push(s.to_owned()) }
+            debug!("split_byte to: %?", v);
+            assert!(vec::all2(v, u, |a,b| a == b));
+        }
+        let data = ~"ประเทศไทย中华Việt Nam";
+        t(data, 'V', ~[~"ประเทศไทย中华", ~"iệt Nam"]);
+        t(data, 'ท', ~[~"ประเ", ~"ศไ", ~"ย中华Việt Nam"]);
+    }
+
+    #[test]
+    fn test_split_str() {
+        fn t<'a>(s: &str, sep: &'a str, u: &[~str]) {
+            let mut v = ~[];
+            for each_split_str(s, sep) |s| { v.push(s.to_owned()) }
+            assert!(vec::all2(v, u, |a,b| a == b));
+        }
+        t(~"--1233345--", ~"12345", ~[~"--1233345--"]);
+        t(~"abc::hello::there", ~"::", ~[~"abc", ~"hello", ~"there"]);
+        t(~"::hello::there", ~"::", ~[~"", ~"hello", ~"there"]);
+        t(~"hello::there::", ~"::", ~[~"hello", ~"there", ~""]);
+        t(~"::hello::there::", ~"::", ~[~"", ~"hello", ~"there", ~""]);
+        t(~"ประเทศไทย中华Việt Nam", ~"中华", ~[~"ประเทศไทย", ~"Việt Nam"]);
+        t(~"zzXXXzzYYYzz", ~"zz", ~[~"", ~"XXX", ~"YYY", ~""]);
+        t(~"zzXXXzYYYz", ~"XXX", ~[~"zz", ~"zYYYz"]);
+        t(~".XXX.YYY.", ~".", ~[~"", ~"XXX", ~"YYY", ~""]);
+        t(~"", ~".", ~[~""]);
+        t(~"zz", ~"zz", ~[~"",~""]);
+        t(~"ok", ~"z", ~[~"ok"]);
+        t(~"zzz", ~"zz", ~[~"",~"z"]);
+        t(~"zzzzz", ~"zz", ~[~"",~"",~"z"]);
+    }
+
+
+    #[test]
+    fn test_split() {
+        fn t(s: &str, sepf: &fn(char) -> bool, u: &[~str]) {
+            let mut v = ~[];
+            for each_split(s, sepf) |s| { v.push(s.to_owned()) }
+            assert!(vec::all2(v, u, |a,b| a == b));
+        }
+
+        t(~"ประเทศไทย中华Việt Nam", |cc| cc == '华', ~[~"ประเทศไทย中", ~"Việt Nam"]);
+        t(~"zzXXXzYYYz", char::is_lowercase, ~[~"", ~"", ~"XXX", ~"YYY", ~""]);
+        t(~"zzXXXzYYYz", char::is_uppercase, ~[~"zz", ~"", ~"", ~"z", ~"", ~"", ~"z"]);
+        t(~"z", |cc| cc == 'z', ~[~"",~""]);
+        t(~"", |cc| cc == 'z', ~[~""]);
+        t(~"ok", |cc| cc == 'z', ~[~"ok"]);
+    }
+
+    #[test]
+    fn test_split_no_trailing() {
+        fn t(s: &str, sepf: &fn(char) -> bool, u: &[~str]) {
+            let mut v = ~[];
+            for each_split_no_trailing(s, sepf) |s| { v.push(s.to_owned()) }
+            assert!(vec::all2(v, u, |a,b| a == b));
+        }
+
+        t(~"ประเทศไทย中华Việt Nam", |cc| cc == '华', ~[~"ประเทศไทย中", ~"Việt Nam"]);
+        t(~"zzXXXzYYYz", char::is_lowercase, ~[~"", ~"", ~"XXX", ~"YYY"]);
+        t(~"zzXXXzYYYz", char::is_uppercase, ~[~"zz", ~"", ~"", ~"z", ~"", ~"", ~"z"]);
+        t(~"z", |cc| cc == 'z', ~[~""]);
+        t(~"", |cc| cc == 'z', ~[]);
+        t(~"ok", |cc| cc == 'z', ~[~"ok"]);
+    }
+
+    #[test]
+    fn test_lines() {
+        let lf = ~"\nMary had a little lamb\nLittle lamb\n";
+        let crlf = ~"\r\nMary had a little lamb\r\nLittle lamb\r\n";
+
+        fn t(s: &str, f: &fn(&str, &fn(&str) -> bool) -> bool, u: &[~str]) {
+            let mut v = ~[];
+            for f(s) |s| { v.push(s.to_owned()) }
+            assert!(vec::all2(v, u, |a,b| a == b));
+        }
+
+        t(lf, each_line ,~[~"", ~"Mary had a little lamb", ~"Little lamb"]);
+        t(lf, each_line_any, ~[~"", ~"Mary had a little lamb", ~"Little lamb"]);
+        t(crlf, each_line, ~[~"\r", ~"Mary had a little lamb\r", ~"Little lamb\r"]);
+        t(crlf, each_line_any, ~[~"", ~"Mary had a little lamb", ~"Little lamb"]);
+        t(~"", each_line, ~[]);
+        t(~"", each_line_any, ~[]);
+        t(~"\n", each_line, ~[~""]);
+        t(~"\n", each_line_any, ~[~""]);
+        t(~"banana", each_line, ~[~"banana"]);
+        t(~"banana", each_line_any, ~[~"banana"]);
+    }
+
+    #[test]
+    fn test_words () {
+        fn t(s: &str, f: &fn(&str, &fn(&str) -> bool) -> bool, u: &[~str]) {
+            let mut v = ~[];
+            for f(s) |s| { v.push(s.to_owned()) }
+            assert!(vec::all2(v, u, |a,b| a == b));
+        }
+        let data = ~"\nMary had a little lamb\nLittle lamb\n";
+
+        t(data, each_word, ~[~"Mary",~"had",~"a",~"little",~"lamb",~"Little",~"lamb"]);
+        t(~"ok", each_word, ~[~"ok"]);
+        t(~"", each_word, ~[]);
+    }
+
+    #[test]
+    fn test_split_within() {
+        fn t(s: &str, i: uint, u: &[~str]) {
+            let mut v = ~[];
+            for each_split_within(s, i) |s| { v.push(s.to_owned()) }
+            assert!(vec::all2(v, u, |a,b| a == b));
+        }
+        t(~"", 0, ~[]);
+        t(~"", 15, ~[]);
+        t(~"hello", 15, ~[~"hello"]);
+        t(~"\nMary had a little lamb\nLittle lamb\n", 15,
+            ~[~"Mary had a", ~"little lamb", ~"Little lamb"]);
+    }
+
+    #[test]
+    fn test_find_str() {
+        // byte positions
+        assert!(find_str(~"banana", ~"apple pie").is_none());
+        assert_eq!(find_str(~"", ~""), Some(0u));
+
+        let data = ~"ประเทศไทย中华Việt Nam";
+        assert_eq!(find_str(data, ~""), Some(0u));
+        assert_eq!(find_str(data, ~"ประเ"), Some( 0u));
+        assert_eq!(find_str(data, ~"ะเ"), Some( 6u));
+        assert_eq!(find_str(data, ~"中华"), Some(27u));
+        assert!(find_str(data, ~"ไท华").is_none());
+    }
+
+    #[test]
+    fn test_find_str_between() {
+        // byte positions
+        assert_eq!(find_str_between(~"", ~"", 0u, 0u), Some(0u));
+
+        let data = ~"abcabc";
+        assert_eq!(find_str_between(data, ~"ab", 0u, 6u), Some(0u));
+        assert_eq!(find_str_between(data, ~"ab", 2u, 6u), Some(3u));
+        assert!(find_str_between(data, ~"ab", 2u, 4u).is_none());
+
+        let mut data = ~"ประเทศไทย中华Việt Nam";
+        data = data + data;
+        assert_eq!(find_str_between(data, ~"", 0u, 43u), Some(0u));
+        assert_eq!(find_str_between(data, ~"", 6u, 43u), Some(6u));
+
+        assert_eq!(find_str_between(data, ~"ประ", 0u, 43u), Some( 0u));
+        assert_eq!(find_str_between(data, ~"ทศไ", 0u, 43u), Some(12u));
+        assert_eq!(find_str_between(data, ~"ย中", 0u, 43u), Some(24u));
+        assert_eq!(find_str_between(data, ~"iệt", 0u, 43u), Some(34u));
+        assert_eq!(find_str_between(data, ~"Nam", 0u, 43u), Some(40u));
+
+        assert_eq!(find_str_between(data, ~"ประ", 43u, 86u), Some(43u));
+        assert_eq!(find_str_between(data, ~"ทศไ", 43u, 86u), Some(55u));
+        assert_eq!(find_str_between(data, ~"ย中", 43u, 86u), Some(67u));
+        assert_eq!(find_str_between(data, ~"iệt", 43u, 86u), Some(77u));
+        assert_eq!(find_str_between(data, ~"Nam", 43u, 86u), Some(83u));
+    }
+
+    #[test]
+    fn test_substr() {
+        fn t(a: &str, b: &str, start: int) {
+            assert_eq!(substr(a, start as uint, len(b)), b);
+        }
+        t("hello", "llo", 2);
+        t("hello", "el", 1);
+        assert_eq!("ะเทศไท", substr("ประเทศไทย中华Việt Nam", 6u, 6u));
+    }
+
+    #[test]
+    fn test_concat() {
+        fn t(v: &[~str], s: &str) {
+            assert_eq!(concat(v), s.to_str());
+        }
+        t(~[~"you", ~"know", ~"I'm", ~"no", ~"good"], ~"youknowI'mnogood");
+        let v: ~[~str] = ~[];
+        t(v, ~"");
+        t(~[~"hi"], ~"hi");
+    }
+
+    #[test]
+    fn test_connect() {
+        fn t(v: &[~str], sep: &str, s: &str) {
+            assert_eq!(connect(v, sep), s.to_str());
+        }
+        t(~[~"you", ~"know", ~"I'm", ~"no", ~"good"],
+          ~" ", ~"you know I'm no good");
+        let v: ~[~str] = ~[];
+        t(v, ~" ", ~"");
+        t(~[~"hi"], ~" ", ~"hi");
+    }
+
+    #[test]
+    fn test_connect_slices() {
+        fn t(v: &[&str], sep: &str, s: &str) {
+            assert_eq!(connect_slices(v, sep), s.to_str());
+        }
+        t(["you", "know", "I'm", "no", "good"],
+          " ", "you know I'm no good");
+        t([], " ", "");
+        t(["hi"], " ", "hi");
+    }
+
+    #[test]
+    fn test_repeat() {
+        assert_eq!(repeat(~"x", 4), ~"xxxx");
+        assert_eq!(repeat(~"hi", 4), ~"hihihihi");
+        assert_eq!(repeat(~"ไท华", 3), ~"ไท华ไท华ไท华");
+        assert_eq!(repeat(~"", 4), ~"");
+        assert_eq!(repeat(~"hi", 0), ~"");
+    }
+
+    #[test]
+    fn test_unsafe_slice() {
+        assert_eq!("ab", unsafe {raw::slice_bytes("abc", 0, 2)});
+        assert_eq!("bc", unsafe {raw::slice_bytes("abc", 1, 3)});
+        assert_eq!("", unsafe {raw::slice_bytes("abc", 1, 1)});
+        fn a_million_letter_a() -> ~str {
+            let mut i = 0;
+            let mut rs = ~"";
+            while i < 100000 { push_str(&mut rs, "aaaaaaaaaa"); i += 1; }
+            rs
+        }
+        fn half_a_million_letter_a() -> ~str {
+            let mut i = 0;
+            let mut rs = ~"";
+            while i < 100000 { push_str(&mut rs, "aaaaa"); i += 1; }
+            rs
+        }
+        let letters = a_million_letter_a();
+        assert!(half_a_million_letter_a() ==
+            unsafe {raw::slice_bytes(letters, 0u, 500000)}.to_owned());
+    }
+
+    #[test]
+    fn test_starts_with() {
+        assert!((starts_with(~"", ~"")));
+        assert!((starts_with(~"abc", ~"")));
+        assert!((starts_with(~"abc", ~"a")));
+        assert!((!starts_with(~"a", ~"abc")));
+        assert!((!starts_with(~"", ~"abc")));
+    }
+
+    #[test]
+    fn test_ends_with() {
+        assert!((ends_with(~"", ~"")));
+        assert!((ends_with(~"abc", ~"")));
+        assert!((ends_with(~"abc", ~"c")));
+        assert!((!ends_with(~"a", ~"abc")));
+        assert!((!ends_with(~"", ~"abc")));
+    }
+
+    #[test]
+    fn test_is_empty() {
+        assert!((is_empty(~"")));
+        assert!((!is_empty(~"a")));
+    }
+
+    #[test]
+    fn test_replace() {
+        let a = ~"a";
+        assert_eq!(replace(~"", a, ~"b"), ~"");
+        assert_eq!(replace(~"a", a, ~"b"), ~"b");
+        assert_eq!(replace(~"ab", a, ~"b"), ~"bb");
+        let test = ~"test";
+        assert!(replace(~" test test ", test, ~"toast") ==
+            ~" toast toast ");
+        assert_eq!(replace(~" test test ", test, ~""), ~"   ");
+    }
+
+    #[test]
+    fn test_replace_2a() {
+        let data = ~"ประเทศไทย中华";
+        let repl = ~"دولة الكويت";
+
+        let a = ~"ประเ";
+        let A = ~"دولة الكويتทศไทย中华";
+        assert_eq!(replace(data, a, repl), A);
+    }
+
+    #[test]
+    fn test_replace_2b() {
+        let data = ~"ประเทศไทย中华";
+        let repl = ~"دولة الكويت";
+
+        let b = ~"ะเ";
+        let B = ~"ปรدولة الكويتทศไทย中华";
+        assert_eq!(replace(data, b,   repl), B);
+    }
+
+    #[test]
+    fn test_replace_2c() {
+        let data = ~"ประเทศไทย中华";
+        let repl = ~"دولة الكويت";
+
+        let c = ~"中华";
+        let C = ~"ประเทศไทยدولة الكويت";
+        assert_eq!(replace(data, c, repl), C);
+    }
+
+    #[test]
+    fn test_replace_2d() {
+        let data = ~"ประเทศไทย中华";
+        let repl = ~"دولة الكويت";
+
+        let d = ~"ไท华";
+        assert_eq!(replace(data, d, repl), data);
+    }
+
+    #[test]
+    fn test_slice() {
+        assert_eq!("ab", slice("abc", 0, 2));
+        assert_eq!("bc", slice("abc", 1, 3));
+        assert_eq!("", slice("abc", 1, 1));
+        assert_eq!("\u65e5", slice("\u65e5\u672c", 0, 3));
+
+        let data = "ประเทศไทย中华";
+        assert_eq!("ป", slice(data, 0, 3));
+        assert_eq!("ร", slice(data, 3, 6));
+        assert_eq!("", slice(data, 3, 3));
+        assert_eq!("华", slice(data, 30, 33));
+
+        fn a_million_letter_X() -> ~str {
+            let mut i = 0;
+            let mut rs = ~"";
+            while i < 100000 {
+                push_str(&mut rs, "华华华华华华华华华华");
+                i += 1;
+            }
+            rs
+        }
+        fn half_a_million_letter_X() -> ~str {
+            let mut i = 0;
+            let mut rs = ~"";
+            while i < 100000 { push_str(&mut rs, "华华华华华"); i += 1; }
+            rs
+        }
+        let letters = a_million_letter_X();
+        assert!(half_a_million_letter_X() ==
+            slice(letters, 0u, 3u * 500000u).to_owned());
+    }
+
+    #[test]
+    fn test_slice_2() {
+        let ss = "中华Việt Nam";
+
+        assert_eq!("华", slice(ss, 3u, 6u));
+        assert_eq!("Việt Nam", slice(ss, 6u, 16u));
+
+        assert_eq!("ab", slice("abc", 0u, 2u));
+        assert_eq!("bc", slice("abc", 1u, 3u));
+        assert_eq!("", slice("abc", 1u, 1u));
+
+        assert_eq!("中", slice(ss, 0u, 3u));
+        assert_eq!("华V", slice(ss, 3u, 7u));
+        assert_eq!("", slice(ss, 3u, 3u));
+        /*0: 中
+          3: 华
+          6: V
+          7: i
+          8: ệ
+         11: t
+         12:
+         13: N
+         14: a
+         15: m */
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_slice_fail() {
+        slice("中华Việt Nam", 0u, 2u);
+    }
+
+    #[test]
+    fn test_trim_left_chars() {
+        assert!(trim_left_chars(" *** foo *** ", ~[]) ==
+                     " *** foo *** ");
+        assert!(trim_left_chars(" *** foo *** ", ~['*', ' ']) ==
+                     "foo *** ");
+        assert_eq!(trim_left_chars(" ***  *** ", ~['*', ' ']), "");
+        assert!(trim_left_chars("foo *** ", ~['*', ' ']) ==
+                     "foo *** ");
+    }
+
+    #[test]
+    fn test_trim_right_chars() {
+        assert!(trim_right_chars(" *** foo *** ", ~[]) ==
+                     " *** foo *** ");
+        assert!(trim_right_chars(" *** foo *** ", ~['*', ' ']) ==
+                     " *** foo");
+        assert_eq!(trim_right_chars(" ***  *** ", ~['*', ' ']), "");
+        assert!(trim_right_chars(" *** foo", ~['*', ' ']) ==
+                     " *** foo");
+    }
+
+    #[test]
+    fn test_trim_chars() {
+        assert_eq!(trim_chars(" *** foo *** ", ~[]), " *** foo *** ");
+        assert_eq!(trim_chars(" *** foo *** ", ~['*', ' ']), "foo");
+        assert_eq!(trim_chars(" ***  *** ", ~['*', ' ']), "");
+        assert_eq!(trim_chars("foo", ~['*', ' ']), "foo");
+    }
+
+    #[test]
+    fn test_trim_left() {
+        assert_eq!(trim_left(""), "");
+        assert_eq!(trim_left("a"), "a");
+        assert_eq!(trim_left("    "), "");
+        assert_eq!(trim_left("     blah"), "blah");
+        assert_eq!(trim_left("   \u3000  wut"), "wut");
+        assert_eq!(trim_left("hey "), "hey ");
+    }
+
+    #[test]
+    fn test_trim_right() {
+        assert_eq!(trim_right(""), "");
+        assert_eq!(trim_right("a"), "a");
+        assert_eq!(trim_right("    "), "");
+        assert_eq!(trim_right("blah     "), "blah");
+        assert_eq!(trim_right("wut   \u3000  "), "wut");
+        assert_eq!(trim_right(" hey"), " hey");
+    }
+
+    #[test]
+    fn test_trim() {
+        assert_eq!(trim(""), "");
+        assert_eq!(trim("a"), "a");
+        assert_eq!(trim("    "), "");
+        assert_eq!(trim("    blah     "), "blah");
+        assert_eq!(trim("\nwut   \u3000  "), "wut");
+        assert_eq!(trim(" hey dude "), "hey dude");
+    }
+
+    #[test]
+    fn test_is_whitespace() {
+        assert!((is_whitespace(~"")));
+        assert!((is_whitespace(~" ")));
+        assert!((is_whitespace(~"\u2009"))); // Thin space
+        assert!((is_whitespace(~"  \n\t   ")));
+        assert!((!is_whitespace(~"   _   ")));
+    }
+
+    #[test]
+    fn test_shift_byte() {
+        let mut s = ~"ABC";
+        let b = unsafe{raw::shift_byte(&mut s)};
+        assert_eq!(s, ~"BC");
+        assert_eq!(b, 65u8);
+    }
+
+    #[test]
+    fn test_pop_byte() {
+        let mut s = ~"ABC";
+        let b = unsafe{raw::pop_byte(&mut s)};
+        assert_eq!(s, ~"AB");
+        assert_eq!(b, 67u8);
+    }
+
+    #[test]
+    fn test_unsafe_from_bytes() {
+        let a = ~[65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8];
+        let b = unsafe { raw::from_bytes(a) };
+        assert_eq!(b, ~"AAAAAAA");
+    }
+
+    #[test]
+    fn test_from_bytes() {
+        let ss = ~"ศไทย中华Việt Nam";
+        let bb = ~[0xe0_u8, 0xb8_u8, 0xa8_u8,
+                  0xe0_u8, 0xb9_u8, 0x84_u8,
+                  0xe0_u8, 0xb8_u8, 0x97_u8,
+                  0xe0_u8, 0xb8_u8, 0xa2_u8,
+                  0xe4_u8, 0xb8_u8, 0xad_u8,
+                  0xe5_u8, 0x8d_u8, 0x8e_u8,
+                  0x56_u8, 0x69_u8, 0xe1_u8,
+                  0xbb_u8, 0x87_u8, 0x74_u8,
+                  0x20_u8, 0x4e_u8, 0x61_u8,
+                  0x6d_u8];
+
+        assert_eq!(ss, from_bytes(bb));
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_from_bytes_fail() {
+        let bb = ~[0xff_u8, 0xb8_u8, 0xa8_u8,
+                  0xe0_u8, 0xb9_u8, 0x84_u8,
+                  0xe0_u8, 0xb8_u8, 0x97_u8,
+                  0xe0_u8, 0xb8_u8, 0xa2_u8,
+                  0xe4_u8, 0xb8_u8, 0xad_u8,
+                  0xe5_u8, 0x8d_u8, 0x8e_u8,
+                  0x56_u8, 0x69_u8, 0xe1_u8,
+                  0xbb_u8, 0x87_u8, 0x74_u8,
+                  0x20_u8, 0x4e_u8, 0x61_u8,
+                  0x6d_u8];
+
+         let _x = from_bytes(bb);
+    }
+
+    #[test]
+    fn test_unsafe_from_bytes_with_null() {
+        let a = [65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
+        let b = unsafe { raw::from_bytes_with_null(a) };
+        assert_eq!(b, "AAAAAAA");
+    }
+
+    #[test]
+    fn test_from_bytes_with_null() {
+        let ss = "ศไทย中华Việt Nam";
+        let bb = [0xe0_u8, 0xb8_u8, 0xa8_u8,
+                  0xe0_u8, 0xb9_u8, 0x84_u8,
+                  0xe0_u8, 0xb8_u8, 0x97_u8,
+                  0xe0_u8, 0xb8_u8, 0xa2_u8,
+                  0xe4_u8, 0xb8_u8, 0xad_u8,
+                  0xe5_u8, 0x8d_u8, 0x8e_u8,
+                  0x56_u8, 0x69_u8, 0xe1_u8,
+                  0xbb_u8, 0x87_u8, 0x74_u8,
+                  0x20_u8, 0x4e_u8, 0x61_u8,
+                  0x6d_u8, 0x0_u8];
+
+        assert_eq!(ss, from_bytes_with_null(bb));
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_from_bytes_with_null_fail() {
+        let bb = [0xff_u8, 0xb8_u8, 0xa8_u8,
+                  0xe0_u8, 0xb9_u8, 0x84_u8,
+                  0xe0_u8, 0xb8_u8, 0x97_u8,
+                  0xe0_u8, 0xb8_u8, 0xa2_u8,
+                  0xe4_u8, 0xb8_u8, 0xad_u8,
+                  0xe5_u8, 0x8d_u8, 0x8e_u8,
+                  0x56_u8, 0x69_u8, 0xe1_u8,
+                  0xbb_u8, 0x87_u8, 0x74_u8,
+                  0x20_u8, 0x4e_u8, 0x61_u8,
+                  0x6d_u8, 0x0_u8];
+
+         let _x = from_bytes_with_null(bb);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_from_bytes_with_null_fail_2() {
+        let bb = [0xff_u8, 0xb8_u8, 0xa8_u8,
+                  0xe0_u8, 0xb9_u8, 0x84_u8,
+                  0xe0_u8, 0xb8_u8, 0x97_u8,
+                  0xe0_u8, 0xb8_u8, 0xa2_u8,
+                  0xe4_u8, 0xb8_u8, 0xad_u8,
+                  0xe5_u8, 0x8d_u8, 0x8e_u8,
+                  0x56_u8, 0x69_u8, 0xe1_u8,
+                  0xbb_u8, 0x87_u8, 0x74_u8,
+                  0x20_u8, 0x4e_u8, 0x61_u8,
+                  0x6d_u8, 0x60_u8];
+
+         let _x = from_bytes_with_null(bb);
+    }
+
+    #[test]
+    fn test_from_buf() {
+        unsafe {
+            let a = ~[65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 65u8, 0u8];
+            let b = vec::raw::to_ptr(a);
+            let c = raw::from_buf(b);
+            assert_eq!(c, ~"AAAAAAA");
+        }
+    }
+
+    #[test]
+    #[ignore(cfg(windows))]
+    #[should_fail]
+    fn test_as_bytes_fail() {
+        // Don't double free
+        as_bytes::<()>(&~"", |_bytes| fail!() );
+    }
+
+    #[test]
+    fn test_as_buf() {
+        let a = ~"Abcdefg";
+        let b = as_buf(a, |buf, _l| {
+            assert_eq!(unsafe { *buf }, 65u8);
+            100
+        });
+        assert_eq!(b, 100);
+    }
+
+    #[test]
+    fn test_as_buf_small() {
+        let a = ~"A";
+        let b = as_buf(a, |buf, _l| {
+            assert_eq!(unsafe { *buf }, 65u8);
+            100
+        });
+        assert_eq!(b, 100);
+    }
+
+    #[test]
+    fn test_as_buf2() {
+        unsafe {
+            let s = ~"hello";
+            let sb = as_buf(s, |b, _l| b);
+            let s_cstr = raw::from_buf(sb);
+            assert_eq!(s_cstr, s);
+        }
+    }
+
+    #[test]
+    fn test_as_buf_3() {
+        let a = ~"hello";
+        do as_buf(a) |buf, len| {
+            unsafe {
+                assert_eq!(a[0], 'h' as u8);
+                assert_eq!(*buf, 'h' as u8);
+                assert_eq!(len, 6u);
+                assert_eq!(*ptr::offset(buf,4u), 'o' as u8);
+                assert_eq!(*ptr::offset(buf,5u), 0u8);
+            }
+        }
+    }
+
+    #[test]
+    fn test_subslice_offset() {
+        let a = "kernelsprite";
+        let b = slice(a, 7, len(a));
+        let c = slice(a, 0, len(a) - 6);
+        assert_eq!(subslice_offset(a, b), 7);
+        assert_eq!(subslice_offset(a, c), 0);
+
+        let string = "a\nb\nc";
+        let mut lines = ~[];
+        for each_line(string) |line| { lines.push(line) }
+        assert_eq!(subslice_offset(string, lines[0]), 0);
+        assert_eq!(subslice_offset(string, lines[1]), 2);
+        assert_eq!(subslice_offset(string, lines[2]), 4);
+    }
+
+    #[test]
+    #[should_fail]
+    fn test_subslice_offset_2() {
+        let a = "alchemiter";
+        let b = "cruxtruder";
+        subslice_offset(a, b);
+    }
+
+    #[test]
+    fn vec_str_conversions() {
+        let s1: ~str = ~"All mimsy were the borogoves";
+
+        let v: ~[u8] = to_bytes(s1);
+        let s2: ~str = from_bytes(v);
+        let mut i: uint = 0u;
+        let n1: uint = len(s1);
+        let n2: uint = vec::len::<u8>(v);
+        assert_eq!(n1, n2);
+        while i < n1 {
+            let a: u8 = s1[i];
+            let b: u8 = s2[i];
+            debug!(a);
+            debug!(b);
+            assert_eq!(a, b);
+            i += 1u;
+        }
+    }
+
+    #[test]
+    fn test_contains() {
+        assert!(contains(~"abcde", ~"bcd"));
+        assert!(contains(~"abcde", ~"abcd"));
+        assert!(contains(~"abcde", ~"bcde"));
+        assert!(contains(~"abcde", ~""));
+        assert!(contains(~"", ~""));
+        assert!(!contains(~"abcde", ~"def"));
+        assert!(!contains(~"", ~"a"));
+
+        let data = ~"ประเทศไทย中华Việt Nam";
+        assert!(contains(data, ~"ประเ"));
+        assert!(contains(data, ~"ะเ"));
+        assert!(contains(data, ~"中华"));
+        assert!(!contains(data, ~"ไท华"));
+    }
+
+    #[test]
+    fn test_contains_char() {
+        assert!(contains_char(~"abc", 'b'));
+        assert!(contains_char(~"a", 'a'));
+        assert!(!contains_char(~"abc", 'd'));
+        assert!(!contains_char(~"", 'a'));
+    }
+
+    #[test]
+    fn test_split_char_each() {
+        let data = ~"\nMary had a little lamb\nLittle lamb\n";
+
+        let mut ii = 0;
+
+        for each_split_char(data, ' ') |xx| {
+            match ii {
+              0 => assert!("\nMary" == xx),
+              1 => assert!("had"    == xx),
+              2 => assert!("a"      == xx),
+              3 => assert!("little" == xx),
+              _ => ()
+            }
+            ii += 1;
+        }
+    }
+
+    #[test]
+    fn test_splitn_char_each() {
+        let data = ~"\nMary had a little lamb\nLittle lamb\n";
+
+        let mut ii = 0;
+
+        for each_splitn_char(data, ' ', 2u) |xx| {
+            match ii {
+              0 => assert!("\nMary" == xx),
+              1 => assert!("had"    == xx),
+              2 => assert!("a little lamb\nLittle lamb\n" == xx),
+              _ => ()
+            }
+            ii += 1;
+        }
+    }
+
+    #[test]
+    fn test_words_each() {
+        let data = ~"\nMary had a little lamb\nLittle lamb\n";
+
+        let mut ii = 0;
+
+        for each_word(data) |ww| {
+            match ii {
+              0 => assert!("Mary"   == ww),
+              1 => assert!("had"    == ww),
+              2 => assert!("a"      == ww),
+              3 => assert!("little" == ww),
+              _ => ()
+            }
+            ii += 1;
+        }
+
+        each_word(~"", |_x| fail!()); // should not fail
+    }
+
+    #[test]
+    fn test_lines_each () {
+        let lf = ~"\nMary had a little lamb\nLittle lamb\n";
+
+        let mut ii = 0;
+
+        for each_line(lf) |x| {
+            match ii {
+                0 => assert!("" == x),
+                1 => assert!("Mary had a little lamb" == x),
+                2 => assert!("Little lamb" == x),
+                _ => ()
+            }
+            ii += 1;
+        }
+    }
+
+    #[test]
+    fn test_map() {
+        assert_eq!(~"", map(~"", |c| unsafe {libc::toupper(c as c_char)} as char));
+        assert_eq!(~"YMCA", map(~"ymca", |c| unsafe {libc::toupper(c as c_char)} as char));
+    }
+
+    #[test]
+    fn test_all() {
+        assert_eq!(true, all(~"", char::is_uppercase));
+        assert_eq!(false, all(~"ymca", char::is_uppercase));
+        assert_eq!(true, all(~"YMCA", char::is_uppercase));
+        assert_eq!(false, all(~"yMCA", char::is_uppercase));
+        assert_eq!(false, all(~"YMCy", char::is_uppercase));
+    }
+
+    #[test]
+    fn test_any() {
+        assert_eq!(false, any(~"", char::is_uppercase));
+        assert_eq!(false, any(~"ymca", char::is_uppercase));
+        assert_eq!(true, any(~"YMCA", char::is_uppercase));
+        assert_eq!(true, any(~"yMCA", char::is_uppercase));
+        assert_eq!(true, any(~"Ymcy", char::is_uppercase));
+    }
+
+    #[test]
+    fn test_chars() {
+        let ss = ~"ศไทย中华Việt Nam";
+        assert!(~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a',
+                       'm']
+            == to_chars(ss));
+    }
+
+    #[test]
+    fn test_utf16() {
+        let pairs =
+            ~[(~"𐍅𐌿𐌻𐍆𐌹𐌻𐌰\n",
+              ~[0xd800_u16, 0xdf45_u16, 0xd800_u16, 0xdf3f_u16,
+               0xd800_u16, 0xdf3b_u16, 0xd800_u16, 0xdf46_u16,
+               0xd800_u16, 0xdf39_u16, 0xd800_u16, 0xdf3b_u16,
+               0xd800_u16, 0xdf30_u16, 0x000a_u16]),
+
+             (~"𐐒𐑉𐐮𐑀𐐲𐑋 𐐏𐐲𐑍\n",
+              ~[0xd801_u16, 0xdc12_u16, 0xd801_u16,
+               0xdc49_u16, 0xd801_u16, 0xdc2e_u16, 0xd801_u16,
+               0xdc40_u16, 0xd801_u16, 0xdc32_u16, 0xd801_u16,
+               0xdc4b_u16, 0x0020_u16, 0xd801_u16, 0xdc0f_u16,
+               0xd801_u16, 0xdc32_u16, 0xd801_u16, 0xdc4d_u16,
+               0x000a_u16]),
+
+             (~"𐌀𐌖𐌋𐌄𐌑𐌉·𐌌𐌄𐌕𐌄𐌋𐌉𐌑\n",
+              ~[0xd800_u16, 0xdf00_u16, 0xd800_u16, 0xdf16_u16,
+               0xd800_u16, 0xdf0b_u16, 0xd800_u16, 0xdf04_u16,
+               0xd800_u16, 0xdf11_u16, 0xd800_u16, 0xdf09_u16,
+               0x00b7_u16, 0xd800_u16, 0xdf0c_u16, 0xd800_u16,
+               0xdf04_u16, 0xd800_u16, 0xdf15_u16, 0xd800_u16,
+               0xdf04_u16, 0xd800_u16, 0xdf0b_u16, 0xd800_u16,
+               0xdf09_u16, 0xd800_u16, 0xdf11_u16, 0x000a_u16 ]),
+
+             (~"𐒋𐒘𐒈𐒑𐒛𐒒 𐒕𐒓 𐒈𐒚𐒍 𐒏𐒜𐒒𐒖𐒆 𐒕𐒆\n",
+              ~[0xd801_u16, 0xdc8b_u16, 0xd801_u16, 0xdc98_u16,
+               0xd801_u16, 0xdc88_u16, 0xd801_u16, 0xdc91_u16,
+               0xd801_u16, 0xdc9b_u16, 0xd801_u16, 0xdc92_u16,
+               0x0020_u16, 0xd801_u16, 0xdc95_u16, 0xd801_u16,
+               0xdc93_u16, 0x0020_u16, 0xd801_u16, 0xdc88_u16,
+               0xd801_u16, 0xdc9a_u16, 0xd801_u16, 0xdc8d_u16,
+               0x0020_u16, 0xd801_u16, 0xdc8f_u16, 0xd801_u16,
+               0xdc9c_u16, 0xd801_u16, 0xdc92_u16, 0xd801_u16,
+               0xdc96_u16, 0xd801_u16, 0xdc86_u16, 0x0020_u16,
+               0xd801_u16, 0xdc95_u16, 0xd801_u16, 0xdc86_u16,
+               0x000a_u16 ]) ];
+
+        for pairs.each |p| {
+            let (s, u) = copy *p;
+            assert!(to_utf16(s) == u);
+            assert!(from_utf16(u) == s);
+            assert!(from_utf16(to_utf16(s)) == s);
+            assert!(to_utf16(from_utf16(u)) == u);
+        }
+    }
+
+    #[test]
+    fn test_char_at() {
+        let s = ~"ศไทย中华Việt Nam";
+        let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
+        let mut pos = 0;
+        for v.each |ch| {
+            assert!(s.char_at(pos) == *ch);
+            pos += from_char(*ch).len();
+        }
+    }
+
+    #[test]
+    fn test_char_at_reverse() {
+        let s = ~"ศไทย中华Việt Nam";
+        let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
+        let mut pos = s.len();
+        for v.each_reverse |ch| {
+            assert!(s.char_at_reverse(pos) == *ch);
+            pos -= from_char(*ch).len();
+        }
+    }
+
+    #[test]
+    fn test_each() {
+        let s = ~"ศไทย中华Việt Nam";
+        let v = [
+            224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
+            184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
+            109
+        ];
+        let mut pos = 0;
+
+        for s.each |b| {
+            assert_eq!(b, v[pos]);
+            pos += 1;
+        }
+    }
+
+    #[test]
+    fn test_each_empty() {
+        for "".each |b| {
+            assert_eq!(b, 0u8);
+        }
+    }
+
+    #[test]
+    fn test_eachi() {
+        let s = ~"ศไทย中华Việt Nam";
+        let v = [
+            224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
+            184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
+            109
+        ];
+        let mut pos = 0;
+
+        for s.eachi |i, b| {
+            assert_eq!(pos, i);
+            assert_eq!(b, v[pos]);
+            pos += 1;
+        }
+    }
+
+    #[test]
+    fn test_eachi_empty() {
+        for "".eachi |i, b| {
+            assert_eq!(i, 0);
+            assert_eq!(b, 0);
+        }
+    }
+
+    #[test]
+    fn test_each_reverse() {
+        let s = ~"ศไทย中华Việt Nam";
+        let v = [
+            224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
+            184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
+            109
+        ];
+        let mut pos = v.len();
+
+        for s.each_reverse |b| {
+            pos -= 1;
+            assert_eq!(b, v[pos]);
+        }
+    }
+
+    #[test]
+    fn test_each_empty_reverse() {
+        for "".each_reverse |b| {
+            assert_eq!(b, 0u8);
+        }
+    }
+
+    #[test]
+    fn test_eachi_reverse() {
+        let s = ~"ศไทย中华Việt Nam";
+        let v = [
+            224, 184, 168, 224, 185, 132, 224, 184, 151, 224, 184, 162, 228,
+            184, 173, 229, 141, 142, 86, 105, 225, 187, 135, 116, 32, 78, 97,
+            109
+        ];
+        let mut pos = v.len();
+
+        for s.eachi_reverse |i, b| {
+            pos -= 1;
+            assert_eq!(pos, i);
+            assert_eq!(b, v[pos]);
+        }
+    }
+
+    #[test]
+    fn test_eachi_reverse_empty() {
+        for "".eachi_reverse |i, b| {
+            assert_eq!(i, 0);
+            assert_eq!(b, 0);
+        }
+    }
+
+    #[test]
+    fn test_each_char() {
+        let s = ~"ศไทย中华Việt Nam";
+        let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
+        let mut pos = 0;
+        for s.each_char |ch| {
+            assert_eq!(ch, v[pos]);
+            pos += 1;
+        }
+    }
+
+    #[test]
+    fn test_each_chari() {
+        let s = ~"ศไทย中华Việt Nam";
+        let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
+        let mut pos = 0;
+        for s.each_chari |i, ch| {
+            assert_eq!(pos, i);
+            assert_eq!(ch, v[pos]);
+            pos += 1;
+        }
+    }
+
+    #[test]
+    fn test_each_char_reverse() {
+        let s = ~"ศไทย中华Việt Nam";
+        let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
+        let mut pos = v.len();
+        for s.each_char_reverse |ch| {
+            pos -= 1;
+            assert_eq!(ch, v[pos]);
+        }
+    }
+
+    #[test]
+    fn test_each_chari_reverse() {
+        let s = ~"ศไทย中华Việt Nam";
+        let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
+        let mut pos = v.len();
+        for s.each_chari_reverse |i, ch| {
+            pos -= 1;
+            assert_eq!(pos, i);
+            assert_eq!(ch, v[pos]);
+        }
+    }
+
+    #[test]
+    fn test_escape_unicode() {
+        assert_eq!(escape_unicode(~"abc"), ~"\\x61\\x62\\x63");
+        assert_eq!(escape_unicode(~"a c"), ~"\\x61\\x20\\x63");
+        assert_eq!(escape_unicode(~"\r\n\t"), ~"\\x0d\\x0a\\x09");
+        assert_eq!(escape_unicode(~"'\"\\"), ~"\\x27\\x22\\x5c");
+        assert!(escape_unicode(~"\x00\x01\xfe\xff") ==
+                     ~"\\x00\\x01\\xfe\\xff");
+        assert_eq!(escape_unicode(~"\u0100\uffff"), ~"\\u0100\\uffff");
+        assert!(escape_unicode(~"\U00010000\U0010ffff") ==
+            ~"\\U00010000\\U0010ffff");
+        assert_eq!(escape_unicode(~"ab\ufb00"), ~"\\x61\\x62\\ufb00");
+        assert_eq!(escape_unicode(~"\U0001d4ea\r"), ~"\\U0001d4ea\\x0d");
+    }
+
+    #[test]
+    fn test_escape_default() {
+        assert_eq!(escape_default(~"abc"), ~"abc");
+        assert_eq!(escape_default(~"a c"), ~"a c");
+        assert_eq!(escape_default(~"\r\n\t"), ~"\\r\\n\\t");
+        assert_eq!(escape_default(~"'\"\\"), ~"\\'\\\"\\\\");
+        assert_eq!(escape_default(~"\u0100\uffff"), ~"\\u0100\\uffff");
+        assert!(escape_default(~"\U00010000\U0010ffff") ==
+            ~"\\U00010000\\U0010ffff");
+        assert_eq!(escape_default(~"ab\ufb00"), ~"ab\\ufb00");
+        assert_eq!(escape_default(~"\U0001d4ea\r"), ~"\\U0001d4ea\\r");
+    }
+
+    #[test]
+    fn test_to_managed() {
+        assert_eq!((~"abc").to_managed(), @"abc");
+        assert_eq!(slice("abcdef", 1, 5).to_managed(), @"bcde");
+    }
+
+    #[test]
+    fn test_total_ord() {
+        "1234".cmp(& &"123") == Greater;
+        "123".cmp(& &"1234") == Less;
+        "1234".cmp(& &"1234") == Equal;
+        "12345555".cmp(& &"123456") == Less;
+        "22".cmp(& &"1234") == Greater;
+    }
+
+    #[test]
+    fn test_char_range_at_reverse_underflow() {
+        assert_eq!(char_range_at_reverse("abc", 0).next, 0);
+    }
+
+    #[test]
+    fn test_iterator() {
+        use iterator::*;
+        let s = ~"ศไทย中华Việt Nam";
+        let v = ~['ศ','ไ','ท','ย','中','华','V','i','ệ','t',' ','N','a','m'];
+
+        let mut pos = 0;
+        let mut it = s.char_iter();
+
+        for it.advance |c| {
+            assert_eq!(c, v[pos]);
+            pos += 1;
+        }
+        assert_eq!(pos, v.len());
+    }
+}
diff --git a/src/libstd/str/ascii.rs b/src/libstd/str/ascii.rs
new file mode 100644
index 00000000000..4e239c4c82c
--- /dev/null
+++ b/src/libstd/str/ascii.rs
@@ -0,0 +1,287 @@
+// 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.
+
+//! Operations on ASCII strings and characters.
+
+use to_str::{ToStr,ToStrConsume};
+use str;
+use str::StrSlice;
+use cast;
+use old_iter::BaseIter;
+use vec::{CopyableVector, ImmutableVector, OwnedVector};
+
+/// Datatype to hold one ascii character. It is 8 bit long.
+#[deriving(Clone, Eq)]
+pub struct Ascii { priv chr: u8 }
+
+pub impl Ascii {
+    /// Converts a ascii character into a `u8`.
+    #[inline(always)]
+    fn to_byte(self) -> u8 {
+        self.chr
+    }
+
+    /// Converts a ascii character into a `char`.
+    #[inline(always)]
+    fn to_char(self) -> char {
+        self.chr as char
+    }
+
+    /// Convert to lowercase.
+    #[inline(always)]
+    fn to_lower(self) -> Ascii {
+        if self.chr >= 65 && self.chr <= 90 {
+            Ascii{chr: self.chr | 0x20 }
+        } else {
+            self
+        }
+    }
+
+    /// Convert to uppercase.
+    #[inline(always)]
+    fn to_upper(self) -> Ascii {
+        if self.chr >= 97 && self.chr <= 122 {
+            Ascii{chr: self.chr & !0x20 }
+        } else {
+            self
+        }
+    }
+
+    // Compares two ascii characters of equality, ignoring case.
+    #[inline(always)]
+    fn eq_ignore_case(self, other: Ascii) -> bool {
+        self.to_lower().chr == other.to_lower().chr
+    }
+}
+
+impl ToStr for Ascii {
+    #[inline(always)]
+    fn to_str(&self) -> ~str { str::from_bytes(['\'' as u8, self.chr, '\'' as u8]) }
+}
+
+/// Trait for converting into an ascii type.
+pub trait AsciiCast<T> {
+    /// Convert to an ascii type
+    fn to_ascii(&self) -> T;
+
+    /// Check if convertible to ascii
+    fn is_ascii(&self) -> bool;
+}
+
+impl<'self> AsciiCast<&'self[Ascii]> for &'self [u8] {
+    #[inline(always)]
+    fn to_ascii(&self) -> &'self[Ascii] {
+        assert!(self.is_ascii());
+        unsafe{ cast::transmute(*self) }
+    }
+
+    #[inline(always)]
+    fn is_ascii(&self) -> bool {
+        for self.each |b| {
+            if !b.is_ascii() { return false; }
+        }
+        true
+    }
+}
+
+impl<'self> AsciiCast<&'self[Ascii]> for &'self str {
+    #[inline(always)]
+    fn to_ascii(&self) -> &'self[Ascii] {
+        assert!(self.is_ascii());
+        let (p,len): (*u8, uint) = unsafe{ cast::transmute(*self) };
+        unsafe{ cast::transmute((p, len - 1))}
+    }
+
+    #[inline(always)]
+    fn is_ascii(&self) -> bool {
+        for self.each |b| {
+            if !b.is_ascii() { return false; }
+        }
+        true
+    }
+}
+
+impl AsciiCast<Ascii> for u8 {
+    #[inline(always)]
+    fn to_ascii(&self) -> Ascii {
+        assert!(self.is_ascii());
+        Ascii{ chr: *self }
+    }
+
+    #[inline(always)]
+    fn is_ascii(&self) -> bool {
+        *self & 128 == 0u8
+    }
+}
+
+impl AsciiCast<Ascii> for char {
+    #[inline(always)]
+    fn to_ascii(&self) -> Ascii {
+        assert!(self.is_ascii());
+        Ascii{ chr: *self as u8 }
+    }
+
+    #[inline(always)]
+    fn is_ascii(&self) -> bool {
+        *self - ('\x7F' & *self) == '\x00'
+    }
+}
+
+/// Trait for copyless casting to an ascii vector.
+pub trait OwnedAsciiCast {
+    /// Take ownership and cast to an ascii vector without trailing zero element.
+    fn to_ascii_consume(self) -> ~[Ascii];
+}
+
+impl OwnedAsciiCast for ~[u8] {
+    #[inline(always)]
+    fn to_ascii_consume(self) -> ~[Ascii] {
+        assert!(self.is_ascii());
+        unsafe {cast::transmute(self)}
+    }
+}
+
+impl OwnedAsciiCast for ~str {
+    #[inline(always)]
+    fn to_ascii_consume(self) -> ~[Ascii] {
+        assert!(self.is_ascii());
+        let mut s = self;
+        unsafe {
+            str::raw::pop_byte(&mut s);
+            cast::transmute(s)
+        }
+    }
+}
+
+/// Trait for converting an ascii type to a string. Needed to convert `&[Ascii]` to `~str`
+pub trait AsciiStr {
+    /// Convert to a string.
+    fn to_str_ascii(&self) -> ~str;
+
+    /// Convert to vector representing a lower cased ascii string.
+    fn to_lower(&self) -> ~[Ascii];
+
+    /// Convert to vector representing a upper cased ascii string.
+    fn to_upper(&self) -> ~[Ascii];
+
+}
+
+impl<'self> AsciiStr for &'self [Ascii] {
+    #[inline(always)]
+    fn to_str_ascii(&self) -> ~str {
+        let mut cpy = self.to_owned();
+        cpy.push(0u8.to_ascii());
+        unsafe {cast::transmute(cpy)}
+    }
+
+    #[inline(always)]
+    fn to_lower(&self) -> ~[Ascii] {
+        self.map(|a| a.to_lower())
+    }
+
+    #[inline(always)]
+    fn to_upper(&self) -> ~[Ascii] {
+        self.map(|a| a.to_upper())
+    }
+}
+
+impl ToStrConsume for ~[Ascii] {
+    #[inline(always)]
+    fn to_str_consume(self) -> ~str {
+        let mut cpy = self;
+        cpy.push(0u8.to_ascii());
+        unsafe {cast::transmute(cpy)}
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use str;
+
+    macro_rules! v2ascii (
+        ( [$($e:expr),*]) => ( [$(Ascii{chr:$e}),*]);
+        (~[$($e:expr),*]) => (~[$(Ascii{chr:$e}),*]);
+    )
+
+    #[test]
+    fn test_ascii() {
+        assert_eq!(65u8.to_ascii().to_byte(), 65u8);
+        assert_eq!(65u8.to_ascii().to_char(), 'A');
+        assert_eq!('A'.to_ascii().to_char(), 'A');
+        assert_eq!('A'.to_ascii().to_byte(), 65u8);
+
+        assert_eq!('A'.to_ascii().to_lower().to_char(), 'a');
+        assert_eq!('Z'.to_ascii().to_lower().to_char(), 'z');
+        assert_eq!('a'.to_ascii().to_upper().to_char(), 'A');
+        assert_eq!('z'.to_ascii().to_upper().to_char(), 'Z');
+
+        assert_eq!('@'.to_ascii().to_lower().to_char(), '@');
+        assert_eq!('['.to_ascii().to_lower().to_char(), '[');
+        assert_eq!('`'.to_ascii().to_upper().to_char(), '`');
+        assert_eq!('{'.to_ascii().to_upper().to_char(), '{');
+
+        assert!(str::all(~"banana", |c| c.is_ascii()));
+        assert!(! str::all(~"ประเทศไทย中华Việt Nam", |c| c.is_ascii()));
+    }
+
+    #[test]
+    fn test_ascii_vec() {
+        assert_eq!((&[40u8, 32u8, 59u8]).to_ascii(), v2ascii!([40, 32, 59]));
+        assert_eq!("( ;".to_ascii(),                 v2ascii!([40, 32, 59]));
+        // FIXME: #5475 borrowchk error, owned vectors do not live long enough
+        // if chained-from directly
+        let v = ~[40u8, 32u8, 59u8]; assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
+        let v = ~"( ;";              assert_eq!(v.to_ascii(), v2ascii!([40, 32, 59]));
+
+        assert_eq!("abCDef&?#".to_ascii().to_lower().to_str_ascii(), ~"abcdef&?#");
+        assert_eq!("abCDef&?#".to_ascii().to_upper().to_str_ascii(), ~"ABCDEF&?#");
+
+        assert_eq!("".to_ascii().to_lower().to_str_ascii(), ~"");
+        assert_eq!("YMCA".to_ascii().to_lower().to_str_ascii(), ~"ymca");
+        assert_eq!("abcDEFxyz:.;".to_ascii().to_upper().to_str_ascii(), ~"ABCDEFXYZ:.;");
+
+        assert!("".is_ascii());
+        assert!("a".is_ascii());
+        assert!(!"\u2009".is_ascii());
+
+    }
+
+    #[test]
+    fn test_owned_ascii_vec() {
+        // FIXME: #4318 Compiler crashes on moving self
+        //assert_eq!(~"( ;".to_ascii_consume(), v2ascii!(~[40, 32, 59]));
+        //assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume(), v2ascii!(~[40, 32, 59]));
+        //assert_eq!(~"( ;".to_ascii_consume_with_null(), v2ascii!(~[40, 32, 59, 0]));
+        //assert_eq!(~[40u8, 32u8, 59u8].to_ascii_consume_with_null(),
+        //           v2ascii!(~[40, 32, 59, 0]));
+    }
+
+    #[test]
+    fn test_ascii_to_str() { assert_eq!(v2ascii!([40, 32, 59]).to_str_ascii(), ~"( ;"); }
+
+    #[test]
+    fn test_ascii_to_str_consume() {
+        // FIXME: #4318 Compiler crashes on moving self
+        //assert_eq!(v2ascii!(~[40, 32, 59]).to_str_consume(), ~"( ;");
+    }
+
+    #[test] #[should_fail]
+    fn test_ascii_vec_fail_u8_slice()  { (&[127u8, 128u8, 255u8]).to_ascii(); }
+
+    #[test] #[should_fail]
+    fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); }
+
+    #[test] #[should_fail]
+    fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); }
+
+    #[test] #[should_fail]
+    fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
+}
diff --git a/src/libstd/sync.rs b/src/libstd/sync.rs
deleted file mode 100644
index 002c6b2eca3..00000000000
--- a/src/libstd/sync.rs
+++ /dev/null
@@ -1,1351 +0,0 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/**
- * The concurrency primitives you know and love.
- *
- * Maybe once we have a "core exports x only to std" mechanism, these can be
- * in std.
- */
-
-use core::unstable::sync::{Exclusive, exclusive};
-use core::ptr;
-use core::task;
-use core::util;
-
-/****************************************************************************
- * Internals
- ****************************************************************************/
-
-// Each waiting task receives on one of these.
-#[doc(hidden)]
-type WaitEnd = comm::PortOne<()>;
-#[doc(hidden)]
-type SignalEnd = comm::ChanOne<()>;
-// A doubly-ended queue of waiting tasks.
-#[doc(hidden)]
-struct Waitqueue { head: comm::Port<SignalEnd>,
-                   tail: comm::Chan<SignalEnd> }
-
-fn new_waitqueue() -> Waitqueue {
-    let (block_head, block_tail) = comm::stream();
-    Waitqueue { head: block_head, tail: block_tail }
-}
-
-// Signals one live task from the queue.
-#[doc(hidden)]
-fn signal_waitqueue(q: &Waitqueue) -> bool {
-    // The peek is mandatory to make sure recv doesn't block.
-    if q.head.peek() {
-        // Pop and send a wakeup signal. If the waiter was killed, its port
-        // will have closed. Keep trying until we get a live task.
-        if comm::try_send_one(q.head.recv(), ()) {
-            true
-        } else {
-            signal_waitqueue(q)
-        }
-    } else {
-        false
-    }
-}
-
-#[doc(hidden)]
-fn broadcast_waitqueue(q: &Waitqueue) -> uint {
-    let mut count = 0;
-    while q.head.peek() {
-        if comm::try_send_one(q.head.recv(), ()) {
-            count += 1;
-        }
-    }
-    count
-}
-
-// The building-block used to make semaphores, mutexes, and rwlocks.
-#[doc(hidden)]
-struct SemInner<Q> {
-    count: int,
-    waiters:   Waitqueue,
-    // Can be either unit or another waitqueue. Some sems shouldn't come with
-    // a condition variable attached, others should.
-    blocked:   Q
-}
-
-#[doc(hidden)]
-struct Sem<Q>(Exclusive<SemInner<Q>>);
-
-#[doc(hidden)]
-fn new_sem<Q:Owned>(count: int, q: Q) -> Sem<Q> {
-    Sem(exclusive(SemInner {
-        count: count, waiters: new_waitqueue(), blocked: q }))
-}
-#[doc(hidden)]
-fn new_sem_and_signal(count: int, num_condvars: uint)
-        -> Sem<~[Waitqueue]> {
-    let mut queues = ~[];
-    for num_condvars.times {
-        queues.push(new_waitqueue());
-    }
-    new_sem(count, queues)
-}
-
-#[doc(hidden)]
-pub impl<Q:Owned> Sem<Q> {
-    fn acquire(&self) {
-        let mut waiter_nobe = None;
-        do (**self).with |state| {
-            state.count -= 1;
-            if state.count < 0 {
-                // Create waiter nobe.
-                let (WaitEnd, SignalEnd) = comm::oneshot();
-                // Tell outer scope we need to block.
-                waiter_nobe = Some(WaitEnd);
-                // Enqueue ourself.
-                state.waiters.tail.send(SignalEnd);
-            }
-        }
-        // Uncomment if you wish to test for sem races. Not valgrind-friendly.
-        /* for 1000.times { task::yield(); } */
-        // Need to wait outside the exclusive.
-        if waiter_nobe.is_some() {
-            let _ = comm::recv_one(waiter_nobe.unwrap());
-        }
-    }
-    fn release(&self) {
-        do (**self).with |state| {
-            state.count += 1;
-            if state.count <= 0 {
-                signal_waitqueue(&state.waiters);
-            }
-        }
-    }
-}
-// FIXME(#3154) move both copies of this into Sem<Q>, and unify the 2 structs
-#[doc(hidden)]
-pub impl Sem<()> {
-    fn access<U>(&self, blk: &fn() -> U) -> U {
-        let mut release = None;
-        unsafe {
-            do task::unkillable {
-                self.acquire();
-                release = Some(SemRelease(self));
-            }
-        }
-        blk()
-    }
-}
-#[doc(hidden)]
-pub impl Sem<~[Waitqueue]> {
-    fn access<U>(&self, blk: &fn() -> U) -> U {
-        let mut release = None;
-        unsafe {
-            do task::unkillable {
-                self.acquire();
-                release = Some(SemAndSignalRelease(self));
-            }
-        }
-        blk()
-    }
-}
-
-// FIXME(#3588) should go inside of access()
-#[doc(hidden)]
-type SemRelease<'self> = SemReleaseGeneric<'self, ()>;
-type SemAndSignalRelease<'self> = SemReleaseGeneric<'self, ~[Waitqueue]>;
-struct SemReleaseGeneric<'self, Q> { sem: &'self Sem<Q> }
-
-#[unsafe_destructor]
-impl<'self, Q:Owned> Drop for SemReleaseGeneric<'self, Q> {
-    fn finalize(&self) {
-        self.sem.release();
-    }
-}
-
-fn SemRelease<'r>(sem: &'r Sem<()>) -> SemRelease<'r> {
-    SemReleaseGeneric {
-        sem: sem
-    }
-}
-
-fn SemAndSignalRelease<'r>(sem: &'r Sem<~[Waitqueue]>)
-                        -> SemAndSignalRelease<'r> {
-    SemReleaseGeneric {
-        sem: sem
-    }
-}
-
-/// A mechanism for atomic-unlock-and-deschedule blocking and signalling.
-pub struct Condvar<'self> { priv sem: &'self Sem<~[Waitqueue]> }
-
-#[unsafe_destructor]
-impl<'self> Drop for Condvar<'self> { fn finalize(&self) {} }
-
-pub impl<'self> Condvar<'self> {
-    /**
-     * Atomically drop the associated lock, and block until a signal is sent.
-     *
-     * # Failure
-     * A task which is killed (i.e., by linked failure with another task)
-     * while waiting on a condition variable will wake up, fail, and unlock
-     * the associated lock as it unwinds.
-     */
-    fn wait(&self) { self.wait_on(0) }
-
-    /**
-     * As wait(), but can specify which of multiple condition variables to
-     * wait on. Only a signal_on() or broadcast_on() with the same condvar_id
-     * will wake this thread.
-     *
-     * The associated lock must have been initialised with an appropriate
-     * number of condvars. The condvar_id must be between 0 and num_condvars-1
-     * or else this call will fail.
-     *
-     * wait() is equivalent to wait_on(0).
-     */
-    fn wait_on(&self, condvar_id: uint) {
-        // Create waiter nobe.
-        let (WaitEnd, SignalEnd) = comm::oneshot();
-        let mut WaitEnd   = Some(WaitEnd);
-        let mut SignalEnd = Some(SignalEnd);
-        let mut reacquire = None;
-        let mut out_of_bounds = None;
-        unsafe {
-            do task::unkillable {
-                // Release lock, 'atomically' enqueuing ourselves in so doing.
-                do (**self.sem).with |state| {
-                    if condvar_id < state.blocked.len() {
-                        // Drop the lock.
-                        state.count += 1;
-                        if state.count <= 0 {
-                            signal_waitqueue(&state.waiters);
-                        }
-                        // Enqueue ourself to be woken up by a signaller.
-                        let SignalEnd = SignalEnd.swap_unwrap();
-                        state.blocked[condvar_id].tail.send(SignalEnd);
-                    } else {
-                        out_of_bounds = Some(state.blocked.len());
-                    }
-                }
-
-                // If yield checks start getting inserted anywhere, we can be
-                // killed before or after enqueueing. Deciding whether to
-                // unkillably reacquire the lock needs to happen atomically
-                // wrt enqueuing.
-                if out_of_bounds.is_none() {
-                    reacquire = Some(SemAndSignalReacquire(self.sem));
-                }
-            }
-        }
-        do check_cvar_bounds(out_of_bounds, condvar_id, "cond.wait_on()") {
-            // Unconditionally "block". (Might not actually block if a
-            // signaller already sent -- I mean 'unconditionally' in contrast
-            // with acquire().)
-            let _ = comm::recv_one(WaitEnd.swap_unwrap());
-        }
-
-        // This is needed for a failing condition variable to reacquire the
-        // mutex during unwinding. As long as the wrapper (mutex, etc) is
-        // bounded in when it gets released, this shouldn't hang forever.
-        struct SemAndSignalReacquire<'self> {
-            sem: &'self Sem<~[Waitqueue]>,
-        }
-
-        #[unsafe_destructor]
-        impl<'self> Drop for SemAndSignalReacquire<'self> {
-            fn finalize(&self) {
-                unsafe {
-                    // Needs to succeed, instead of itself dying.
-                    do task::unkillable {
-                        self.sem.acquire();
-                    }
-                }
-            }
-        }
-
-        fn SemAndSignalReacquire<'r>(sem: &'r Sem<~[Waitqueue]>)
-                                  -> SemAndSignalReacquire<'r> {
-            SemAndSignalReacquire {
-                sem: sem
-            }
-        }
-    }
-
-    /// Wake up a blocked task. Returns false if there was no blocked task.
-    fn signal(&self) -> bool { self.signal_on(0) }
-
-    /// As signal, but with a specified condvar_id. See wait_on.
-    fn signal_on(&self, condvar_id: uint) -> bool {
-        let mut out_of_bounds = None;
-        let mut result = false;
-        do (**self.sem).with |state| {
-            if condvar_id < state.blocked.len() {
-                result = signal_waitqueue(&state.blocked[condvar_id]);
-            } else {
-                out_of_bounds = Some(state.blocked.len());
-            }
-        }
-        do check_cvar_bounds(out_of_bounds, condvar_id, "cond.signal_on()") {
-            result
-        }
-    }
-
-    /// Wake up all blocked tasks. Returns the number of tasks woken.
-    fn broadcast(&self) -> uint { self.broadcast_on(0) }
-
-    /// As broadcast, but with a specified condvar_id. See wait_on.
-    fn broadcast_on(&self, condvar_id: uint) -> uint {
-        let mut out_of_bounds = None;
-        let mut queue = None;
-        do (**self.sem).with |state| {
-            if condvar_id < state.blocked.len() {
-                // To avoid :broadcast_heavy, we make a new waitqueue,
-                // swap it out with the old one, and broadcast on the
-                // old one outside of the little-lock.
-                queue = Some(util::replace(&mut state.blocked[condvar_id],
-                                           new_waitqueue()));
-            } else {
-                out_of_bounds = Some(state.blocked.len());
-            }
-        }
-        do check_cvar_bounds(out_of_bounds, condvar_id, "cond.signal_on()") {
-            let queue = queue.swap_unwrap();
-            broadcast_waitqueue(&queue)
-        }
-    }
-}
-
-// Checks whether a condvar ID was out of bounds, and fails if so, or does
-// something else next on success.
-#[inline(always)]
-#[doc(hidden)]
-fn check_cvar_bounds<U>(out_of_bounds: Option<uint>, id: uint, act: &str,
-                        blk: &fn() -> U) -> U {
-    match out_of_bounds {
-        Some(0) =>
-            fail!("%s with illegal ID %u - this lock has no condvars!", act, id),
-        Some(length) =>
-            fail!("%s with illegal ID %u - ID must be less than %u", act, id, length),
-        None => blk()
-    }
-}
-
-#[doc(hidden)]
-pub impl Sem<~[Waitqueue]> {
-    // The only other place that condvars get built is rwlock_write_mode.
-    fn access_cond<U>(&self, blk: &fn(c: &Condvar) -> U) -> U {
-        do self.access { blk(&Condvar { sem: self }) }
-    }
-}
-
-/****************************************************************************
- * Semaphores
- ****************************************************************************/
-
-/// A counting, blocking, bounded-waiting semaphore.
-struct Semaphore { priv sem: Sem<()> }
-
-/// Create a new semaphore with the specified count.
-pub fn semaphore(count: int) -> Semaphore {
-    Semaphore { sem: new_sem(count, ()) }
-}
-
-impl Clone for Semaphore {
-    /// Create a new handle to the semaphore.
-    fn clone(&self) -> Semaphore {
-        Semaphore { sem: Sem((*self.sem).clone()) }
-    }
-}
-
-pub impl Semaphore {
-    /**
-     * Acquire a resource represented by the semaphore. Blocks if necessary
-     * until resource(s) become available.
-     */
-    fn acquire(&self) { (&self.sem).acquire() }
-
-    /**
-     * Release a held resource represented by the semaphore. Wakes a blocked
-     * contending task, if any exist. Won't block the caller.
-     */
-    fn release(&self) { (&self.sem).release() }
-
-    /// Run a function with ownership of one of the semaphore's resources.
-    fn access<U>(&self, blk: &fn() -> U) -> U { (&self.sem).access(blk) }
-}
-
-/****************************************************************************
- * Mutexes
- ****************************************************************************/
-
-/**
- * A blocking, bounded-waiting, mutual exclusion lock with an associated
- * FIFO condition variable.
- *
- * # Failure
- * A task which fails while holding a mutex will unlock the mutex as it
- * unwinds.
- */
-pub struct Mutex { priv sem: Sem<~[Waitqueue]> }
-
-/// Create a new mutex, with one associated condvar.
-pub fn Mutex() -> Mutex { mutex_with_condvars(1) }
-/**
- * Create a new mutex, with a specified number of associated condvars. This
- * will allow calling wait_on/signal_on/broadcast_on with condvar IDs between
- * 0 and num_condvars-1. (If num_condvars is 0, lock_cond will be allowed but
- * any operations on the condvar will fail.)
- */
-pub fn mutex_with_condvars(num_condvars: uint) -> Mutex {
-    Mutex { sem: new_sem_and_signal(1, num_condvars) }
-}
-
-impl Clone for Mutex {
-    /// Create a new handle to the mutex.
-    fn clone(&self) -> Mutex { Mutex { sem: Sem((*self.sem).clone()) } }
-}
-
-pub impl Mutex {
-    /// Run a function with ownership of the mutex.
-    fn lock<U>(&self, blk: &fn() -> U) -> U { (&self.sem).access(blk) }
-
-    /// Run a function with ownership of the mutex and a handle to a condvar.
-    fn lock_cond<U>(&self, blk: &fn(c: &Condvar) -> U) -> U {
-        (&self.sem).access_cond(blk)
-    }
-}
-
-/****************************************************************************
- * Reader-writer locks
- ****************************************************************************/
-
-// NB: Wikipedia - Readers-writers_problem#The_third_readers-writers_problem
-
-#[doc(hidden)]
-struct RWlockInner {
-    read_mode:  bool,
-    read_count: uint
-}
-
-/**
- * A blocking, no-starvation, reader-writer lock with an associated condvar.
- *
- * # Failure
- * A task which fails while holding an rwlock will unlock the rwlock as it
- * unwinds.
- */
-pub struct RWlock {
-    priv order_lock:  Semaphore,
-    priv access_lock: Sem<~[Waitqueue]>,
-    priv state:       Exclusive<RWlockInner>
-}
-
-/// Create a new rwlock, with one associated condvar.
-pub fn RWlock() -> RWlock { rwlock_with_condvars(1) }
-
-/**
- * Create a new rwlock, with a specified number of associated condvars.
- * Similar to mutex_with_condvars.
- */
-pub fn rwlock_with_condvars(num_condvars: uint) -> RWlock {
-    RWlock { order_lock: semaphore(1),
-             access_lock: new_sem_and_signal(1, num_condvars),
-             state: exclusive(RWlockInner { read_mode:  false,
-                                             read_count: 0 }) }
-}
-
-pub impl RWlock {
-    /// Create a new handle to the rwlock.
-    fn clone(&self) -> RWlock {
-        RWlock { order_lock:  (&(self.order_lock)).clone(),
-                 access_lock: Sem((*self.access_lock).clone()),
-                 state:       self.state.clone() }
-    }
-
-    /**
-     * Run a function with the rwlock in read mode. Calls to 'read' from other
-     * tasks may run concurrently with this one.
-     */
-    fn read<U>(&self, blk: &fn() -> U) -> U {
-        let mut release = None;
-        unsafe {
-            do task::unkillable {
-                do (&self.order_lock).access {
-                    let mut first_reader = false;
-                    do self.state.with |state| {
-                        first_reader = (state.read_count == 0);
-                        state.read_count += 1;
-                    }
-                    if first_reader {
-                        (&self.access_lock).acquire();
-                        do self.state.with |state| {
-                            // Must happen *after* getting access_lock. If
-                            // this is set while readers are waiting, but
-                            // while a writer holds the lock, the writer will
-                            // be confused if they downgrade-then-unlock.
-                            state.read_mode = true;
-                        }
-                    }
-                }
-                release = Some(RWlockReleaseRead(self));
-            }
-        }
-        blk()
-    }
-
-    /**
-     * Run a function with the rwlock in write mode. No calls to 'read' or
-     * 'write' from other tasks will run concurrently with this one.
-     */
-    fn write<U>(&self, blk: &fn() -> U) -> U {
-        unsafe {
-            do task::unkillable {
-                (&self.order_lock).acquire();
-                do (&self.access_lock).access {
-                    (&self.order_lock).release();
-                    task::rekillable(blk)
-                }
-            }
-        }
-    }
-
-    /**
-     * As write(), but also with a handle to a condvar. Waiting on this
-     * condvar will allow readers and writers alike to take the rwlock before
-     * the waiting task is signalled. (Note: a writer that waited and then
-     * was signalled might reacquire the lock before other waiting writers.)
-     */
-    fn write_cond<U>(&self, blk: &fn(c: &Condvar) -> U) -> U {
-        // NB: You might think I should thread the order_lock into the cond
-        // wait call, so that it gets waited on before access_lock gets
-        // reacquired upon being woken up. However, (a) this would be not
-        // pleasant to implement (and would mandate a new 'rw_cond' type) and
-        // (b) I think violating no-starvation in that case is appropriate.
-        unsafe {
-            do task::unkillable {
-                (&self.order_lock).acquire();
-                do (&self.access_lock).access_cond |cond| {
-                    (&self.order_lock).release();
-                    do task::rekillable { blk(cond) }
-                }
-            }
-        }
-    }
-
-    /**
-     * As write(), but with the ability to atomically 'downgrade' the lock;
-     * i.e., to become a reader without letting other writers get the lock in
-     * the meantime (such as unlocking and then re-locking as a reader would
-     * do). The block takes a "write mode token" argument, which can be
-     * transformed into a "read mode token" by calling downgrade(). Example:
-     * ~~~
-     * do lock.write_downgrade |write_mode| {
-     *     do (&write_mode).write_cond |condvar| {
-     *         ... exclusive access ...
-     *     }
-     *     let read_mode = lock.downgrade(write_mode);
-     *     do (&read_mode).read {
-     *         ... shared access ...
-     *     }
-     * }
-     * ~~~
-     */
-    fn write_downgrade<U>(&self, blk: &fn(v: RWlockWriteMode) -> U) -> U {
-        // Implementation slightly different from the slicker 'write's above.
-        // The exit path is conditional on whether the caller downgrades.
-        let mut _release = None;
-        unsafe {
-            do task::unkillable {
-                (&self.order_lock).acquire();
-                (&self.access_lock).acquire();
-                (&self.order_lock).release();
-            }
-            _release = Some(RWlockReleaseDowngrade(self));
-        }
-        blk(RWlockWriteMode { lock: self })
-    }
-
-    /// To be called inside of the write_downgrade block.
-    fn downgrade<'a>(&self,
-                     token: RWlockWriteMode<'a>)
-                  -> RWlockReadMode<'a> {
-        if !ptr::ref_eq(self, token.lock) {
-            fail!("Can't downgrade() with a different rwlock's write_mode!");
-        }
-        unsafe {
-            do task::unkillable {
-                let mut first_reader = false;
-                do self.state.with |state| {
-                    assert!(!state.read_mode);
-                    state.read_mode = true;
-                    first_reader = (state.read_count == 0);
-                    state.read_count += 1;
-                }
-                if !first_reader {
-                    // Guaranteed not to let another writer in, because
-                    // another reader was holding the order_lock. Hence they
-                    // must be the one to get the access_lock (because all
-                    // access_locks are acquired with order_lock held).
-                    (&self.access_lock).release();
-                }
-            }
-        }
-        RWlockReadMode { lock: token.lock }
-    }
-}
-
-// FIXME(#3588) should go inside of read()
-#[doc(hidden)]
-struct RWlockReleaseRead<'self> {
-    lock: &'self RWlock,
-}
-
-#[unsafe_destructor]
-impl<'self> Drop for RWlockReleaseRead<'self> {
-    fn finalize(&self) {
-        unsafe {
-            do task::unkillable {
-                let mut last_reader = false;
-                do self.lock.state.with |state| {
-                    assert!(state.read_mode);
-                    assert!(state.read_count > 0);
-                    state.read_count -= 1;
-                    if state.read_count == 0 {
-                        last_reader = true;
-                        state.read_mode = false;
-                    }
-                }
-                if last_reader {
-                    (&self.lock.access_lock).release();
-                }
-            }
-        }
-    }
-}
-
-fn RWlockReleaseRead<'r>(lock: &'r RWlock) -> RWlockReleaseRead<'r> {
-    RWlockReleaseRead {
-        lock: lock
-    }
-}
-
-// FIXME(#3588) should go inside of downgrade()
-#[doc(hidden)]
-#[unsafe_destructor]
-struct RWlockReleaseDowngrade<'self> {
-    lock: &'self RWlock,
-}
-
-#[unsafe_destructor]
-impl<'self> Drop for RWlockReleaseDowngrade<'self> {
-    fn finalize(&self) {
-        unsafe {
-            do task::unkillable {
-                let mut writer_or_last_reader = false;
-                do self.lock.state.with |state| {
-                    if state.read_mode {
-                        assert!(state.read_count > 0);
-                        state.read_count -= 1;
-                        if state.read_count == 0 {
-                            // Case 1: Writer downgraded & was the last reader
-                            writer_or_last_reader = true;
-                            state.read_mode = false;
-                        } else {
-                            // Case 2: Writer downgraded & was not the last
-                            // reader
-                        }
-                    } else {
-                        // Case 3: Writer did not downgrade
-                        writer_or_last_reader = true;
-                    }
-                }
-                if writer_or_last_reader {
-                    (&self.lock.access_lock).release();
-                }
-            }
-        }
-    }
-}
-
-fn RWlockReleaseDowngrade<'r>(lock: &'r RWlock)
-                           -> RWlockReleaseDowngrade<'r> {
-    RWlockReleaseDowngrade {
-        lock: lock
-    }
-}
-
-/// The "write permission" token used for rwlock.write_downgrade().
-pub struct RWlockWriteMode<'self> { priv lock: &'self RWlock }
-#[unsafe_destructor]
-impl<'self> Drop for RWlockWriteMode<'self> { fn finalize(&self) {} }
-
-/// The "read permission" token used for rwlock.write_downgrade().
-pub struct RWlockReadMode<'self> { priv lock: &'self RWlock }
-#[unsafe_destructor]
-impl<'self> Drop for RWlockReadMode<'self> { fn finalize(&self) {} }
-
-pub impl<'self> RWlockWriteMode<'self> {
-    /// Access the pre-downgrade rwlock in write mode.
-    fn write<U>(&self, blk: &fn() -> U) -> U { blk() }
-    /// Access the pre-downgrade rwlock in write mode with a condvar.
-    fn write_cond<U>(&self, blk: &fn(c: &Condvar) -> U) -> U {
-        blk(&Condvar { sem: &self.lock.access_lock })
-    }
-}
-
-pub impl<'self> RWlockReadMode<'self> {
-    /// Access the post-downgrade rwlock in read mode.
-    fn read<U>(&self, blk: &fn() -> U) -> U { blk() }
-}
-
-/****************************************************************************
- * Tests
- ****************************************************************************/
-
-#[cfg(test)]
-mod tests {
-
-    use sync::*;
-
-    use core::cast;
-    use core::cell::Cell;
-    use core::ptr;
-    use core::result;
-    use core::task;
-    use core::vec;
-
-    /************************************************************************
-     * Semaphore tests
-     ************************************************************************/
-    #[test]
-    fn test_sem_acquire_release() {
-        let s = ~semaphore(1);
-        s.acquire();
-        s.release();
-        s.acquire();
-    }
-    #[test]
-    fn test_sem_basic() {
-        let s = ~semaphore(1);
-        do s.access { }
-    }
-    #[test]
-    fn test_sem_as_mutex() {
-        let s = ~semaphore(1);
-        let s2 = ~s.clone();
-        do task::spawn || {
-            do s2.access {
-                for 5.times { task::yield(); }
-            }
-        }
-        do s.access {
-            for 5.times { task::yield(); }
-        }
-    }
-    #[test]
-    fn test_sem_as_cvar() {
-        /* Child waits and parent signals */
-        let (p,c) = comm::stream();
-        let s = ~semaphore(0);
-        let s2 = ~s.clone();
-        do task::spawn || {
-            s2.acquire();
-            c.send(());
-        }
-        for 5.times { task::yield(); }
-        s.release();
-        let _ = p.recv();
-
-        /* Parent waits and child signals */
-        let (p,c) = comm::stream();
-        let s = ~semaphore(0);
-        let s2 = ~s.clone();
-        do task::spawn || {
-            for 5.times { task::yield(); }
-            s2.release();
-            let _ = p.recv();
-        }
-        s.acquire();
-        c.send(());
-    }
-    #[test]
-    fn test_sem_multi_resource() {
-        // Parent and child both get in the critical section at the same
-        // time, and shake hands.
-        let s = ~semaphore(2);
-        let s2 = ~s.clone();
-        let (p1,c1) = comm::stream();
-        let (p2,c2) = comm::stream();
-        do task::spawn || {
-            do s2.access {
-                let _ = p2.recv();
-                c1.send(());
-            }
-        }
-        do s.access {
-            c2.send(());
-            let _ = p1.recv();
-        }
-    }
-    #[test]
-    fn test_sem_runtime_friendly_blocking() {
-        // Force the runtime to schedule two threads on the same sched_loop.
-        // When one blocks, it should schedule the other one.
-        do task::spawn_sched(task::ManualThreads(1)) {
-            let s = ~semaphore(1);
-            let s2 = ~s.clone();
-            let (p,c) = comm::stream();
-            let child_data = Cell((s2, c));
-            do s.access {
-                let (s2, c) = child_data.take();
-                do task::spawn || {
-                    c.send(());
-                    do s2.access { }
-                    c.send(());
-                }
-                let _ = p.recv(); // wait for child to come alive
-                for 5.times { task::yield(); } // let the child contend
-            }
-            let _ = p.recv(); // wait for child to be done
-        }
-    }
-    /************************************************************************
-     * Mutex tests
-     ************************************************************************/
-    #[test]
-    fn test_mutex_lock() {
-        // Unsafely achieve shared state, and do the textbook
-        // "load tmp = move ptr; inc tmp; store ptr <- tmp" dance.
-        let (p,c) = comm::stream();
-        let m = ~Mutex();
-        let m2 = m.clone();
-        let mut sharedstate = ~0;
-        {
-            let ptr: *int = &*sharedstate;
-            do task::spawn || {
-                let sharedstate: &mut int =
-                    unsafe { cast::transmute(ptr) };
-                access_shared(sharedstate, m2, 10);
-                c.send(());
-
-            }
-        }
-        {
-            access_shared(sharedstate, m, 10);
-            let _ = p.recv();
-
-            assert_eq!(*sharedstate, 20);
-        }
-
-        fn access_shared(sharedstate: &mut int, m: &Mutex, n: uint) {
-            for n.times {
-                do m.lock {
-                    let oldval = *sharedstate;
-                    task::yield();
-                    *sharedstate = oldval + 1;
-                }
-            }
-        }
-    }
-    #[test]
-    fn test_mutex_cond_wait() {
-        let m = ~Mutex();
-
-        // Child wakes up parent
-        do m.lock_cond |cond| {
-            let m2 = ~m.clone();
-            do task::spawn || {
-                do m2.lock_cond |cond| {
-                    let woken = cond.signal();
-                    assert!(woken);
-                }
-            }
-            cond.wait();
-        }
-        // Parent wakes up child
-        let (port,chan) = comm::stream();
-        let m3 = ~m.clone();
-        do task::spawn || {
-            do m3.lock_cond |cond| {
-                chan.send(());
-                cond.wait();
-                chan.send(());
-            }
-        }
-        let _ = port.recv(); // Wait until child gets in the mutex
-        do m.lock_cond |cond| {
-            let woken = cond.signal();
-            assert!(woken);
-        }
-        let _ = port.recv(); // Wait until child wakes up
-    }
-    #[cfg(test)]
-    fn test_mutex_cond_broadcast_helper(num_waiters: uint) {
-        let m = ~Mutex();
-        let mut ports = ~[];
-
-        for num_waiters.times {
-            let mi = ~m.clone();
-            let (port, chan) = comm::stream();
-            ports.push(port);
-            do task::spawn || {
-                do mi.lock_cond |cond| {
-                    chan.send(());
-                    cond.wait();
-                    chan.send(());
-                }
-            }
-        }
-
-        // wait until all children get in the mutex
-        for ports.each |port| { let _ = port.recv(); }
-        do m.lock_cond |cond| {
-            let num_woken = cond.broadcast();
-            assert_eq!(num_woken, num_waiters);
-        }
-        // wait until all children wake up
-        for ports.each |port| { let _ = port.recv(); }
-    }
-    #[test]
-    fn test_mutex_cond_broadcast() {
-        test_mutex_cond_broadcast_helper(12);
-    }
-    #[test]
-    fn test_mutex_cond_broadcast_none() {
-        test_mutex_cond_broadcast_helper(0);
-    }
-    #[test]
-    fn test_mutex_cond_no_waiter() {
-        let m = ~Mutex();
-        let m2 = ~m.clone();
-        do task::try || {
-            do m.lock_cond |_x| { }
-        };
-        do m2.lock_cond |cond| {
-            assert!(!cond.signal());
-        }
-    }
-    #[test] #[ignore(cfg(windows))]
-    fn test_mutex_killed_simple() {
-        // Mutex must get automatically unlocked if failed/killed within.
-        let m = ~Mutex();
-        let m2 = ~m.clone();
-
-        let result: result::Result<(),()> = do task::try || {
-            do m2.lock {
-                fail!();
-            }
-        };
-        assert!(result.is_err());
-        // child task must have finished by the time try returns
-        do m.lock { }
-    }
-    #[test] #[ignore(cfg(windows))]
-    fn test_mutex_killed_cond() {
-        // Getting killed during cond wait must not corrupt the mutex while
-        // unwinding (e.g. double unlock).
-        let m = ~Mutex();
-        let m2 = ~m.clone();
-
-        let result: result::Result<(),()> = do task::try || {
-            let (p,c) = comm::stream();
-            do task::spawn || { // linked
-                let _ = p.recv(); // wait for sibling to get in the mutex
-                task::yield();
-                fail!();
-            }
-            do m2.lock_cond |cond| {
-                c.send(()); // tell sibling go ahead
-                cond.wait(); // block forever
-            }
-        };
-        assert!(result.is_err());
-        // child task must have finished by the time try returns
-        do m.lock_cond |cond| {
-            let woken = cond.signal();
-            assert!(!woken);
-        }
-    }
-    #[test] #[ignore(cfg(windows))]
-    fn test_mutex_killed_broadcast() {
-        let m = ~Mutex();
-        let m2 = ~m.clone();
-        let (p,c) = comm::stream();
-
-        let result: result::Result<(),()> = do task::try || {
-            let mut sibling_convos = ~[];
-            for 2.times {
-                let (p,c) = comm::stream();
-                let c = Cell(c);
-                sibling_convos.push(p);
-                let mi = ~m2.clone();
-                // spawn sibling task
-                do task::spawn { // linked
-                    do mi.lock_cond |cond| {
-                        let c = c.take();
-                        c.send(()); // tell sibling to go ahead
-                        let _z = SendOnFailure(c);
-                        cond.wait(); // block forever
-                    }
-                }
-            }
-            for sibling_convos.each |p| {
-                let _ = p.recv(); // wait for sibling to get in the mutex
-            }
-            do m2.lock { }
-            c.send(sibling_convos); // let parent wait on all children
-            fail!();
-        };
-        assert!(result.is_err());
-        // child task must have finished by the time try returns
-        for vec::each(p.recv()) |p| { p.recv(); } // wait on all its siblings
-        do m.lock_cond |cond| {
-            let woken = cond.broadcast();
-            assert_eq!(woken, 0);
-        }
-        struct SendOnFailure {
-            c: comm::Chan<()>,
-        }
-
-        impl Drop for SendOnFailure {
-            fn finalize(&self) {
-                self.c.send(());
-            }
-        }
-
-        fn SendOnFailure(c: comm::Chan<()>) -> SendOnFailure {
-            SendOnFailure {
-                c: c
-            }
-        }
-    }
-    #[test]
-    fn test_mutex_cond_signal_on_0() {
-        // Tests that signal_on(0) is equivalent to signal().
-        let m = ~Mutex();
-        do m.lock_cond |cond| {
-            let m2 = ~m.clone();
-            do task::spawn || {
-                do m2.lock_cond |cond| {
-                    cond.signal_on(0);
-                }
-            }
-            cond.wait();
-        }
-    }
-    #[test] #[ignore(cfg(windows))]
-    fn test_mutex_different_conds() {
-        let result = do task::try {
-            let m = ~mutex_with_condvars(2);
-            let m2 = ~m.clone();
-            let (p,c) = comm::stream();
-            do task::spawn || {
-                do m2.lock_cond |cond| {
-                    c.send(());
-                    cond.wait_on(1);
-                }
-            }
-            let _ = p.recv();
-            do m.lock_cond |cond| {
-                if !cond.signal_on(0) {
-                    fail!(); // success; punt sibling awake.
-                }
-            }
-        };
-        assert!(result.is_err());
-    }
-    #[test] #[ignore(cfg(windows))]
-    fn test_mutex_no_condvars() {
-        let result = do task::try {
-            let m = ~mutex_with_condvars(0);
-            do m.lock_cond |cond| { cond.wait(); }
-        };
-        assert!(result.is_err());
-        let result = do task::try {
-            let m = ~mutex_with_condvars(0);
-            do m.lock_cond |cond| { cond.signal(); }
-        };
-        assert!(result.is_err());
-        let result = do task::try {
-            let m = ~mutex_with_condvars(0);
-            do m.lock_cond |cond| { cond.broadcast(); }
-        };
-        assert!(result.is_err());
-    }
-    /************************************************************************
-     * Reader/writer lock tests
-     ************************************************************************/
-    #[cfg(test)]
-    pub enum RWlockMode { Read, Write, Downgrade, DowngradeRead }
-    #[cfg(test)]
-    fn lock_rwlock_in_mode(x: &RWlock, mode: RWlockMode, blk: &fn()) {
-        match mode {
-            Read => x.read(blk),
-            Write => x.write(blk),
-            Downgrade =>
-                do x.write_downgrade |mode| {
-                    (&mode).write(blk);
-                },
-            DowngradeRead =>
-                do x.write_downgrade |mode| {
-                    let mode = x.downgrade(mode);
-                    (&mode).read(blk);
-                },
-        }
-    }
-    #[cfg(test)]
-    fn test_rwlock_exclusion(x: ~RWlock,
-                                 mode1: RWlockMode,
-                                 mode2: RWlockMode) {
-        // Test mutual exclusion between readers and writers. Just like the
-        // mutex mutual exclusion test, a ways above.
-        let (p,c) = comm::stream();
-        let x2 = (*x).clone();
-        let mut sharedstate = ~0;
-        {
-            let ptr: *int = &*sharedstate;
-            do task::spawn || {
-                let sharedstate: &mut int =
-                    unsafe { cast::transmute(ptr) };
-                access_shared(sharedstate, &x2, mode1, 10);
-                c.send(());
-            }
-        }
-        {
-            access_shared(sharedstate, x, mode2, 10);
-            let _ = p.recv();
-
-            assert_eq!(*sharedstate, 20);
-        }
-
-        fn access_shared(sharedstate: &mut int, x: &RWlock, mode: RWlockMode,
-                         n: uint) {
-            for n.times {
-                do lock_rwlock_in_mode(x, mode) {
-                    let oldval = *sharedstate;
-                    task::yield();
-                    *sharedstate = oldval + 1;
-                }
-            }
-        }
-    }
-    #[test]
-    fn test_rwlock_readers_wont_modify_the_data() {
-        test_rwlock_exclusion(~RWlock(), Read, Write);
-        test_rwlock_exclusion(~RWlock(), Write, Read);
-        test_rwlock_exclusion(~RWlock(), Read, Downgrade);
-        test_rwlock_exclusion(~RWlock(), Downgrade, Read);
-    }
-    #[test]
-    fn test_rwlock_writers_and_writers() {
-        test_rwlock_exclusion(~RWlock(), Write, Write);
-        test_rwlock_exclusion(~RWlock(), Write, Downgrade);
-        test_rwlock_exclusion(~RWlock(), Downgrade, Write);
-        test_rwlock_exclusion(~RWlock(), Downgrade, Downgrade);
-    }
-    #[cfg(test)]
-    fn test_rwlock_handshake(x: ~RWlock,
-                                 mode1: RWlockMode,
-                                 mode2: RWlockMode,
-                                 make_mode2_go_first: bool) {
-        // Much like sem_multi_resource.
-        let x2 = (*x).clone();
-        let (p1,c1) = comm::stream();
-        let (p2,c2) = comm::stream();
-        do task::spawn || {
-            if !make_mode2_go_first {
-                let _ = p2.recv(); // parent sends to us once it locks, or ...
-            }
-            do lock_rwlock_in_mode(&x2, mode2) {
-                if make_mode2_go_first {
-                    c1.send(()); // ... we send to it once we lock
-                }
-                let _ = p2.recv();
-                c1.send(());
-            }
-        }
-        if make_mode2_go_first {
-            let _ = p1.recv(); // child sends to us once it locks, or ...
-        }
-        do lock_rwlock_in_mode(x, mode1) {
-            if !make_mode2_go_first {
-                c2.send(()); // ... we send to it once we lock
-            }
-            c2.send(());
-            let _ = p1.recv();
-        }
-    }
-    #[test]
-    fn test_rwlock_readers_and_readers() {
-        test_rwlock_handshake(~RWlock(), Read, Read, false);
-        // The downgrader needs to get in before the reader gets in, otherwise
-        // they cannot end up reading at the same time.
-        test_rwlock_handshake(~RWlock(), DowngradeRead, Read, false);
-        test_rwlock_handshake(~RWlock(), Read, DowngradeRead, true);
-        // Two downgrade_reads can never both end up reading at the same time.
-    }
-    #[test]
-    fn test_rwlock_downgrade_unlock() {
-        // Tests that downgrade can unlock the lock in both modes
-        let x = ~RWlock();
-        do lock_rwlock_in_mode(x, Downgrade) { }
-        test_rwlock_handshake(x, Read, Read, false);
-        let y = ~RWlock();
-        do lock_rwlock_in_mode(y, DowngradeRead) { }
-        test_rwlock_exclusion(y, Write, Write);
-    }
-    #[test]
-    fn test_rwlock_read_recursive() {
-        let x = ~RWlock();
-        do x.read { do x.read { } }
-    }
-    #[test]
-    fn test_rwlock_cond_wait() {
-        // As test_mutex_cond_wait above.
-        let x = ~RWlock();
-
-        // Child wakes up parent
-        do x.write_cond |cond| {
-            let x2 = (*x).clone();
-            do task::spawn || {
-                do x2.write_cond |cond| {
-                    let woken = cond.signal();
-                    assert!(woken);
-                }
-            }
-            cond.wait();
-        }
-        // Parent wakes up child
-        let (port,chan) = comm::stream();
-        let x3 = (*x).clone();
-        do task::spawn || {
-            do x3.write_cond |cond| {
-                chan.send(());
-                cond.wait();
-                chan.send(());
-            }
-        }
-        let _ = port.recv(); // Wait until child gets in the rwlock
-        do x.read { } // Must be able to get in as a reader in the meantime
-        do x.write_cond |cond| { // Or as another writer
-            let woken = cond.signal();
-            assert!(woken);
-        }
-        let _ = port.recv(); // Wait until child wakes up
-        do x.read { } // Just for good measure
-    }
-    #[cfg(test)]
-    fn test_rwlock_cond_broadcast_helper(num_waiters: uint,
-                                             dg1: bool,
-                                             dg2: bool) {
-        // Much like the mutex broadcast test. Downgrade-enabled.
-        fn lock_cond(x: &RWlock, downgrade: bool, blk: &fn(c: &Condvar)) {
-            if downgrade {
-                do x.write_downgrade |mode| {
-                    (&mode).write_cond(blk)
-                }
-            } else {
-                x.write_cond(blk)
-            }
-        }
-        let x = ~RWlock();
-        let mut ports = ~[];
-
-        for num_waiters.times {
-            let xi = (*x).clone();
-            let (port, chan) = comm::stream();
-            ports.push(port);
-            do task::spawn || {
-                do lock_cond(&xi, dg1) |cond| {
-                    chan.send(());
-                    cond.wait();
-                    chan.send(());
-                }
-            }
-        }
-
-        // wait until all children get in the mutex
-        for ports.each |port| { let _ = port.recv(); }
-        do lock_cond(x, dg2) |cond| {
-            let num_woken = cond.broadcast();
-            assert_eq!(num_woken, num_waiters);
-        }
-        // wait until all children wake up
-        for ports.each |port| { let _ = port.recv(); }
-    }
-    #[test]
-    fn test_rwlock_cond_broadcast() {
-        test_rwlock_cond_broadcast_helper(0, true, true);
-        test_rwlock_cond_broadcast_helper(0, true, false);
-        test_rwlock_cond_broadcast_helper(0, false, true);
-        test_rwlock_cond_broadcast_helper(0, false, false);
-        test_rwlock_cond_broadcast_helper(12, true, true);
-        test_rwlock_cond_broadcast_helper(12, true, false);
-        test_rwlock_cond_broadcast_helper(12, false, true);
-        test_rwlock_cond_broadcast_helper(12, false, false);
-    }
-    #[cfg(test)] #[ignore(cfg(windows))]
-    fn rwlock_kill_helper(mode1: RWlockMode, mode2: RWlockMode) {
-        // Mutex must get automatically unlocked if failed/killed within.
-        let x = ~RWlock();
-        let x2 = (*x).clone();
-
-        let result: result::Result<(),()> = do task::try || {
-            do lock_rwlock_in_mode(&x2, mode1) {
-                fail!();
-            }
-        };
-        assert!(result.is_err());
-        // child task must have finished by the time try returns
-        do lock_rwlock_in_mode(x, mode2) { }
-    }
-    #[test] #[ignore(cfg(windows))]
-    fn test_rwlock_reader_killed_writer() {
-        rwlock_kill_helper(Read, Write);
-    }
-    #[test] #[ignore(cfg(windows))]
-    fn test_rwlock_writer_killed_reader() {
-        rwlock_kill_helper(Write,Read );
-    }
-    #[test] #[ignore(cfg(windows))]
-    fn test_rwlock_reader_killed_reader() {
-        rwlock_kill_helper(Read, Read );
-    }
-    #[test] #[ignore(cfg(windows))]
-    fn test_rwlock_writer_killed_writer() {
-        rwlock_kill_helper(Write,Write);
-    }
-    #[test] #[ignore(cfg(windows))]
-    fn test_rwlock_kill_downgrader() {
-        rwlock_kill_helper(Downgrade, Read);
-        rwlock_kill_helper(Read, Downgrade);
-        rwlock_kill_helper(Downgrade, Write);
-        rwlock_kill_helper(Write, Downgrade);
-        rwlock_kill_helper(DowngradeRead, Read);
-        rwlock_kill_helper(Read, DowngradeRead);
-        rwlock_kill_helper(DowngradeRead, Write);
-        rwlock_kill_helper(Write, DowngradeRead);
-        rwlock_kill_helper(DowngradeRead, Downgrade);
-        rwlock_kill_helper(DowngradeRead, Downgrade);
-        rwlock_kill_helper(Downgrade, DowngradeRead);
-        rwlock_kill_helper(Downgrade, DowngradeRead);
-    }
-    #[test] #[should_fail] #[ignore(cfg(windows))]
-    fn test_rwlock_downgrade_cant_swap() {
-        // Tests that you can't downgrade with a different rwlock's token.
-        let x = ~RWlock();
-        let y = ~RWlock();
-        do x.write_downgrade |xwrite| {
-            let mut xopt = Some(xwrite);
-            do y.write_downgrade |_ywrite| {
-                y.downgrade(xopt.swap_unwrap());
-                error!("oops, y.downgrade(x) should have failed!");
-            }
-        }
-    }
-}
diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs
new file mode 100644
index 00000000000..137070ce202
--- /dev/null
+++ b/src/libstd/sys.rs
@@ -0,0 +1,352 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Misc low level stuff
+
+use option::{Some, None};
+use cast;
+use cmp::{Eq, Ord};
+use gc;
+use io;
+use libc;
+use libc::{c_void, c_char, size_t};
+use repr;
+use str;
+use unstable::intrinsics;
+
+pub type FreeGlue<'self> = &'self fn(*TypeDesc, *c_void);
+
+// Corresponds to runtime type_desc type
+pub struct TypeDesc {
+    size: uint,
+    align: uint,
+    take_glue: uint,
+    drop_glue: uint,
+    free_glue: uint
+    // Remaining fields not listed
+}
+
+/// The representation of a Rust closure
+pub struct Closure {
+    code: *(),
+    env: *(),
+}
+
+pub mod rustrt {
+    use libc::{c_char, size_t};
+
+    pub extern {
+        #[rust_stack]
+        unsafe fn rust_upcall_fail(expr: *c_char,
+                                   file: *c_char,
+                                   line: size_t);
+    }
+}
+
+/// Compares contents of two pointers using the default method.
+/// Equivalent to `*x1 == *x2`.  Useful for hashtables.
+pub fn shape_eq<T:Eq>(x1: &T, x2: &T) -> bool {
+    *x1 == *x2
+}
+
+pub fn shape_lt<T:Ord>(x1: &T, x2: &T) -> bool {
+    *x1 < *x2
+}
+
+pub fn shape_le<T:Ord>(x1: &T, x2: &T) -> bool {
+    *x1 <= *x2
+}
+
+/**
+ * Returns a pointer to a type descriptor.
+ *
+ * Useful for calling certain function in the Rust runtime or otherwise
+ * performing dark magick.
+ */
+#[inline(always)]
+pub fn get_type_desc<T>() -> *TypeDesc {
+    unsafe { intrinsics::get_tydesc::<T>() as *TypeDesc }
+}
+
+/// Returns a pointer to a type descriptor.
+#[inline(always)]
+pub fn get_type_desc_val<T>(_val: &T) -> *TypeDesc {
+    get_type_desc::<T>()
+}
+
+/// Returns the size of a type
+#[inline(always)]
+pub fn size_of<T>() -> uint {
+    unsafe { intrinsics::size_of::<T>() }
+}
+
+/// Returns the size of the type that `_val` points to
+#[inline(always)]
+pub fn size_of_val<T>(_val: &T) -> uint {
+    size_of::<T>()
+}
+
+/**
+ * Returns the size of a type, or 1 if the actual size is zero.
+ *
+ * Useful for building structures containing variable-length arrays.
+ */
+#[inline(always)]
+pub fn nonzero_size_of<T>() -> uint {
+    let s = size_of::<T>();
+    if s == 0 { 1 } else { s }
+}
+
+/// Returns the size of the type of the value that `_val` points to
+#[inline(always)]
+pub fn nonzero_size_of_val<T>(_val: &T) -> uint {
+    nonzero_size_of::<T>()
+}
+
+
+/**
+ * Returns the ABI-required minimum alignment of a type
+ *
+ * This is the alignment used for struct fields. It may be smaller
+ * than the preferred alignment.
+ */
+#[inline(always)]
+pub fn min_align_of<T>() -> uint {
+    unsafe { intrinsics::min_align_of::<T>() }
+}
+
+/// Returns the ABI-required minimum alignment of the type of the value that
+/// `_val` points to
+#[inline(always)]
+pub fn min_align_of_val<T>(_val: &T) -> uint {
+    min_align_of::<T>()
+}
+
+/// Returns the preferred alignment of a type
+#[inline(always)]
+pub fn pref_align_of<T>() -> uint {
+    unsafe { intrinsics::pref_align_of::<T>() }
+}
+
+/// Returns the preferred alignment of the type of the value that
+/// `_val` points to
+#[inline(always)]
+pub fn pref_align_of_val<T>(_val: &T) -> uint {
+    pref_align_of::<T>()
+}
+
+/// Returns the refcount of a shared box (as just before calling this)
+#[inline(always)]
+pub fn refcount<T>(t: @T) -> uint {
+    unsafe {
+        let ref_ptr: *uint = cast::transmute_copy(&t);
+        *ref_ptr - 1
+    }
+}
+
+pub fn log_str<T>(t: &T) -> ~str {
+    do io::with_str_writer |wr| {
+        repr::write_repr(wr, t)
+    }
+}
+
+/// Trait for initiating task failure.
+pub trait FailWithCause {
+    /// Fail the current task, taking ownership of `cause`
+    fn fail_with(cause: Self, file: &'static str, line: uint) -> !;
+}
+
+impl FailWithCause for ~str {
+    fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! {
+        do str::as_buf(cause) |msg_buf, _msg_len| {
+            do str::as_buf(file) |file_buf, _file_len| {
+                unsafe {
+                    let msg_buf = cast::transmute(msg_buf);
+                    let file_buf = cast::transmute(file_buf);
+                    begin_unwind_(msg_buf, file_buf, line as libc::size_t)
+                }
+            }
+        }
+    }
+}
+
+impl FailWithCause for &'static str {
+    fn fail_with(cause: &'static str, file: &'static str, line: uint) -> ! {
+        do str::as_buf(cause) |msg_buf, _msg_len| {
+            do str::as_buf(file) |file_buf, _file_len| {
+                unsafe {
+                    let msg_buf = cast::transmute(msg_buf);
+                    let file_buf = cast::transmute(file_buf);
+                    begin_unwind_(msg_buf, file_buf, line as libc::size_t)
+                }
+            }
+        }
+    }
+}
+
+// FIXME #4427: Temporary until rt::rt_fail_ goes away
+pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
+    use option::Option;
+    use rt::{context, OldTaskContext, TaskContext};
+    use rt::task::{Task, Unwinder};
+    use rt::local::Local;
+
+    let context = context();
+    match context {
+        OldTaskContext => {
+            unsafe {
+                gc::cleanup_stack_for_failure();
+                rustrt::rust_upcall_fail(msg, file, line);
+                cast::transmute(())
+            }
+        }
+        _ => {
+            unsafe {
+                // XXX: Bad re-allocations. fail! needs some refactoring
+                let msg = str::raw::from_c_str(msg);
+                let file = str::raw::from_c_str(file);
+
+                let outmsg = fmt!("%s at line %i of file %s", msg, line as int, file);
+
+                // XXX: Logging doesn't work correctly in non-task context because it
+                // invokes the local heap
+                if context == TaskContext {
+                    error!(outmsg);
+                } else {
+                    rtdebug!("%s", outmsg);
+                }
+
+                gc::cleanup_stack_for_failure();
+
+                let task = Local::unsafe_borrow::<Task>();
+                let unwinder: &mut Option<Unwinder> = &mut (*task).unwinder;
+                match *unwinder {
+                    Some(ref mut unwinder) => unwinder.begin_unwind(),
+                    None => abort!("failure without unwinder. aborting process")
+                }
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use cast;
+    use sys::*;
+
+    #[test]
+    fn size_of_basic() {
+        assert_eq!(size_of::<u8>(), 1u);
+        assert_eq!(size_of::<u16>(), 2u);
+        assert_eq!(size_of::<u32>(), 4u);
+        assert_eq!(size_of::<u64>(), 8u);
+    }
+
+    #[test]
+    #[cfg(target_arch = "x86")]
+    #[cfg(target_arch = "arm")]
+    #[cfg(target_arch = "mips")]
+    fn size_of_32() {
+        assert_eq!(size_of::<uint>(), 4u);
+        assert_eq!(size_of::<*uint>(), 4u);
+    }
+
+    #[test]
+    #[cfg(target_arch = "x86_64")]
+    fn size_of_64() {
+        assert_eq!(size_of::<uint>(), 8u);
+        assert_eq!(size_of::<*uint>(), 8u);
+    }
+
+    #[test]
+    fn size_of_val_basic() {
+        assert_eq!(size_of_val(&1u8), 1);
+        assert_eq!(size_of_val(&1u16), 2);
+        assert_eq!(size_of_val(&1u32), 4);
+        assert_eq!(size_of_val(&1u64), 8);
+    }
+
+    #[test]
+    fn nonzero_size_of_basic() {
+        type Z = [i8, ..0];
+        assert_eq!(size_of::<Z>(), 0u);
+        assert_eq!(nonzero_size_of::<Z>(), 1u);
+        assert_eq!(nonzero_size_of::<uint>(), size_of::<uint>());
+    }
+
+    #[test]
+    fn nonzero_size_of_val_basic() {
+        let z = [0u8, ..0];
+        assert_eq!(size_of_val(&z), 0u);
+        assert_eq!(nonzero_size_of_val(&z), 1u);
+        assert_eq!(nonzero_size_of_val(&1u), size_of_val(&1u));
+    }
+
+    #[test]
+    fn align_of_basic() {
+        assert_eq!(pref_align_of::<u8>(), 1u);
+        assert_eq!(pref_align_of::<u16>(), 2u);
+        assert_eq!(pref_align_of::<u32>(), 4u);
+    }
+
+    #[test]
+    #[cfg(target_arch = "x86")]
+    #[cfg(target_arch = "arm")]
+    #[cfg(target_arch = "mips")]
+    fn align_of_32() {
+        assert_eq!(pref_align_of::<uint>(), 4u);
+        assert_eq!(pref_align_of::<*uint>(), 4u);
+    }
+
+    #[test]
+    #[cfg(target_arch = "x86_64")]
+    fn align_of_64() {
+        assert_eq!(pref_align_of::<uint>(), 8u);
+        assert_eq!(pref_align_of::<*uint>(), 8u);
+    }
+
+    #[test]
+    fn align_of_val_basic() {
+        assert_eq!(pref_align_of_val(&1u8), 1u);
+        assert_eq!(pref_align_of_val(&1u16), 2u);
+        assert_eq!(pref_align_of_val(&1u32), 4u);
+    }
+
+    #[test]
+    fn synthesize_closure() {
+        unsafe {
+            let x = 10;
+            let f: &fn(int) -> int = |y| x + y;
+
+            assert_eq!(f(20), 30);
+
+            let original_closure: Closure = cast::transmute(f);
+
+            let actual_function_pointer = original_closure.code;
+            let environment = original_closure.env;
+
+            let new_closure = Closure {
+                code: actual_function_pointer,
+                env: environment
+            };
+
+            let new_f: &fn(int) -> int = cast::transmute(new_closure);
+            assert_eq!(new_f(20), 30);
+        }
+    }
+
+    #[test]
+    #[should_fail]
+    fn fail_static() { FailWithCause::fail_with("cause", file!(), line!())  }
+
+    #[test]
+    #[should_fail]
+    fn fail_owned() { FailWithCause::fail_with(~"cause", file!(), line!())  }
+}
diff --git a/src/libstd/task/local_data_priv.rs b/src/libstd/task/local_data_priv.rs
new file mode 100644
index 00000000000..2f97eaacf4b
--- /dev/null
+++ b/src/libstd/task/local_data_priv.rs
@@ -0,0 +1,235 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[doc(hidden)]; // FIXME #3538
+
+use cast;
+use cmp::Eq;
+use libc;
+use prelude::*;
+use task::rt;
+use local_data::LocalDataKey;
+
+use super::rt::rust_task;
+use rt::task::{Task, LocalStorage};
+
+pub enum Handle {
+    OldHandle(*rust_task),
+    NewHandle(*mut LocalStorage)
+}
+
+impl Handle {
+    pub fn new() -> Handle {
+        use rt::{context, OldTaskContext};
+        use rt::local::Local;
+        unsafe {
+            match context() {
+                OldTaskContext => {
+                    OldHandle(rt::rust_get_task())
+                }
+                _ => {
+                    let task = Local::unsafe_borrow::<Task>();
+                    NewHandle(&mut (*task).storage)
+                }
+            }
+        }
+    }
+}
+
+pub trait LocalData { }
+impl<T: 'static> LocalData for @T { }
+
+impl Eq for @LocalData {
+    fn eq(&self, other: &@LocalData) -> bool {
+        unsafe {
+            let ptr_a: &(uint, uint) = cast::transmute(self);
+            let ptr_b: &(uint, uint) = cast::transmute(other);
+            return ptr_a == ptr_b;
+        }
+    }
+    fn ne(&self, other: &@LocalData) -> bool { !(*self).eq(other) }
+}
+
+// If TLS is used heavily in future, this could be made more efficient with a
+// proper map.
+type TaskLocalElement = (*libc::c_void, *libc::c_void, @LocalData);
+// Has to be a pointer at outermost layer; the foreign call returns void *.
+type TaskLocalMap = @mut ~[Option<TaskLocalElement>];
+
+fn cleanup_task_local_map(map_ptr: *libc::c_void) {
+    unsafe {
+        assert!(!map_ptr.is_null());
+        // Get and keep the single reference that was created at the
+        // beginning.
+        let _map: TaskLocalMap = cast::transmute(map_ptr);
+        // All local_data will be destroyed along with the map.
+    }
+}
+
+// Gets the map from the runtime. Lazily initialises if not done so already.
+unsafe fn get_local_map(handle: Handle) -> TaskLocalMap {
+    match handle {
+        OldHandle(task) => get_task_local_map(task),
+        NewHandle(local_storage) => get_newsched_local_map(local_storage)
+    }
+}
+
+unsafe fn get_task_local_map(task: *rust_task) -> TaskLocalMap {
+
+    extern fn cleanup_task_local_map_extern_cb(map_ptr: *libc::c_void) {
+        cleanup_task_local_map(map_ptr);
+    }
+
+    // Relies on the runtime initialising the pointer to null.
+    // Note: The map's box lives in TLS invisibly referenced once. Each time
+    // we retrieve it for get/set, we make another reference, which get/set
+    // drop when they finish. No "re-storing after modifying" is needed.
+    let map_ptr = rt::rust_get_task_local_data(task);
+    if map_ptr.is_null() {
+        let map: TaskLocalMap = @mut ~[];
+        // NB: This bumps the ref count before converting to an unsafe pointer,
+        // keeping the map alive until TLS is destroyed
+        rt::rust_set_task_local_data(task, cast::transmute(map));
+        rt::rust_task_local_data_atexit(task, cleanup_task_local_map_extern_cb);
+        map
+    } else {
+        let map = cast::transmute(map_ptr);
+        let nonmut = cast::transmute::<TaskLocalMap,
+                                       @~[Option<TaskLocalElement>]>(map);
+        cast::bump_box_refcount(nonmut);
+        map
+    }
+}
+
+unsafe fn get_newsched_local_map(local: *mut LocalStorage) -> TaskLocalMap {
+    match &mut *local {
+        &LocalStorage(map_ptr, Some(_)) => {
+            assert!(map_ptr.is_not_null());
+            let map = cast::transmute(map_ptr);
+            let nonmut = cast::transmute::<TaskLocalMap,
+            @~[Option<TaskLocalElement>]>(map);
+            cast::bump_box_refcount(nonmut);
+            return map;
+        }
+        &LocalStorage(ref mut map_ptr, ref mut at_exit) => {
+            assert!((*map_ptr).is_null());
+            let map: TaskLocalMap = @mut ~[];
+            *map_ptr = cast::transmute(map);
+            let at_exit_fn: ~fn(*libc::c_void) = |p|cleanup_task_local_map(p);
+            *at_exit = Some(at_exit_fn);
+            return map;
+        }
+    }
+}
+
+unsafe fn key_to_key_value<T: 'static>(key: LocalDataKey<T>) -> *libc::c_void {
+    // Keys are closures, which are (fnptr,envptr) pairs. Use fnptr.
+    // Use reinterpret_cast -- transmute would leak (forget) the closure.
+    let pair: (*libc::c_void, *libc::c_void) = cast::transmute_copy(&key);
+    pair.first()
+}
+
+// If returning Some(..), returns with @T with the map's reference. Careful!
+unsafe fn local_data_lookup<T: 'static>(
+    map: TaskLocalMap, key: LocalDataKey<T>)
+    -> Option<(uint, *libc::c_void)> {
+
+    let key_value = key_to_key_value(key);
+    let map_pos = (*map).position(|entry|
+        match *entry {
+            Some((k,_,_)) => k == key_value,
+            None => false
+        }
+    );
+    do map_pos.map |index| {
+        // .get() is guaranteed because of "None { false }" above.
+        let (_, data_ptr, _) = (*map)[*index].get();
+        (*index, data_ptr)
+    }
+}
+
+unsafe fn local_get_helper<T: 'static>(
+    handle: Handle, key: LocalDataKey<T>,
+    do_pop: bool) -> Option<@T> {
+
+    let map = get_local_map(handle);
+    // Interpreturn our findings from the map
+    do local_data_lookup(map, key).map |result| {
+        // A reference count magically appears on 'data' out of thin air. It
+        // was referenced in the local_data box, though, not here, so before
+        // overwriting the local_data_box we need to give an extra reference.
+        // We must also give an extra reference when not removing.
+        let (index, data_ptr) = *result;
+        let data: @T = cast::transmute(data_ptr);
+        cast::bump_box_refcount(data);
+        if do_pop {
+            map[index] = None;
+        }
+        data
+    }
+}
+
+
+pub unsafe fn local_pop<T: 'static>(
+    handle: Handle,
+    key: LocalDataKey<T>) -> Option<@T> {
+
+    local_get_helper(handle, key, true)
+}
+
+pub unsafe fn local_get<T: 'static>(
+    handle: Handle,
+    key: LocalDataKey<T>) -> Option<@T> {
+
+    local_get_helper(handle, key, false)
+}
+
+pub unsafe fn local_set<T: 'static>(
+    handle: Handle, key: LocalDataKey<T>, data: @T) {
+
+    let map = get_local_map(handle);
+    // Store key+data as *voids. Data is invisibly referenced once; key isn't.
+    let keyval = key_to_key_value(key);
+    // We keep the data in two forms: one as an unsafe pointer, so we can get
+    // it back by casting; another in an existential box, so the reference we
+    // own on it can be dropped when the box is destroyed. The unsafe pointer
+    // does not have a reference associated with it, so it may become invalid
+    // when the box is destroyed.
+    let data_ptr = *cast::transmute::<&@T, &*libc::c_void>(&data);
+    let data_box = @data as @LocalData;
+    // Construct new entry to store in the map.
+    let new_entry = Some((keyval, data_ptr, data_box));
+    // Find a place to put it.
+    match local_data_lookup(map, key) {
+        Some((index, _old_data_ptr)) => {
+            // Key already had a value set, _old_data_ptr, whose reference
+            // will get dropped when the local_data box is overwritten.
+            map[index] = new_entry;
+        }
+        None => {
+            // Find an empty slot. If not, grow the vector.
+            match (*map).position(|x| x.is_none()) {
+                Some(empty_index) => { map[empty_index] = new_entry; }
+                None => { map.push(new_entry); }
+            }
+        }
+    }
+}
+
+pub unsafe fn local_modify<T: 'static>(
+    handle: Handle, key: LocalDataKey<T>,
+    modify_fn: &fn(Option<@T>) -> Option<@T>) {
+
+    // Could be more efficient by doing the lookup work, but this is easy.
+    let newdata = modify_fn(local_pop(handle, key));
+    if newdata.is_some() {
+        local_set(handle, key, newdata.unwrap());
+    }
+}
diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs
new file mode 100644
index 00000000000..490a69248ee
--- /dev/null
+++ b/src/libstd/task/mod.rs
@@ -0,0 +1,1189 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+ * Task management.
+ *
+ * An executing Rust program consists of a tree of tasks, each with their own
+ * stack, and sole ownership of their allocated heap data. Tasks communicate
+ * with each other using ports and channels.
+ *
+ * When a task fails, that failure will propagate to its parent (the task
+ * that spawned it) and the parent will fail as well. The reverse is not
+ * true: when a parent task fails its children will continue executing. When
+ * the root (main) task fails, all tasks fail, and then so does the entire
+ * process.
+ *
+ * Tasks may execute in parallel and are scheduled automatically by the
+ * runtime.
+ *
+ * # Example
+ *
+ * ~~~
+ * do spawn {
+ *     log(error, "Hello, World!");
+ * }
+ * ~~~
+ */
+
+use cell::Cell;
+use cmp::Eq;
+use result::Result;
+use comm::{stream, Chan, GenericChan, GenericPort, Port};
+use prelude::*;
+use result;
+use task::rt::{task_id, sched_id};
+use util;
+use util::replace;
+use unstable::finally::Finally;
+use rt::{context, OldTaskContext};
+
+#[cfg(test)] use comm::SharedChan;
+
+mod local_data_priv;
+pub mod rt;
+pub mod spawn;
+
+/// A handle to a scheduler
+#[deriving(Eq)]
+pub enum Scheduler {
+    SchedulerHandle(sched_id)
+}
+
+/// A handle to a task
+#[deriving(Eq)]
+pub enum Task {
+    TaskHandle(task_id)
+}
+
+/**
+ * Indicates the manner in which a task exited.
+ *
+ * A task that completes without failing is considered to exit successfully.
+ * Supervised ancestors and linked siblings may yet fail after this task
+ * succeeds. Also note that in such a case, it may be nondeterministic whether
+ * linked failure or successful exit happen first.
+ *
+ * If you wish for this result's delivery to block until all linked and/or
+ * children tasks complete, recommend using a result future.
+ */
+#[deriving(Eq)]
+pub enum TaskResult {
+    Success,
+    Failure,
+}
+
+/// Scheduler modes
+#[deriving(Eq)]
+pub enum SchedMode {
+    /// Run task on the default scheduler
+    DefaultScheduler,
+    /// Run task on the current scheduler
+    CurrentScheduler,
+    /// Run task on a specific scheduler
+    ExistingScheduler(Scheduler),
+    /**
+     * Tasks are scheduled on the main OS thread
+     *
+     * The main OS thread is the thread used to launch the runtime which,
+     * in most cases, is the process's initial thread as created by the OS.
+     */
+    PlatformThread,
+    /// All tasks run in the same OS thread
+    SingleThreaded,
+    /// Tasks are distributed among available CPUs
+    ThreadPerCore,
+    /// Each task runs in its own OS thread
+    ThreadPerTask,
+    /// Tasks are distributed among a fixed number of OS threads
+    ManualThreads(uint),
+}
+
+/**
+ * Scheduler configuration options
+ *
+ * # Fields
+ *
+ * * sched_mode - The operating mode of the scheduler
+ *
+ * * foreign_stack_size - The size of the foreign stack, in bytes
+ *
+ *     Rust code runs on Rust-specific stacks. When Rust code calls foreign
+ *     code (via functions in foreign modules) it switches to a typical, large
+ *     stack appropriate for running code written in languages like C. By
+ *     default these foreign stacks have unspecified size, but with this
+ *     option their size can be precisely specified.
+ */
+pub struct SchedOpts {
+    mode: SchedMode,
+    foreign_stack_size: Option<uint>,
+}
+
+/**
+ * Task configuration options
+ *
+ * # Fields
+ *
+ * * linked - Propagate failure bidirectionally between child and parent.
+ *            True by default. If both this and 'supervised' are false, then
+ *            either task's failure will not affect the other ("unlinked").
+ *
+ * * supervised - Propagate failure unidirectionally from parent to child,
+ *                but not from child to parent. False by default.
+ *
+ * * notify_chan - Enable lifecycle notifications on the given channel
+ *
+ * * sched - Specify the configuration of a new scheduler to create the task
+ *           in
+ *
+ *     By default, every task is created in the same scheduler as its
+ *     parent, where it is scheduled cooperatively with all other tasks
+ *     in that scheduler. Some specialized applications may want more
+ *     control over their scheduling, in which case they can be spawned
+ *     into a new scheduler with the specific properties required.
+ *
+ *     This is of particular importance for libraries which want to call
+ *     into foreign code that blocks. Without doing so in a different
+ *     scheduler other tasks will be impeded or even blocked indefinitely.
+ */
+pub struct TaskOpts {
+    linked: bool,
+    supervised: bool,
+    notify_chan: Option<Chan<TaskResult>>,
+    sched: SchedOpts
+}
+
+/**
+ * The task builder type.
+ *
+ * Provides detailed control over the properties and behavior of new tasks.
+ */
+// NB: Builders are designed to be single-use because they do stateful
+// things that get weird when reusing - e.g. if you create a result future
+// it only applies to a single task, so then you have to maintain Some
+// potentially tricky state to ensure that everything behaves correctly
+// when you try to reuse the builder to spawn a new task. We'll just
+// sidestep that whole issue by making builders uncopyable and making
+// the run function move them in.
+
+// FIXME (#3724): Replace the 'consumed' bit with move mode on self
+pub struct TaskBuilder {
+    opts: TaskOpts,
+    gen_body: Option<~fn(v: ~fn()) -> ~fn()>,
+    can_not_copy: Option<util::NonCopyable>,
+    consumed: bool,
+}
+
+/**
+ * Generate the base configuration for spawning a task, off of which more
+ * configuration methods can be chained.
+ * For example, task().unlinked().spawn is equivalent to spawn_unlinked.
+ */
+pub fn task() -> TaskBuilder {
+    TaskBuilder {
+        opts: default_task_opts(),
+        gen_body: None,
+        can_not_copy: None,
+        consumed: false,
+    }
+}
+
+#[doc(hidden)] // FIXME #3538
+priv impl TaskBuilder {
+    fn consume(&mut self) -> TaskBuilder {
+        if self.consumed {
+            fail!("Cannot copy a task_builder"); // Fake move mode on self
+        }
+        self.consumed = true;
+        let gen_body = replace(&mut self.gen_body, None);
+        let notify_chan = replace(&mut self.opts.notify_chan, None);
+        TaskBuilder {
+            opts: TaskOpts {
+                linked: self.opts.linked,
+                supervised: self.opts.supervised,
+                notify_chan: notify_chan,
+                sched: self.opts.sched
+            },
+            gen_body: gen_body,
+            can_not_copy: None,
+            consumed: false
+        }
+    }
+}
+
+pub impl TaskBuilder {
+    /// Decouple the child task's failure from the parent's. If either fails,
+    /// the other will not be killed.
+    fn unlinked(&mut self) {
+        self.opts.linked = false;
+    }
+
+    /// Unidirectionally link the child task's failure with the parent's. The
+    /// child's failure will not kill the parent, but the parent's will kill
+    /// the child.
+    fn supervised(&mut self) {
+        self.opts.supervised = true;
+        self.opts.linked = false;
+    }
+
+    /// Link the child task's and parent task's failures. If either fails, the
+    /// other will be killed.
+    fn linked(&mut self) {
+        self.opts.linked = true;
+        self.opts.supervised = false;
+    }
+
+    /**
+     * Get a future representing the exit status of the task.
+     *
+     * Taking the value of the future will block until the child task
+     * terminates. The future-receiving callback specified will be called
+     * *before* the task is spawned; as such, do not invoke .get() within the
+     * closure; rather, store it in an outer variable/list for later use.
+     *
+     * Note that the future returning by this function is only useful for
+     * obtaining the value of the next task to be spawning with the
+     * builder. If additional tasks are spawned with the same builder
+     * then a new result future must be obtained prior to spawning each
+     * task.
+     *
+     * # Failure
+     * Fails if a future_result was already set for this task.
+     */
+    fn future_result(&mut self, blk: &fn(v: Port<TaskResult>)) {
+        // FIXME (#3725): Once linked failure and notification are
+        // handled in the library, I can imagine implementing this by just
+        // registering an arbitrary number of task::on_exit handlers and
+        // sending out messages.
+
+        if self.opts.notify_chan.is_some() {
+            fail!("Can't set multiple future_results for one task!");
+        }
+
+        // Construct the future and give it to the caller.
+        let (notify_pipe_po, notify_pipe_ch) = stream::<TaskResult>();
+
+        blk(notify_pipe_po);
+
+        // Reconfigure self to use a notify channel.
+        self.opts.notify_chan = Some(notify_pipe_ch);
+    }
+
+    /// Configure a custom scheduler mode for the task.
+    fn sched_mode(&mut self, mode: SchedMode) {
+        self.opts.sched.mode = mode;
+    }
+
+    /**
+     * Add a wrapper to the body of the spawned task.
+     *
+     * Before the task is spawned it is passed through a 'body generator'
+     * function that may perform local setup operations as well as wrap
+     * the task body in remote setup operations. With this the behavior
+     * of tasks can be extended in simple ways.
+     *
+     * This function augments the current body generator with a new body
+     * generator by applying the task body which results from the
+     * existing body generator to the new body generator.
+     */
+    fn add_wrapper(&mut self, wrapper: ~fn(v: ~fn()) -> ~fn()) {
+        let prev_gen_body = replace(&mut self.gen_body, None);
+        let prev_gen_body = match prev_gen_body {
+            Some(gen) => gen,
+            None => {
+                let f: ~fn(~fn()) -> ~fn() = |body| body;
+                f
+            }
+        };
+        let prev_gen_body = Cell(prev_gen_body);
+        let next_gen_body = {
+            let f: ~fn(~fn()) -> ~fn() = |body| {
+                let prev_gen_body = prev_gen_body.take();
+                wrapper(prev_gen_body(body))
+            };
+            f
+        };
+        self.gen_body = Some(next_gen_body);
+    }
+
+    /**
+     * Creates and executes a new child task
+     *
+     * Sets up a new task with its own call stack and schedules it to run
+     * the provided unique closure. The task has the properties and behavior
+     * specified by the task_builder.
+     *
+     * # Failure
+     *
+     * When spawning into a new scheduler, the number of threads requested
+     * must be greater than zero.
+     */
+    fn spawn(&mut self, f: ~fn()) {
+        let gen_body = replace(&mut self.gen_body, None);
+        let notify_chan = replace(&mut self.opts.notify_chan, None);
+        let x = self.consume();
+        let opts = TaskOpts {
+            linked: x.opts.linked,
+            supervised: x.opts.supervised,
+            notify_chan: notify_chan,
+            sched: x.opts.sched
+        };
+        let f = match gen_body {
+            Some(gen) => {
+                gen(f)
+            }
+            None => {
+                f
+            }
+        };
+        spawn::spawn_raw(opts, f);
+    }
+
+    /// Runs a task, while transfering ownership of one argument to the child.
+    fn spawn_with<A:Owned>(&mut self, arg: A, f: ~fn(v: A)) {
+        let arg = Cell(arg);
+        do self.spawn {
+            f(arg.take());
+        }
+    }
+
+    /**
+     * Execute a function in another task and return either the return value
+     * of the function or result::err.
+     *
+     * # Return value
+     *
+     * If the function executed successfully then try returns result::ok
+     * containing the value returned by the function. If the function fails
+     * then try returns result::err containing nil.
+     *
+     * # Failure
+     * Fails if a future_result was already set for this task.
+     */
+    fn try<T:Owned>(&mut self, f: ~fn() -> T) -> Result<T,()> {
+        let (po, ch) = stream::<T>();
+        let mut result = None;
+
+        self.future_result(|r| { result = Some(r); });
+
+        do self.spawn {
+            ch.send(f());
+        }
+
+        match result.unwrap().recv() {
+            Success => result::Ok(po.recv()),
+            Failure => result::Err(())
+        }
+    }
+}
+
+
+/* Task construction */
+
+pub fn default_task_opts() -> TaskOpts {
+    /*!
+     * The default task options
+     *
+     * By default all tasks are supervised by their parent, are spawned
+     * into the same scheduler, and do not post lifecycle notifications.
+     */
+
+    TaskOpts {
+        linked: true,
+        supervised: false,
+        notify_chan: None,
+        sched: SchedOpts {
+            mode: DefaultScheduler,
+            foreign_stack_size: None
+        }
+    }
+}
+
+/* Spawn convenience functions */
+
+/// Creates and executes a new child task
+///
+/// Sets up a new task with its own call stack and schedules it to run
+/// the provided unique closure.
+///
+/// This function is equivalent to `task().spawn(f)`.
+pub fn spawn(f: ~fn()) {
+    let mut task = task();
+    task.spawn(f)
+}
+
+/// Creates a child task unlinked from the current one. If either this
+/// task or the child task fails, the other will not be killed.
+pub fn spawn_unlinked(f: ~fn()) {
+    let mut task = task();
+    task.unlinked();
+    task.spawn(f)
+}
+
+pub fn spawn_supervised(f: ~fn()) {
+    /*!
+     * Creates a child task supervised by the current one. If the child
+     * task fails, the parent will not be killed, but if the parent fails,
+     * the child will be killed.
+     */
+
+    let mut task = task();
+    task.supervised();
+    task.spawn(f)
+}
+
+pub fn spawn_with<A:Owned>(arg: A, f: ~fn(v: A)) {
+    /*!
+     * Runs a task, while transfering ownership of one argument to the
+     * child.
+     *
+     * This is useful for transfering ownership of noncopyables to
+     * another task.
+     *
+     * This function is equivalent to `task().spawn_with(arg, f)`.
+     */
+
+    let mut task = task();
+    task.spawn_with(arg, f)
+}
+
+pub fn spawn_sched(mode: SchedMode, f: ~fn()) {
+    /*!
+     * Creates a new task on a new or existing scheduler
+
+     * When there are no more tasks to execute the
+     * scheduler terminates.
+     *
+     * # Failure
+     *
+     * In manual threads mode the number of threads requested must be
+     * greater than zero.
+     */
+
+    let mut task = task();
+    task.sched_mode(mode);
+    task.spawn(f)
+}
+
+pub fn try<T:Owned>(f: ~fn() -> T) -> Result<T,()> {
+    /*!
+     * Execute a function in another task and return either the return value
+     * of the function or result::err.
+     *
+     * This is equivalent to task().supervised().try.
+     */
+
+    let mut task = task();
+    task.supervised();
+    task.try(f)
+}
+
+
+/* Lifecycle functions */
+
+pub fn yield() {
+    //! Yield control to the task scheduler
+
+    unsafe {
+        let task_ = rt::rust_get_task();
+        let killed = rt::rust_task_yield(task_);
+        if killed && !failing() {
+            fail!("killed");
+        }
+    }
+}
+
+pub fn failing() -> bool {
+    //! True if the running task has failed
+
+    use rt::{context, OldTaskContext};
+    use rt::local::Local;
+    use rt::task::Task;
+
+    match context() {
+        OldTaskContext => {
+            unsafe {
+                rt::rust_task_is_unwinding(rt::rust_get_task())
+            }
+        }
+        _ => {
+            let mut unwinding = false;
+            do Local::borrow::<Task> |local| {
+                unwinding = match local.unwinder {
+                    Some(unwinder) => {
+                        unwinder.unwinding
+                    }
+                    None => {
+                        // Because there is no unwinder we can't be unwinding.
+                        // (The process will abort on failure)
+                        false
+                    }
+                }
+            }
+            return unwinding;
+        }
+    }
+}
+
+pub fn get_task() -> Task {
+    //! Get a handle to the running task
+
+    unsafe {
+        TaskHandle(rt::get_task_id())
+    }
+}
+
+pub fn get_scheduler() -> Scheduler {
+    SchedulerHandle(unsafe { rt::rust_get_sched_id() })
+}
+
+/**
+ * Temporarily make the task unkillable
+ *
+ * # Example
+ *
+ * ~~~
+ * do task::unkillable {
+ *     // detach / yield / destroy must all be called together
+ *     rustrt::rust_port_detach(po);
+ *     // This must not result in the current task being killed
+ *     task::yield();
+ *     rustrt::rust_port_destroy(po);
+ * }
+ * ~~~
+ */
+pub unsafe fn unkillable<U>(f: &fn() -> U) -> U {
+    if context() == OldTaskContext {
+        let t = rt::rust_get_task();
+        do (|| {
+            rt::rust_task_inhibit_kill(t);
+            f()
+        }).finally {
+            rt::rust_task_allow_kill(t);
+        }
+    } else {
+        // FIXME #6377
+        f()
+    }
+}
+
+/// The inverse of unkillable. Only ever to be used nested in unkillable().
+pub unsafe fn rekillable<U>(f: &fn() -> U) -> U {
+    if context() == OldTaskContext {
+        let t = rt::rust_get_task();
+        do (|| {
+            rt::rust_task_allow_kill(t);
+            f()
+        }).finally {
+            rt::rust_task_inhibit_kill(t);
+        }
+    } else {
+        // FIXME #6377
+        f()
+    }
+}
+
+/**
+ * A stronger version of unkillable that also inhibits scheduling operations.
+ * For use with exclusive ARCs, which use pthread mutexes directly.
+ */
+pub unsafe fn atomically<U>(f: &fn() -> U) -> U {
+    if context() == OldTaskContext {
+        let t = rt::rust_get_task();
+        do (|| {
+            rt::rust_task_inhibit_kill(t);
+            rt::rust_task_inhibit_yield(t);
+            f()
+        }).finally {
+            rt::rust_task_allow_yield(t);
+            rt::rust_task_allow_kill(t);
+        }
+    } else {
+        // FIXME #6377
+        f()
+    }
+}
+
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_cant_dup_task_builder() {
+    let mut builder = task();
+    builder.unlinked();
+    do builder.spawn {}
+    // FIXME(#3724): For now, this is a -runtime- failure, because we haven't
+    // got move mode on self. When 3724 is fixed, this test should fail to
+    // compile instead, and should go in tests/compile-fail.
+    do builder.spawn {} // b should have been consumed by the previous call
+}
+
+// The following 8 tests test the following 2^3 combinations:
+// {un,}linked {un,}supervised failure propagation {up,down}wards.
+
+// !!! These tests are dangerous. If Something is buggy, they will hang, !!!
+// !!! instead of exiting cleanly. This might wedge the buildbots.       !!!
+
+#[test] #[ignore(cfg(windows))]
+fn test_spawn_unlinked_unsup_no_fail_down() { // grandchild sends on a port
+    let (po, ch) = stream();
+    let ch = SharedChan::new(ch);
+    do spawn_unlinked {
+        let ch = ch.clone();
+        do spawn_unlinked {
+            // Give middle task a chance to fail-but-not-kill-us.
+            for 16.times { task::yield(); }
+            ch.send(()); // If killed first, grandparent hangs.
+        }
+        fail!(); // Shouldn't kill either (grand)parent or (grand)child.
+    }
+    po.recv();
+}
+#[test] #[ignore(cfg(windows))]
+fn test_spawn_unlinked_unsup_no_fail_up() { // child unlinked fails
+    do spawn_unlinked { fail!(); }
+}
+#[test] #[ignore(cfg(windows))]
+fn test_spawn_unlinked_sup_no_fail_up() { // child unlinked fails
+    do spawn_supervised { fail!(); }
+    // Give child a chance to fail-but-not-kill-us.
+    for 16.times { task::yield(); }
+}
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_spawn_unlinked_sup_fail_down() {
+    do spawn_supervised { loop { task::yield(); } }
+    fail!(); // Shouldn't leave a child hanging around.
+}
+
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_spawn_linked_sup_fail_up() { // child fails; parent fails
+    let (po, _ch) = stream::<()>();
+
+    // Unidirectional "parenting" shouldn't override bidirectional linked.
+    // We have to cheat with opts - the interface doesn't support them because
+    // they don't make sense (redundant with task().supervised()).
+    let mut b0 = task();
+    b0.opts.linked = true;
+    b0.opts.supervised = true;
+
+    do b0.spawn {
+        fail!();
+    }
+    po.recv(); // We should get punted awake
+}
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_spawn_linked_sup_fail_down() { // parent fails; child fails
+    // We have to cheat with opts - the interface doesn't support them because
+    // they don't make sense (redundant with task().supervised()).
+    let mut b0 = task();
+    b0.opts.linked = true;
+    b0.opts.supervised = true;
+    do b0.spawn {
+        loop {
+            task::yield();
+        }
+    }
+    fail!(); // *both* mechanisms would be wrong if this didn't kill the child
+}
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_spawn_linked_unsup_fail_up() { // child fails; parent fails
+    let (po, _ch) = stream::<()>();
+    // Default options are to spawn linked & unsupervised.
+    do spawn { fail!(); }
+    po.recv(); // We should get punted awake
+}
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_spawn_linked_unsup_fail_down() { // parent fails; child fails
+    // Default options are to spawn linked & unsupervised.
+    do spawn { loop { task::yield(); } }
+    fail!();
+}
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_spawn_linked_unsup_default_opts() { // parent fails; child fails
+    // Make sure the above test is the same as this one.
+    let mut builder = task();
+    builder.linked();
+    do builder.spawn {
+        loop {
+            task::yield();
+        }
+    }
+    fail!();
+}
+
+// A couple bonus linked failure tests - testing for failure propagation even
+// when the middle task exits successfully early before kill signals are sent.
+
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_spawn_failure_propagate_grandchild() {
+    // Middle task exits; does grandparent's failure propagate across the gap?
+    do spawn_supervised {
+        do spawn_supervised {
+            loop { task::yield(); }
+        }
+    }
+    for 16.times { task::yield(); }
+    fail!();
+}
+
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_spawn_failure_propagate_secondborn() {
+    // First-born child exits; does parent's failure propagate to sibling?
+    do spawn_supervised {
+        do spawn { // linked
+            loop { task::yield(); }
+        }
+    }
+    for 16.times { task::yield(); }
+    fail!();
+}
+
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_spawn_failure_propagate_nephew_or_niece() {
+    // Our sibling exits; does our failure propagate to sibling's child?
+    do spawn { // linked
+        do spawn_supervised {
+            loop { task::yield(); }
+        }
+    }
+    for 16.times { task::yield(); }
+    fail!();
+}
+
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_spawn_linked_sup_propagate_sibling() {
+    // Middle sibling exits - does eldest's failure propagate to youngest?
+    do spawn { // linked
+        do spawn { // linked
+            loop { task::yield(); }
+        }
+    }
+    for 16.times { task::yield(); }
+    fail!();
+}
+
+#[test]
+fn test_run_basic() {
+    let (po, ch) = stream::<()>();
+    let mut builder = task();
+    do builder.spawn {
+        ch.send(());
+    }
+    po.recv();
+}
+
+#[cfg(test)]
+struct Wrapper {
+    f: Option<Chan<()>>
+}
+
+#[test]
+fn test_add_wrapper() {
+    let (po, ch) = stream::<()>();
+    let mut b0 = task();
+    let ch = Cell(ch);
+    do b0.add_wrapper |body| {
+        let ch = Cell(ch.take());
+        let result: ~fn() = || {
+            let ch = ch.take();
+            body();
+            ch.send(());
+        };
+        result
+    };
+    do b0.spawn { }
+    po.recv();
+}
+
+#[test]
+#[ignore(cfg(windows))]
+fn test_future_result() {
+    let mut result = None;
+    let mut builder = task();
+    builder.future_result(|r| result = Some(r));
+    do builder.spawn {}
+    assert_eq!(result.unwrap().recv(), Success);
+
+    result = None;
+    let mut builder = task();
+    builder.future_result(|r| result = Some(r));
+    builder.unlinked();
+    do builder.spawn {
+        fail!();
+    }
+    assert_eq!(result.unwrap().recv(), Failure);
+}
+
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_back_to_the_future_result() {
+    let mut builder = task();
+    builder.future_result(util::ignore);
+    builder.future_result(util::ignore);
+}
+
+#[test]
+fn test_try_success() {
+    match do try {
+        ~"Success!"
+    } {
+        result::Ok(~"Success!") => (),
+        _ => fail!()
+    }
+}
+
+#[test]
+#[ignore(cfg(windows))]
+fn test_try_fail() {
+    match do try {
+        fail!()
+    } {
+        result::Err(()) => (),
+        result::Ok(()) => fail!()
+    }
+}
+
+#[test]
+#[should_fail]
+#[ignore(cfg(windows))]
+fn test_spawn_sched_no_threads() {
+    do spawn_sched(ManualThreads(0u)) { }
+}
+
+#[test]
+fn test_spawn_sched() {
+    let (po, ch) = stream::<()>();
+    let ch = SharedChan::new(ch);
+
+    fn f(i: int, ch: SharedChan<()>) {
+        let parent_sched_id = unsafe { rt::rust_get_sched_id() };
+
+        do spawn_sched(SingleThreaded) {
+            let child_sched_id = unsafe { rt::rust_get_sched_id() };
+            assert!(parent_sched_id != child_sched_id);
+
+            if (i == 0) {
+                ch.send(());
+            } else {
+                f(i - 1, ch.clone());
+            }
+        };
+
+    }
+    f(10, ch);
+    po.recv();
+}
+
+#[test]
+fn test_spawn_sched_childs_on_default_sched() {
+    let (po, ch) = stream();
+
+    // Assuming tests run on the default scheduler
+    let default_id = unsafe { rt::rust_get_sched_id() };
+
+    let ch = Cell(ch);
+    do spawn_sched(SingleThreaded) {
+        let parent_sched_id = unsafe { rt::rust_get_sched_id() };
+        let ch = Cell(ch.take());
+        do spawn {
+            let ch = ch.take();
+            let child_sched_id = unsafe { rt::rust_get_sched_id() };
+            assert!(parent_sched_id != child_sched_id);
+            assert_eq!(child_sched_id, default_id);
+            ch.send(());
+        };
+    };
+
+    po.recv();
+}
+
+#[cfg(test)]
+mod testrt {
+    use libc;
+
+    #[nolink]
+    pub extern {
+        unsafe fn rust_dbg_lock_create() -> *libc::c_void;
+        unsafe fn rust_dbg_lock_destroy(lock: *libc::c_void);
+        unsafe fn rust_dbg_lock_lock(lock: *libc::c_void);
+        unsafe fn rust_dbg_lock_unlock(lock: *libc::c_void);
+        unsafe fn rust_dbg_lock_wait(lock: *libc::c_void);
+        unsafe fn rust_dbg_lock_signal(lock: *libc::c_void);
+    }
+}
+
+#[test]
+fn test_spawn_sched_blocking() {
+    unsafe {
+
+        // Testing that a task in one scheduler can block in foreign code
+        // without affecting other schedulers
+        for 20u.times {
+            let (start_po, start_ch) = stream();
+            let (fin_po, fin_ch) = stream();
+
+            let lock = testrt::rust_dbg_lock_create();
+
+            do spawn_sched(SingleThreaded) {
+                unsafe {
+                    testrt::rust_dbg_lock_lock(lock);
+
+                    start_ch.send(());
+
+                    // Block the scheduler thread
+                    testrt::rust_dbg_lock_wait(lock);
+                    testrt::rust_dbg_lock_unlock(lock);
+
+                    fin_ch.send(());
+                }
+            };
+
+            // Wait until the other task has its lock
+            start_po.recv();
+
+            fn pingpong(po: &Port<int>, ch: &Chan<int>) {
+                let mut val = 20;
+                while val > 0 {
+                    val = po.recv();
+                    ch.send(val - 1);
+                }
+            }
+
+            let (setup_po, setup_ch) = stream();
+            let (parent_po, parent_ch) = stream();
+            do spawn {
+                let (child_po, child_ch) = stream();
+                setup_ch.send(child_ch);
+                pingpong(&child_po, &parent_ch);
+            };
+
+            let child_ch = setup_po.recv();
+            child_ch.send(20);
+            pingpong(&parent_po, &child_ch);
+            testrt::rust_dbg_lock_lock(lock);
+            testrt::rust_dbg_lock_signal(lock);
+            testrt::rust_dbg_lock_unlock(lock);
+            fin_po.recv();
+            testrt::rust_dbg_lock_destroy(lock);
+        }
+    }
+}
+
+#[cfg(test)]
+fn avoid_copying_the_body(spawnfn: &fn(v: ~fn())) {
+    let (p, ch) = stream::<uint>();
+
+    let x = ~1;
+    let x_in_parent = ptr::to_unsafe_ptr(&*x) as uint;
+
+    do spawnfn || {
+        let x_in_child = ptr::to_unsafe_ptr(&*x) as uint;
+        ch.send(x_in_child);
+    }
+
+    let x_in_child = p.recv();
+    assert_eq!(x_in_parent, x_in_child);
+}
+
+#[test]
+fn test_avoid_copying_the_body_spawn() {
+    avoid_copying_the_body(spawn);
+}
+
+#[test]
+fn test_avoid_copying_the_body_task_spawn() {
+    do avoid_copying_the_body |f| {
+        let mut builder = task();
+        do builder.spawn || {
+            f();
+        }
+    }
+}
+
+#[test]
+fn test_avoid_copying_the_body_try() {
+    do avoid_copying_the_body |f| {
+        do try || {
+            f()
+        };
+    }
+}
+
+#[test]
+fn test_avoid_copying_the_body_unlinked() {
+    do avoid_copying_the_body |f| {
+        do spawn_unlinked || {
+            f();
+        }
+    }
+}
+
+#[test]
+fn test_platform_thread() {
+    let (po, ch) = stream();
+    let mut builder = task();
+    builder.sched_mode(PlatformThread);
+    do builder.spawn {
+        ch.send(());
+    }
+    po.recv();
+}
+
+#[test]
+#[ignore(cfg(windows))]
+#[should_fail]
+fn test_unkillable() {
+    let (po, ch) = stream();
+
+    // We want to do this after failing
+    do spawn_unlinked {
+        for 10.times { yield() }
+        ch.send(());
+    }
+
+    do spawn {
+        yield();
+        // We want to fail after the unkillable task
+        // blocks on recv
+        fail!();
+    }
+
+    unsafe {
+        do unkillable {
+            let p = ~0;
+            let pp: *uint = cast::transmute(p);
+
+            // If we are killed here then the box will leak
+            po.recv();
+
+            let _p: ~int = cast::transmute(pp);
+        }
+    }
+
+    // Now we can be killed
+    po.recv();
+}
+
+#[test]
+#[ignore(cfg(windows))]
+#[should_fail]
+fn test_unkillable_nested() {
+    let (po, ch) = comm::stream();
+
+    // We want to do this after failing
+    do spawn_unlinked || {
+        for 10.times { yield() }
+        ch.send(());
+    }
+
+    do spawn {
+        yield();
+        // We want to fail after the unkillable task
+        // blocks on recv
+        fail!();
+    }
+
+    unsafe {
+        do unkillable {
+            do unkillable {} // Here's the difference from the previous test.
+            let p = ~0;
+            let pp: *uint = cast::transmute(p);
+
+            // If we are killed here then the box will leak
+            po.recv();
+
+            let _p: ~int = cast::transmute(pp);
+        }
+    }
+
+    // Now we can be killed
+    po.recv();
+}
+
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_atomically() {
+    unsafe { do atomically { yield(); } }
+}
+
+#[test]
+fn test_atomically2() {
+    unsafe { do atomically { } } yield(); // shouldn't fail
+}
+
+#[test] #[should_fail] #[ignore(cfg(windows))]
+fn test_atomically_nested() {
+    unsafe { do atomically { do atomically { } yield(); } }
+}
+
+#[test]
+fn test_child_doesnt_ref_parent() {
+    // If the child refcounts the parent task, this will stack overflow when
+    // climbing the task tree to dereference each ancestor. (See #1789)
+    // (well, it would if the constant were 8000+ - I lowered it to be more
+    // valgrind-friendly. try this at home, instead..!)
+    static generations: uint = 16;
+    fn child_no(x: uint) -> ~fn() {
+        return || {
+            if x < generations {
+                task::spawn(child_no(x+1));
+            }
+        }
+    }
+    task::spawn(child_no(0));
+}
+
+#[test]
+fn test_sched_thread_per_core() {
+    let (port, chan) = comm::stream();
+
+    do spawn_sched(ThreadPerCore) || {
+        unsafe {
+            let cores = rt::rust_num_threads();
+            let reported_threads = rt::rust_sched_threads();
+            assert_eq!(cores as uint, reported_threads as uint);
+            chan.send(());
+        }
+    }
+
+    port.recv();
+}
+
+#[test]
+fn test_spawn_thread_on_demand() {
+    let (port, chan) = comm::stream();
+
+    do spawn_sched(ManualThreads(2)) || {
+        unsafe {
+            let max_threads = rt::rust_sched_threads();
+            assert_eq!(max_threads as int, 2);
+            let running_threads = rt::rust_sched_current_nonlazy_threads();
+            assert_eq!(running_threads as int, 1);
+
+            let (port2, chan2) = comm::stream();
+
+            do spawn_sched(CurrentScheduler) || {
+                chan2.send(());
+            }
+
+            let running_threads2 = rt::rust_sched_current_nonlazy_threads();
+            assert_eq!(running_threads2 as int, 2);
+
+            port2.recv();
+            chan.send(());
+        }
+    }
+
+    port.recv();
+}
+
+#[test]
+fn test_simple_newsched_spawn() {
+    use rt::test::run_in_newsched_task;
+
+    do run_in_newsched_task {
+        spawn(||())
+    }
+}
diff --git a/src/libstd/task/rt.rs b/src/libstd/task/rt.rs
new file mode 100644
index 00000000000..760812252bc
--- /dev/null
+++ b/src/libstd/task/rt.rs
@@ -0,0 +1,71 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+The task interface to the runtime
+
+*/
+
+#[doc(hidden)]; // FIXME #3538
+
+use libc;
+
+#[allow(non_camel_case_types)] // runtime type
+pub type sched_id = int;
+#[allow(non_camel_case_types)] // runtime type
+pub type task_id = int;
+
+// These are both opaque runtime/compiler types that we don't know the
+// structure of and should only deal with via unsafe pointer
+#[allow(non_camel_case_types)] // runtime type
+pub type rust_task = libc::c_void;
+#[allow(non_camel_case_types)] // runtime type
+pub type rust_closure = libc::c_void;
+
+pub extern {
+    #[rust_stack]
+    fn rust_task_yield(task: *rust_task) -> bool;
+
+    fn rust_get_sched_id() -> sched_id;
+    fn rust_new_sched(num_threads: libc::uintptr_t) -> sched_id;
+    fn rust_sched_threads() -> libc::size_t;
+    fn rust_sched_current_nonlazy_threads() -> libc::size_t;
+    fn rust_num_threads() -> libc::uintptr_t;
+
+    fn get_task_id() -> task_id;
+    #[rust_stack]
+    fn rust_get_task() -> *rust_task;
+
+    fn new_task() -> *rust_task;
+    fn rust_new_task_in_sched(id: sched_id) -> *rust_task;
+
+    fn start_task(task: *rust_task, closure: *rust_closure);
+
+    fn rust_task_is_unwinding(task: *rust_task) -> bool;
+    fn rust_osmain_sched_id() -> sched_id;
+    #[rust_stack]
+    fn rust_task_inhibit_kill(t: *rust_task);
+    #[rust_stack]
+    fn rust_task_allow_kill(t: *rust_task);
+    #[rust_stack]
+    fn rust_task_inhibit_yield(t: *rust_task);
+    #[rust_stack]
+    fn rust_task_allow_yield(t: *rust_task);
+    fn rust_task_kill_other(task: *rust_task);
+    fn rust_task_kill_all(task: *rust_task);
+
+    #[rust_stack]
+    fn rust_get_task_local_data(task: *rust_task) -> *libc::c_void;
+    #[rust_stack]
+    fn rust_set_task_local_data(task: *rust_task, map: *libc::c_void);
+    #[rust_stack]
+    fn rust_task_local_data_atexit(task: *rust_task, cleanup_fn: *u8);
+}
diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs
new file mode 100644
index 00000000000..81e5af5caab
--- /dev/null
+++ b/src/libstd/task/spawn.rs
@@ -0,0 +1,791 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!**************************************************************************
+ * Spawning & linked failure
+ *
+ * Several data structures are involved in task management to allow properly
+ * propagating failure across linked/supervised tasks.
+ *
+ * (1) The "taskgroup_arc" is an unsafe::exclusive which contains a hashset of
+ *     all tasks that are part of the group. Some tasks are 'members', which
+ *     means if they fail, they will kill everybody else in the taskgroup.
+ *     Other tasks are 'descendants', which means they will not kill tasks
+ *     from this group, but can be killed by failing members.
+ *
+ *     A new one of these is created each spawn_linked or spawn_supervised.
+ *
+ * (2) The "tcb" is a per-task control structure that tracks a task's spawn
+ *     configuration. It contains a reference to its taskgroup_arc, a
+ *     reference to its node in the ancestor list (below), a flag for
+ *     whether it's part of the 'main'/'root' taskgroup, and an optionally
+ *     configured notification port. These are stored in TLS.
+ *
+ * (3) The "ancestor_list" is a cons-style list of unsafe::exclusives which
+ *     tracks 'generations' of taskgroups -- a group's ancestors are groups
+ *     which (directly or transitively) spawn_supervised-ed them. Each task
+ *     is recorded in the 'descendants' of each of its ancestor groups.
+ *
+ *     Spawning a supervised task is O(n) in the number of generations still
+ *     alive, and exiting (by success or failure) that task is also O(n).
+ *
+ * This diagram depicts the references between these data structures:
+ *
+ *          linked_________________________________
+ *        ___/                   _________         \___
+ *       /   \                  | group X |        /   \
+ *      (  A  ) - - - - - - - > | {A,B} {}|< - - -(  B  )
+ *       \___/                  |_________|        \___/
+ *      unlinked
+ *         |      __ (nil)
+ *         |      //|                         The following code causes this:
+ *         |__   //   /\         _________
+ *        /   \ //    ||        | group Y |     fn taskA() {
+ *       (  C  )- - - ||- - - > |{C} {D,E}|         spawn(taskB);
+ *        \___/      /  \=====> |_________|         spawn_unlinked(taskC);
+ *      supervise   /gen \                          ...
+ *         |    __  \ 00 /                      }
+ *         |    //|  \__/                       fn taskB() { ... }
+ *         |__ //     /\         _________      fn taskC() {
+ *        /   \/      ||        | group Z |         spawn_supervised(taskD);
+ *       (  D  )- - - ||- - - > | {D} {E} |         ...
+ *        \___/      /  \=====> |_________|     }
+ *      supervise   /gen \                      fn taskD() {
+ *         |    __  \ 01 /                          spawn_supervised(taskE);
+ *         |    //|  \__/                           ...
+ *         |__ //                _________      }
+ *        /   \/                | group W |     fn taskE() { ... }
+ *       (  E  )- - - - - - - > | {E}  {} |
+ *        \___/                 |_________|
+ *
+ *        "tcb"               "taskgroup_arc"
+ *             "ancestor_list"
+ *
+ ****************************************************************************/
+
+#[doc(hidden)]; // FIXME #3538
+
+use cast::transmute;
+use cast;
+use cell::Cell;
+use container::Map;
+use comm::{Chan, GenericChan};
+use prelude::*;
+use ptr;
+use hashmap::HashSet;
+use task::local_data_priv::{local_get, local_set, OldHandle};
+use task::rt::rust_task;
+use task::rt;
+use task::{Failure, ManualThreads, PlatformThread, SchedOpts, SingleThreaded};
+use task::{Success, TaskOpts, TaskResult, ThreadPerCore, ThreadPerTask};
+use task::{ExistingScheduler, SchedulerHandle};
+use task::unkillable;
+use uint;
+use util;
+use unstable::sync::{Exclusive, exclusive};
+use rt::local::Local;
+
+#[cfg(test)] use task::default_task_opts;
+
+macro_rules! move_it (
+    { $x:expr } => ( unsafe { let y = *ptr::to_unsafe_ptr(&($x)); y } )
+)
+
+type TaskSet = HashSet<*rust_task>;
+
+fn new_taskset() -> TaskSet {
+    HashSet::new()
+}
+fn taskset_insert(tasks: &mut TaskSet, task: *rust_task) {
+    let didnt_overwrite = tasks.insert(task);
+    assert!(didnt_overwrite);
+}
+fn taskset_remove(tasks: &mut TaskSet, task: *rust_task) {
+    let was_present = tasks.remove(&task);
+    assert!(was_present);
+}
+pub fn taskset_each(tasks: &TaskSet, blk: &fn(v: *rust_task) -> bool) -> bool {
+    tasks.each(|k| blk(*k))
+}
+
+// One of these per group of linked-failure tasks.
+struct TaskGroupData {
+    // All tasks which might kill this group. When this is empty, the group
+    // can be "GC"ed (i.e., its link in the ancestor list can be removed).
+    members:     TaskSet,
+    // All tasks unidirectionally supervised by (directly or transitively)
+    // tasks in this group.
+    descendants: TaskSet,
+}
+type TaskGroupArc = Exclusive<Option<TaskGroupData>>;
+
+type TaskGroupInner<'self> = &'self mut Option<TaskGroupData>;
+
+// A taskgroup is 'dead' when nothing can cause it to fail; only members can.
+fn taskgroup_is_dead(tg: &TaskGroupData) -> bool {
+    (&const tg.members).is_empty()
+}
+
+// A list-like structure by which taskgroups keep track of all ancestor groups
+// which may kill them. Needed for tasks to be able to remove themselves from
+// ancestor groups upon exit. The list has a node for each "generation", and
+// ends either at the root taskgroup (which has no ancestors) or at a
+// taskgroup which was spawned-unlinked. Tasks from intermediate generations
+// have references to the middle of the list; when intermediate generations
+// die, their node in the list will be collected at a descendant's spawn-time.
+struct AncestorNode {
+    // Since the ancestor list is recursive, we end up with references to
+    // exclusives within other exclusives. This is dangerous business (if
+    // circular references arise, deadlock and memory leaks are imminent).
+    // Hence we assert that this counter monotonically decreases as we
+    // approach the tail of the list.
+    // FIXME(#3068): Make the generation counter togglable with #[cfg(debug)].
+    generation:     uint,
+    // Should really be a non-option. This way appeases borrowck.
+    parent_group:   Option<TaskGroupArc>,
+    // Recursive rest of the list.
+    ancestors:      AncestorList,
+}
+
+struct AncestorList(Option<Exclusive<AncestorNode>>);
+
+// Accessors for taskgroup arcs and ancestor arcs that wrap the unsafety.
+#[inline(always)]
+fn access_group<U>(x: &TaskGroupArc, blk: &fn(TaskGroupInner) -> U) -> U {
+    x.with(blk)
+}
+
+#[inline(always)]
+fn access_ancestors<U>(x: &Exclusive<AncestorNode>,
+                       blk: &fn(x: &mut AncestorNode) -> U) -> U {
+    x.with(blk)
+}
+
+// Iterates over an ancestor list.
+// (1) Runs forward_blk on each ancestral taskgroup in the list
+// (2) If forward_blk "break"s, runs optional bail_blk on all ancestral
+//     taskgroups that forward_blk already ran on successfully (Note: bail_blk
+//     is NOT called on the block that forward_blk broke on!).
+// (3) As a bonus, coalesces away all 'dead' taskgroup nodes in the list.
+// FIXME(#2190): Change Option<@fn(...)> to Option<&fn(...)>, to save on
+// allocations. Once that bug is fixed, changing the sigil should suffice.
+fn each_ancestor(list:        &mut AncestorList,
+                 bail_opt:    Option<@fn(TaskGroupInner)>,
+                 forward_blk: &fn(TaskGroupInner) -> bool)
+              -> bool {
+    // "Kickoff" call - there was no last generation.
+    return !coalesce(list, bail_opt, forward_blk, uint::max_value);
+
+    // Recursively iterates, and coalesces afterwards if needed. Returns
+    // whether or not unwinding is needed (i.e., !successful iteration).
+    fn coalesce(list:            &mut AncestorList,
+                bail_opt:        Option<@fn(TaskGroupInner)>,
+                forward_blk:     &fn(TaskGroupInner) -> bool,
+                last_generation: uint) -> bool {
+        // Need to swap the list out to use it, to appease borrowck.
+        let tmp_list = util::replace(&mut *list, AncestorList(None));
+        let (coalesce_this, early_break) =
+            iterate(&tmp_list, bail_opt, forward_blk, last_generation);
+        // What should our next ancestor end up being?
+        if coalesce_this.is_some() {
+            // Needed coalesce. Our next ancestor becomes our old
+            // ancestor's next ancestor. ("next = old_next->next;")
+            *list = coalesce_this.unwrap();
+        } else {
+            // No coalesce; restore from tmp. ("next = old_next;")
+            *list = tmp_list;
+        }
+        return early_break;
+    }
+
+    // Returns an optional list-to-coalesce and whether unwinding is needed.
+    // Option<ancestor_list>:
+    //     Whether or not the ancestor taskgroup being iterated over is
+    //     dead or not; i.e., it has no more tasks left in it, whether or not
+    //     it has descendants. If dead, the caller shall coalesce it away.
+    // bool:
+    //     True if the supplied block did 'break', here or in any recursive
+    //     calls. If so, must call the unwinder on all previous nodes.
+    fn iterate(ancestors:       &AncestorList,
+               bail_opt:        Option<@fn(TaskGroupInner)>,
+               forward_blk:     &fn(TaskGroupInner) -> bool,
+               last_generation: uint)
+            -> (Option<AncestorList>, bool) {
+        // At each step of iteration, three booleans are at play which govern
+        // how the iteration should behave.
+        // 'nobe_is_dead' - Should the list should be coalesced at this point?
+        //                  Largely unrelated to the other two.
+        // 'need_unwind'  - Should we run the bail_blk at this point? (i.e.,
+        //                  do_continue was false not here, but down the line)
+        // 'do_continue'  - Did the forward_blk succeed at this point? (i.e.,
+        //                  should we recurse? or should our callers unwind?)
+
+        // The map defaults to None, because if ancestors is None, we're at
+        // the end of the list, which doesn't make sense to coalesce.
+        return do (**ancestors).map_default((None,false)) |ancestor_arc| {
+            // NB: Takes a lock! (this ancestor node)
+            do access_ancestors(ancestor_arc) |nobe| {
+                // Check monotonicity
+                assert!(last_generation > nobe.generation);
+                /*##########################################################*
+                 * Step 1: Look at this ancestor group (call iterator block).
+                 *##########################################################*/
+                let mut nobe_is_dead = false;
+                let do_continue =
+                    // NB: Takes a lock! (this ancestor node's parent group)
+                    do with_parent_tg(&mut nobe.parent_group) |tg_opt| {
+                        // Decide whether this group is dead. Note that the
+                        // group being *dead* is disjoint from it *failing*.
+                        nobe_is_dead = match *tg_opt {
+                            Some(ref tg) => taskgroup_is_dead(tg),
+                            None => nobe_is_dead
+                        };
+                        // Call iterator block. (If the group is dead, it's
+                        // safe to skip it. This will leave our *rust_task
+                        // hanging around in the group even after it's freed,
+                        // but that's ok because, by virtue of the group being
+                        // dead, nobody will ever kill-all (foreach) over it.)
+                        if nobe_is_dead { true } else { forward_blk(tg_opt) }
+                    };
+                /*##########################################################*
+                 * Step 2: Recurse on the rest of the list; maybe coalescing.
+                 *##########################################################*/
+                // 'need_unwind' is only set if blk returned true above, *and*
+                // the recursive call early-broke.
+                let mut need_unwind = false;
+                if do_continue {
+                    // NB: Takes many locks! (ancestor nodes & parent groups)
+                    need_unwind = coalesce(&mut nobe.ancestors, bail_opt,
+                                           forward_blk, nobe.generation);
+                }
+                /*##########################################################*
+                 * Step 3: Maybe unwind; compute return info for our caller.
+                 *##########################################################*/
+                if need_unwind && !nobe_is_dead {
+                    for bail_opt.each |bail_blk| {
+                        do with_parent_tg(&mut nobe.parent_group) |tg_opt| {
+                            (*bail_blk)(tg_opt)
+                        }
+                    }
+                }
+                // Decide whether our caller should unwind.
+                need_unwind = need_unwind || !do_continue;
+                // Tell caller whether or not to coalesce and/or unwind
+                if nobe_is_dead {
+                    // Swap the list out here; the caller replaces us with it.
+                    let rest = util::replace(&mut nobe.ancestors,
+                                             AncestorList(None));
+                    (Some(rest), need_unwind)
+                } else {
+                    (None, need_unwind)
+                }
+            }
+        };
+
+        // Wrapper around exclusive::with that appeases borrowck.
+        fn with_parent_tg<U>(parent_group: &mut Option<TaskGroupArc>,
+                             blk: &fn(TaskGroupInner) -> U) -> U {
+            // If this trips, more likely the problem is 'blk' failed inside.
+            let tmp_arc = parent_group.swap_unwrap();
+            let result = do access_group(&tmp_arc) |tg_opt| { blk(tg_opt) };
+            *parent_group = Some(tmp_arc);
+            result
+        }
+    }
+}
+
+// One of these per task.
+struct TCB {
+    me:         *rust_task,
+    // List of tasks with whose fates this one's is intertwined.
+    tasks:      TaskGroupArc, // 'none' means the group has failed.
+    // Lists of tasks who will kill us if they fail, but whom we won't kill.
+    ancestors:  AncestorList,
+    is_main:    bool,
+    notifier:   Option<AutoNotify>,
+}
+
+impl Drop for TCB {
+    // Runs on task exit.
+    fn finalize(&self) {
+        unsafe {
+            let this: &mut TCB = transmute(self);
+
+            // If we are failing, the whole taskgroup needs to die.
+            if rt::rust_task_is_unwinding(self.me) {
+                for this.notifier.each_mut |x| {
+                    x.failed = true;
+                }
+                // Take everybody down with us.
+                do access_group(&self.tasks) |tg| {
+                    kill_taskgroup(tg, self.me, self.is_main);
+                }
+            } else {
+                // Remove ourselves from the group(s).
+                do access_group(&self.tasks) |tg| {
+                    leave_taskgroup(tg, self.me, true);
+                }
+            }
+            // It doesn't matter whether this happens before or after dealing
+            // with our own taskgroup, so long as both happen before we die.
+            // We remove ourself from every ancestor we can, so no cleanup; no
+            // break.
+            for each_ancestor(&mut this.ancestors, None) |ancestor_group| {
+                leave_taskgroup(ancestor_group, self.me, false);
+            };
+        }
+    }
+}
+
+fn TCB(me: *rust_task,
+       tasks: TaskGroupArc,
+       ancestors: AncestorList,
+       is_main: bool,
+       mut notifier: Option<AutoNotify>) -> TCB {
+    for notifier.each_mut |x| {
+        x.failed = false;
+    }
+
+    TCB {
+        me: me,
+        tasks: tasks,
+        ancestors: ancestors,
+        is_main: is_main,
+        notifier: notifier
+    }
+}
+
+struct AutoNotify {
+    notify_chan: Chan<TaskResult>,
+    failed: bool,
+}
+
+impl Drop for AutoNotify {
+    fn finalize(&self) {
+        let result = if self.failed { Failure } else { Success };
+        self.notify_chan.send(result);
+    }
+}
+
+fn AutoNotify(chan: Chan<TaskResult>) -> AutoNotify {
+    AutoNotify {
+        notify_chan: chan,
+        failed: true // Un-set above when taskgroup successfully made.
+    }
+}
+
+fn enlist_in_taskgroup(state: TaskGroupInner, me: *rust_task,
+                           is_member: bool) -> bool {
+    let newstate = util::replace(&mut *state, None);
+    // If 'None', the group was failing. Can't enlist.
+    if newstate.is_some() {
+        let mut group = newstate.unwrap();
+        taskset_insert(if is_member {
+            &mut group.members
+        } else {
+            &mut group.descendants
+        }, me);
+        *state = Some(group);
+        true
+    } else {
+        false
+    }
+}
+
+// NB: Runs in destructor/post-exit context. Can't 'fail'.
+fn leave_taskgroup(state: TaskGroupInner, me: *rust_task,
+                       is_member: bool) {
+    let newstate = util::replace(&mut *state, None);
+    // If 'None', already failing and we've already gotten a kill signal.
+    if newstate.is_some() {
+        let mut group = newstate.unwrap();
+        taskset_remove(if is_member {
+            &mut group.members
+        } else {
+            &mut group.descendants
+        }, me);
+        *state = Some(group);
+    }
+}
+
+// NB: Runs in destructor/post-exit context. Can't 'fail'.
+fn kill_taskgroup(state: TaskGroupInner, me: *rust_task, is_main: bool) {
+    unsafe {
+        // NB: We could do the killing iteration outside of the group arc, by
+        // having "let mut newstate" here, swapping inside, and iterating
+        // after. But that would let other exiting tasks fall-through and exit
+        // while we were trying to kill them, causing potential
+        // use-after-free. A task's presence in the arc guarantees it's alive
+        // only while we hold the lock, so if we're failing, all concurrently
+        // exiting tasks must wait for us. To do it differently, we'd have to
+        // use the runtime's task refcounting, but that could leave task
+        // structs around long after their task exited.
+        let newstate = util::replace(state, None);
+        // Might already be None, if Somebody is failing simultaneously.
+        // That's ok; only one task needs to do the dirty work. (Might also
+        // see 'None' if Somebody already failed and we got a kill signal.)
+        if newstate.is_some() {
+            let group = newstate.unwrap();
+            for taskset_each(&group.members) |sibling| {
+                // Skip self - killing ourself won't do much good.
+                if sibling != me {
+                    rt::rust_task_kill_other(sibling);
+                }
+            }
+            for taskset_each(&group.descendants) |child| {
+                assert!(child != me);
+                rt::rust_task_kill_other(child);
+            }
+            // Only one task should ever do this.
+            if is_main {
+                rt::rust_task_kill_all(me);
+            }
+            // Do NOT restore state to Some(..)! It stays None to indicate
+            // that the whole taskgroup is failing, to forbid new spawns.
+        }
+        // (note: multiple tasks may reach this point)
+    }
+}
+
+// FIXME (#2912): Work around core-vs-coretest function duplication. Can't use
+// a proper closure because the #[test]s won't understand. Have to fake it.
+macro_rules! taskgroup_key (
+    // Use a "code pointer" value that will never be a real code pointer.
+    () => (cast::transmute((-2 as uint, 0u)))
+)
+
+fn gen_child_taskgroup(linked: bool, supervised: bool)
+    -> (TaskGroupArc, AncestorList, bool) {
+    unsafe {
+        let spawner = rt::rust_get_task();
+        /*##################################################################*
+         * Step 1. Get spawner's taskgroup info.
+         *##################################################################*/
+        let spawner_group: @@mut TCB =
+            match local_get(OldHandle(spawner), taskgroup_key!()) {
+                None => {
+                    // Main task, doing first spawn ever. Lazily initialise
+                    // here.
+                    let mut members = new_taskset();
+                    taskset_insert(&mut members, spawner);
+                    let tasks = exclusive(Some(TaskGroupData {
+                        members: members,
+                        descendants: new_taskset(),
+                    }));
+                    // Main task/group has no ancestors, no notifier, etc.
+                    let group = @@mut TCB(spawner,
+                                          tasks,
+                                          AncestorList(None),
+                                          true,
+                                          None);
+                    local_set(OldHandle(spawner), taskgroup_key!(), group);
+                    group
+                }
+                Some(group) => group
+            };
+        let spawner_group: &mut TCB = *spawner_group;
+
+        /*##################################################################*
+         * Step 2. Process spawn options for child.
+         *##################################################################*/
+        return if linked {
+            // Child is in the same group as spawner.
+            let g = spawner_group.tasks.clone();
+            // Child's ancestors are spawner's ancestors.
+            let a = share_ancestors(&mut spawner_group.ancestors);
+            // Propagate main-ness.
+            (g, a, spawner_group.is_main)
+        } else {
+            // Child is in a separate group from spawner.
+            let g = exclusive(Some(TaskGroupData {
+                members:     new_taskset(),
+                descendants: new_taskset(),
+            }));
+            let a = if supervised {
+                // Child's ancestors start with the spawner.
+                let old_ancestors =
+                    share_ancestors(&mut spawner_group.ancestors);
+                // FIXME(#3068) - The generation counter is only used for a
+                // debug assertion, but initialising it requires locking a
+                // mutex. Hence it should be enabled only in debug builds.
+                let new_generation =
+                    match *old_ancestors {
+                        Some(ref arc) => {
+                            access_ancestors(arc, |a| a.generation+1)
+                        }
+                        None => 0 // the actual value doesn't really matter.
+                    };
+                assert!(new_generation < uint::max_value);
+                // Build a new node in the ancestor list.
+                AncestorList(Some(exclusive(AncestorNode {
+                    generation: new_generation,
+                    parent_group: Some(spawner_group.tasks.clone()),
+                    ancestors: old_ancestors,
+                })))
+            } else {
+                // Child has no ancestors.
+                AncestorList(None)
+            };
+            (g, a, false)
+        };
+    }
+
+    fn share_ancestors(ancestors: &mut AncestorList) -> AncestorList {
+        // Appease the borrow-checker. Really this wants to be written as:
+        // match ancestors
+        //    Some(ancestor_arc) { ancestor_list(Some(ancestor_arc.clone())) }
+        //    None               { ancestor_list(None) }
+        let tmp = util::replace(&mut **ancestors, None);
+        if tmp.is_some() {
+            let ancestor_arc = tmp.unwrap();
+            let result = ancestor_arc.clone();
+            **ancestors = Some(ancestor_arc);
+            AncestorList(Some(result))
+        } else {
+            AncestorList(None)
+        }
+    }
+}
+
+pub fn spawn_raw(opts: TaskOpts, f: ~fn()) {
+    use rt::*;
+
+    match context() {
+        OldTaskContext => {
+            spawn_raw_oldsched(opts, f)
+        }
+        TaskContext => {
+            spawn_raw_newsched(opts, f)
+        }
+        SchedulerContext => {
+            fail!("can't spawn from scheduler context")
+        }
+        GlobalContext => {
+            fail!("can't spawn from global context")
+        }
+    }
+}
+
+fn spawn_raw_newsched(_opts: TaskOpts, f: ~fn()) {
+    use rt::sched::*;
+
+    let mut sched = Local::take::<Scheduler>();
+    let task = ~Coroutine::new(&mut sched.stack_pool, f);
+    sched.schedule_new_task(task);
+}
+
+fn spawn_raw_oldsched(mut opts: TaskOpts, f: ~fn()) {
+
+    let (child_tg, ancestors, is_main) =
+        gen_child_taskgroup(opts.linked, opts.supervised);
+
+    unsafe {
+        let child_data = Cell((child_tg, ancestors, f));
+        // Being killed with the unsafe task/closure pointers would leak them.
+        do unkillable {
+            // Agh. Get move-mode items into the closure. FIXME (#2829)
+            let (child_tg, ancestors, f) = child_data.take();
+            // Create child task.
+            let new_task = match opts.sched.mode {
+                DefaultScheduler => rt::new_task(),
+                _ => new_task_in_sched(opts.sched)
+            };
+            assert!(!new_task.is_null());
+            // Getting killed after here would leak the task.
+            let notify_chan = if opts.notify_chan.is_none() {
+                None
+            } else {
+                Some(opts.notify_chan.swap_unwrap())
+            };
+
+            let child_wrapper = make_child_wrapper(new_task, child_tg,
+                  ancestors, is_main, notify_chan, f);
+
+            let closure = cast::transmute(&child_wrapper);
+
+            // Getting killed between these two calls would free the child's
+            // closure. (Reordering them wouldn't help - then getting killed
+            // between them would leak.)
+            rt::start_task(new_task, closure);
+            cast::forget(child_wrapper);
+        }
+    }
+
+    // This function returns a closure-wrapper that we pass to the child task.
+    // (1) It sets up the notification channel.
+    // (2) It attempts to enlist in the child's group and all ancestor groups.
+    // (3a) If any of those fails, it leaves all groups, and does nothing.
+    // (3b) Otherwise it builds a task control structure and puts it in TLS,
+    // (4) ...and runs the provided body function.
+    fn make_child_wrapper(child: *rust_task, child_arc: TaskGroupArc,
+                          ancestors: AncestorList, is_main: bool,
+                          notify_chan: Option<Chan<TaskResult>>,
+                          f: ~fn())
+                       -> ~fn() {
+        let child_data = Cell((child_arc, ancestors));
+        let result: ~fn() = || {
+            // Agh. Get move-mode items into the closure. FIXME (#2829)
+            let mut (child_arc, ancestors) = child_data.take();
+            // Child task runs this code.
+
+            // Even if the below code fails to kick the child off, we must
+            // send Something on the notify channel.
+
+            //let mut notifier = None;//notify_chan.map(|c| AutoNotify(c));
+            let notifier = match notify_chan {
+                Some(ref notify_chan_value) => {
+                    let moved_ncv = move_it!(*notify_chan_value);
+                    Some(AutoNotify(moved_ncv))
+                }
+                _ => None
+            };
+
+            if enlist_many(child, &child_arc, &mut ancestors) {
+                let group = @@mut TCB(child,
+                                      child_arc,
+                                      ancestors,
+                                      is_main,
+                                      notifier);
+                unsafe {
+                    local_set(OldHandle(child), taskgroup_key!(), group);
+                }
+
+                // Run the child's body.
+                f();
+
+                // TLS cleanup code will exit the taskgroup.
+            }
+
+            // Run the box annihilator.
+            // FIXME #4428: Crashy.
+            // unsafe { cleanup::annihilate(); }
+        };
+        return result;
+
+        // Set up membership in taskgroup and descendantship in all ancestor
+        // groups. If any enlistment fails, Some task was already failing, so
+        // don't let the child task run, and undo every successful enlistment.
+        fn enlist_many(child: *rust_task, child_arc: &TaskGroupArc,
+                       ancestors: &mut AncestorList) -> bool {
+            // Join this taskgroup.
+            let mut result =
+                do access_group(child_arc) |child_tg| {
+                    enlist_in_taskgroup(child_tg, child, true) // member
+                };
+            if result {
+                // Unwinding function in case any ancestral enlisting fails
+                let bail: @fn(TaskGroupInner) = |tg| {
+                    leave_taskgroup(tg, child, false)
+                };
+                // Attempt to join every ancestor group.
+                result =
+                    each_ancestor(ancestors, Some(bail), |ancestor_tg| {
+                        // Enlist as a descendant, not as an actual member.
+                        // Descendants don't kill ancestor groups on failure.
+                        enlist_in_taskgroup(ancestor_tg, child, false)
+                    });
+                // If any ancestor group fails, need to exit this group too.
+                if !result {
+                    do access_group(child_arc) |child_tg| {
+                        leave_taskgroup(child_tg, child, true); // member
+                    }
+                }
+            }
+            result
+        }
+    }
+
+    fn new_task_in_sched(opts: SchedOpts) -> *rust_task {
+        if opts.foreign_stack_size != None {
+            fail!("foreign_stack_size scheduler option unimplemented");
+        }
+
+        let num_threads = match opts.mode {
+            DefaultScheduler
+            | CurrentScheduler
+            | ExistingScheduler(*)
+            | PlatformThread => 0u, /* Won't be used */
+            SingleThreaded => 1u,
+            ThreadPerCore => unsafe { rt::rust_num_threads() },
+            ThreadPerTask => {
+                fail!("ThreadPerTask scheduling mode unimplemented")
+            }
+            ManualThreads(threads) => {
+                if threads == 0u {
+                    fail!("can not create a scheduler with no threads");
+                }
+                threads
+            }
+        };
+
+        unsafe {
+            let sched_id = match opts.mode {
+                CurrentScheduler => rt::rust_get_sched_id(),
+                ExistingScheduler(SchedulerHandle(id)) => id,
+                PlatformThread => rt::rust_osmain_sched_id(),
+                _ => rt::rust_new_sched(num_threads)
+            };
+            rt::rust_new_task_in_sched(sched_id)
+        }
+    }
+}
+
+#[test]
+fn test_spawn_raw_simple() {
+    let (po, ch) = stream();
+    do spawn_raw(default_task_opts()) {
+        ch.send(());
+    }
+    po.recv();
+}
+
+#[test]
+#[ignore(cfg(windows))]
+fn test_spawn_raw_unsupervise() {
+    let opts = task::TaskOpts {
+        linked: false,
+        notify_chan: None,
+        .. default_task_opts()
+    };
+    do spawn_raw(opts) {
+        fail!();
+    }
+}
+
+#[test]
+#[ignore(cfg(windows))]
+fn test_spawn_raw_notify_success() {
+    let (notify_po, notify_ch) = comm::stream();
+
+    let opts = task::TaskOpts {
+        notify_chan: Some(notify_ch),
+        .. default_task_opts()
+    };
+    do spawn_raw(opts) {
+    }
+    assert_eq!(notify_po.recv(), Success);
+}
+
+#[test]
+#[ignore(cfg(windows))]
+fn test_spawn_raw_notify_failure() {
+    // New bindings for these
+    let (notify_po, notify_ch) = comm::stream();
+
+    let opts = task::TaskOpts {
+        linked: false,
+        notify_chan: Some(notify_ch),
+        .. default_task_opts()
+    };
+    do spawn_raw(opts) {
+        fail!();
+    }
+    assert_eq!(notify_po.recv(), Failure);
+}
diff --git a/src/libstd/task_pool.rs b/src/libstd/task_pool.rs
deleted file mode 100644
index 0c52e1ff80e..00000000000
--- a/src/libstd/task_pool.rs
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/// A task pool abstraction. Useful for achieving predictable CPU
-/// parallelism.
-
-use core::comm::Chan;
-use core::task::SchedMode;
-use core::task;
-use core::vec;
-
-#[cfg(test)] use core::task::SingleThreaded;
-
-enum Msg<T> {
-    Execute(~fn(&T)),
-    Quit
-}
-
-pub struct TaskPool<T> {
-    channels: ~[Chan<Msg<T>>],
-    next_index: uint,
-}
-
-#[unsafe_destructor]
-impl<T> Drop for TaskPool<T> {
-    fn finalize(&self) {
-        for self.channels.each |channel| {
-            channel.send(Quit);
-        }
-    }
-}
-
-pub impl<T> TaskPool<T> {
-    /// Spawns a new task pool with `n_tasks` tasks. If the `sched_mode`
-    /// is None, the tasks run on this scheduler; otherwise, they run on a
-    /// new scheduler with the given mode. The provided `init_fn_factory`
-    /// returns a function which, given the index of the task, should return
-    /// local data to be kept around in that task.
-    fn new(n_tasks: uint,
-           opt_sched_mode: Option<SchedMode>,
-           init_fn_factory: ~fn() -> ~fn(uint) -> T)
-        -> TaskPool<T> {
-        assert!(n_tasks >= 1);
-
-        let channels = do vec::from_fn(n_tasks) |i| {
-            let (port, chan) = comm::stream::<Msg<T>>();
-            let init_fn = init_fn_factory();
-
-            let task_body: ~fn() = || {
-                let local_data = init_fn(i);
-                loop {
-                    match port.recv() {
-                        Execute(f) => f(&local_data),
-                        Quit => break
-                    }
-                }
-            };
-
-            // Start the task.
-            match opt_sched_mode {
-                None => {
-                    // Run on this scheduler.
-                    task::spawn(task_body);
-                }
-                Some(sched_mode) => {
-                    let mut task = task::task();
-                    task.sched_mode(sched_mode);
-                    task.spawn(task_body);
-                }
-            }
-
-            chan
-        };
-
-        return TaskPool { channels: channels, next_index: 0 };
-    }
-
-    /// Executes the function `f` on a task in the pool. The function
-    /// receives a reference to the local data returned by the `init_fn`.
-    fn execute(&mut self, f: ~fn(&T)) {
-        self.channels[self.next_index].send(Execute(f));
-        self.next_index += 1;
-        if self.next_index == self.channels.len() { self.next_index = 0; }
-    }
-}
-
-#[test]
-fn test_task_pool() {
-    let f: ~fn() -> ~fn(uint) -> uint = || {
-        let g: ~fn(uint) -> uint = |i| i;
-        g
-    };
-    let mut pool = TaskPool::new(4, Some(SingleThreaded), f);
-    for 8.times {
-        pool.execute(|i| io::println(fmt!("Hello from thread %u!", *i)));
-    }
-}
diff --git a/src/libstd/tempfile.rs b/src/libstd/tempfile.rs
deleted file mode 100644
index e02a7a33733..00000000000
--- a/src/libstd/tempfile.rs
+++ /dev/null
@@ -1,116 +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.
-
-//! Temporary files and directories
-
-use core::rand::RngUtil;
-
-pub fn mkdtemp(tmpdir: &Path, suffix: &str) -> Option<Path> {
-    let mut r = rand::rng();
-    for 1000.times {
-        let p = tmpdir.push(r.gen_str(16) + suffix);
-        if os::make_dir(&p, 0x1c0) { // 700
-            return Some(p);
-        }
-    }
-    None
-}
-
-#[cfg(test)]
-mod tests {
-    use tempfile::mkdtemp;
-    use tempfile;
-    use core::os;
-
-    #[test]
-    fn test_mkdtemp() {
-        let p = mkdtemp(&Path("."), "foobar").unwrap();
-        os::remove_dir(&p);
-        assert!(str::ends_with(p.to_str(), "foobar"));
-    }
-
-    // Ideally these would be in core::os but then core would need
-    // to depend on std
-    #[test]
-    fn recursive_mkdir_rel() {
-        use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
-        use core::os;
-
-        let root = mkdtemp(&os::tmpdir(), "recursive_mkdir_rel").
-            expect("recursive_mkdir_rel");
-        assert!(do os::change_dir_locked(&root) {
-            let path = Path("frob");
-            debug!("recursive_mkdir_rel: Making: %s in cwd %s [%?]", path.to_str(),
-                   os::getcwd().to_str(),
-                   os::path_exists(&path));
-            assert!(os::mkdir_recursive(&path,  (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
-            assert!(os::path_is_dir(&path));
-            assert!(os::mkdir_recursive(&path,  (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
-            assert!(os::path_is_dir(&path));
-        });
-    }
-
-    #[test]
-    fn recursive_mkdir_dot() {
-        use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
-        use core::os;
-
-        let dot = Path(".");
-        assert!(os::mkdir_recursive(&dot,  (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
-        let dotdot = Path("..");
-        assert!(os::mkdir_recursive(&dotdot,  (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
-    }
-
-    #[test]
-    fn recursive_mkdir_rel_2() {
-        use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
-        use core::os;
-
-        let root = mkdtemp(&os::tmpdir(), "recursive_mkdir_rel_2").
-            expect("recursive_mkdir_rel_2");
-        assert!(do os::change_dir_locked(&root) {
-            let path = Path("./frob/baz");
-            debug!("recursive_mkdir_rel_2: Making: %s in cwd %s [%?]", path.to_str(),
-                   os::getcwd().to_str(), os::path_exists(&path));
-            assert!(os::mkdir_recursive(&path, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
-                assert!(os::path_is_dir(&path));
-            assert!(os::path_is_dir(&path.pop()));
-            let path2 = Path("quux/blat");
-            debug!("recursive_mkdir_rel_2: Making: %s in cwd %s", path2.to_str(),
-                   os::getcwd().to_str());
-            assert!(os::mkdir_recursive(&path2, (S_IRUSR | S_IWUSR | S_IXUSR) as i32));
-                assert!(os::path_is_dir(&path2));
-            assert!(os::path_is_dir(&path2.pop()));
-        });
-    }
-
-    // Ideally this would be in core, but needs mkdtemp
-    #[test]
-    pub fn test_rmdir_recursive_ok() {
-        use core::libc::consts::os::posix88::{S_IRUSR, S_IWUSR, S_IXUSR};
-        use core::os;
-
-        let rwx = (S_IRUSR | S_IWUSR | S_IXUSR) as i32;
-
-        let tmpdir = mkdtemp(&os::tmpdir(), "test").expect("test_rmdir_recursive_ok: \
-                                            couldn't create temp dir");
-        let root = tmpdir.push("foo");
-
-        debug!("making %s", root.to_str());
-        assert!(os::make_dir(&root, rwx));
-        assert!(os::make_dir(&root.push("foo"), rwx));
-        assert!(os::make_dir(&root.push("foo").push("bar"), rwx));
-        assert!(os::make_dir(&root.push("foo").push("bar").push("blat"), rwx));
-        assert!(os::remove_dir_recursive(&root));
-        assert!(!os::path_exists(&root));
-        assert!(!os::path_exists(&root.push("bar")));
-        assert!(!os::path_exists(&root.push("bar").push("blat")));
-    }
-}
diff --git a/src/libstd/term.rs b/src/libstd/term.rs
deleted file mode 100644
index fcac7062210..00000000000
--- a/src/libstd/term.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Simple ANSI color library
-
-use core::io;
-use core::option;
-use core::os;
-
-// FIXME (#2807): Windows support.
-
-pub static color_black: u8 = 0u8;
-pub static color_red: u8 = 1u8;
-pub static color_green: u8 = 2u8;
-pub static color_yellow: u8 = 3u8;
-pub static color_blue: u8 = 4u8;
-pub static color_magenta: u8 = 5u8;
-pub static color_cyan: u8 = 6u8;
-pub static color_light_gray: u8 = 7u8;
-pub static color_light_grey: u8 = 7u8;
-pub static color_dark_gray: u8 = 8u8;
-pub static color_dark_grey: u8 = 8u8;
-pub static color_bright_red: u8 = 9u8;
-pub static color_bright_green: u8 = 10u8;
-pub static color_bright_yellow: u8 = 11u8;
-pub static color_bright_blue: u8 = 12u8;
-pub static color_bright_magenta: u8 = 13u8;
-pub static color_bright_cyan: u8 = 14u8;
-pub static color_bright_white: u8 = 15u8;
-
-pub fn esc(writer: @io::Writer) { writer.write([0x1bu8, '[' as u8]); }
-
-/// Reset the foreground and background colors to default
-pub fn reset(writer: @io::Writer) {
-    esc(writer);
-    writer.write(['0' as u8, 'm' as u8]);
-}
-
-/// Returns true if the terminal supports color
-pub fn color_supported() -> bool {
-    let supported_terms = ~[~"xterm-color", ~"xterm",
-                           ~"screen-bce", ~"xterm-256color"];
-    return match os::getenv("TERM") {
-          option::Some(ref env) => {
-            for supported_terms.each |term| {
-                if *term == *env { return true; }
-            }
-            false
-          }
-          option::None => false
-        };
-}
-
-pub fn set_color(writer: @io::Writer, first_char: u8, color: u8) {
-    assert!((color < 16u8));
-    esc(writer);
-    let mut color = color;
-    if color >= 8u8 { writer.write(['1' as u8, ';' as u8]); color -= 8u8; }
-    writer.write([first_char, ('0' as u8) + color, 'm' as u8]);
-}
-
-/// Set the foreground color
-pub fn fg(writer: @io::Writer, color: u8) {
-    return set_color(writer, '3' as u8, color);
-}
-
-/// Set the background color
-pub fn bg(writer: @io::Writer, color: u8) {
-    return set_color(writer, '4' as u8, color);
-}
diff --git a/src/libstd/test.rs b/src/libstd/test.rs
deleted file mode 100644
index 4046ce83c9d..00000000000
--- a/src/libstd/test.rs
+++ /dev/null
@@ -1,966 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[doc(hidden)];
-
-// Support code for rustc's built in test runner generator. Currently,
-// none of this is meant for users. It is intended to support the
-// simplest interface possible for representing and running tests
-// while providing a base that other test frameworks may build off of.
-
-use getopts;
-use sort;
-use term;
-
-use core::to_str::ToStr;
-use core::comm::{stream, SharedChan};
-
-pub mod rustrt {
-    use core::libc::size_t;
-
-    #[abi = "cdecl"]
-    pub extern {
-        pub unsafe fn rust_sched_threads() -> size_t;
-    }
-}
-
-// The name of a test. By convention this follows the rules for rust
-// paths; i.e. it should be a series of identifiers separated by double
-// colons. This way if some test runner wants to arrange the tests
-// hierarchically it may.
-
-pub enum TestName {
-    StaticTestName(&'static str),
-    DynTestName(~str)
-}
-impl ToStr for TestName {
-    fn to_str(&self) -> ~str {
-        match copy *self {
-            StaticTestName(s) => s.to_str(),
-            DynTestName(s) => s.to_str()
-        }
-    }
-}
-
-// A function that runs a test. If the function returns successfully,
-// the test succeeds; if the function fails then the test fails. We
-// may need to come up with a more clever definition of test in order
-// to support isolation of tests into tasks.
-pub enum TestFn {
-    StaticTestFn(extern fn()),
-    StaticBenchFn(extern fn(&mut BenchHarness)),
-    DynTestFn(~fn()),
-    DynBenchFn(~fn(&mut BenchHarness))
-}
-
-// Structure passed to BenchFns
-pub struct BenchHarness {
-    iterations: u64,
-    ns_start: u64,
-    ns_end: u64,
-    bytes: u64
-}
-
-// The definition of a single test. A test runner will run a list of
-// these.
-pub struct TestDesc {
-    name: TestName,
-    ignore: bool,
-    should_fail: bool
-}
-
-pub struct TestDescAndFn {
-    desc: TestDesc,
-    testfn: TestFn,
-}
-
-// The default console test runner. It accepts the command line
-// arguments and a vector of test_descs.
-pub fn test_main(args: &[~str], tests: ~[TestDescAndFn]) {
-    let opts =
-        match parse_opts(args) {
-          either::Left(o) => o,
-          either::Right(m) => fail!(m)
-        };
-    if !run_tests_console(&opts, tests) { fail!("Some tests failed"); }
-}
-
-// A variant optimized for invocation with a static test vector.
-// This will fail (intentionally) when fed any dynamic tests, because
-// it is copying the static values out into a dynamic vector and cannot
-// copy dynamic values. It is doing this because from this point on
-// a ~[TestDescAndFn] is used in order to effect ownership-transfer
-// semantics into parallel test runners, which in turn requires a ~[]
-// rather than a &[].
-pub fn test_main_static(args: &[~str], tests: &[TestDescAndFn]) {
-    let owned_tests = do tests.map |t| {
-        match t.testfn {
-            StaticTestFn(f) =>
-            TestDescAndFn { testfn: StaticTestFn(f), desc: copy t.desc },
-
-            StaticBenchFn(f) =>
-            TestDescAndFn { testfn: StaticBenchFn(f), desc: copy t.desc },
-
-            _ => {
-                fail!("non-static tests passed to test::test_main_static");
-            }
-        }
-    };
-    test_main(args, owned_tests)
-}
-
-pub struct TestOpts {
-    filter: Option<~str>,
-    run_ignored: bool,
-    run_tests: bool,
-    run_benchmarks: bool,
-    save_results: Option<Path>,
-    compare_results: Option<Path>,
-    logfile: Option<Path>
-}
-
-type OptRes = Either<TestOpts, ~str>;
-
-// Parses command line arguments into test options
-pub fn parse_opts(args: &[~str]) -> OptRes {
-    let args_ = vec::tail(args);
-    let opts = ~[getopts::optflag("ignored"),
-                 getopts::optflag("test"),
-                 getopts::optflag("bench"),
-                 getopts::optopt("save"),
-                 getopts::optopt("diff"),
-                 getopts::optopt("logfile")];
-    let matches =
-        match getopts::getopts(args_, opts) {
-          Ok(m) => m,
-          Err(f) => return either::Right(getopts::fail_str(f))
-        };
-
-    let filter =
-        if matches.free.len() > 0 {
-            option::Some(copy (matches).free[0])
-        } else { option::None };
-
-    let run_ignored = getopts::opt_present(&matches, "ignored");
-
-    let logfile = getopts::opt_maybe_str(&matches, "logfile");
-    let logfile = logfile.map(|s| Path(*s));
-
-    let run_benchmarks = getopts::opt_present(&matches, "bench");
-    let run_tests = ! run_benchmarks ||
-        getopts::opt_present(&matches, "test");
-
-    let save_results = getopts::opt_maybe_str(&matches, "save");
-    let save_results = save_results.map(|s| Path(*s));
-
-    let compare_results = getopts::opt_maybe_str(&matches, "diff");
-    let compare_results = compare_results.map(|s| Path(*s));
-
-    let test_opts = TestOpts {
-        filter: filter,
-        run_ignored: run_ignored,
-        run_tests: run_tests,
-        run_benchmarks: run_benchmarks,
-        save_results: save_results,
-        compare_results: compare_results,
-        logfile: logfile
-    };
-
-    either::Left(test_opts)
-}
-
-#[deriving(Eq)]
-pub struct BenchSamples {
-    ns_iter_samples: ~[f64],
-    mb_s: uint
-}
-
-#[deriving(Eq)]
-pub enum TestResult { TrOk, TrFailed, TrIgnored, TrBench(BenchSamples) }
-
-struct ConsoleTestState {
-    out: @io::Writer,
-    log_out: Option<@io::Writer>,
-    use_color: bool,
-    total: uint,
-    passed: uint,
-    failed: uint,
-    ignored: uint,
-    benchmarked: uint,
-    failures: ~[TestDesc]
-}
-
-// A simple console test runner
-pub fn run_tests_console(opts: &TestOpts,
-                         tests: ~[TestDescAndFn]) -> bool {
-
-    fn callback(event: &TestEvent, st: &mut ConsoleTestState) {
-        debug!("callback(event=%?)", event);
-        match copy *event {
-          TeFiltered(ref filtered_tests) => {
-            st.total = filtered_tests.len();
-            let noun = if st.total != 1 { ~"tests" } else { ~"test" };
-            st.out.write_line(fmt!("\nrunning %u %s", st.total, noun));
-          }
-          TeWait(ref test) => st.out.write_str(
-              fmt!("test %s ... ", test.name.to_str())),
-          TeResult(copy test, result) => {
-            match st.log_out {
-                Some(f) => write_log(f, copy result, &test),
-                None => ()
-            }
-            match result {
-              TrOk => {
-                st.passed += 1;
-                write_ok(st.out, st.use_color);
-                st.out.write_line("");
-              }
-              TrFailed => {
-                st.failed += 1;
-                write_failed(st.out, st.use_color);
-                st.out.write_line("");
-                st.failures.push(test);
-              }
-              TrIgnored => {
-                st.ignored += 1;
-                write_ignored(st.out, st.use_color);
-                st.out.write_line("");
-              }
-              TrBench(bs) => {
-                st.benchmarked += 1u;
-                write_bench(st.out, st.use_color);
-                st.out.write_line(fmt!(": %s",
-                                       fmt_bench_samples(&bs)));
-              }
-            }
-          }
-        }
-    }
-
-    let log_out = match opts.logfile {
-        Some(ref path) => match io::file_writer(path,
-                                                [io::Create,
-                                                 io::Truncate]) {
-          result::Ok(w) => Some(w),
-          result::Err(ref s) => {
-              fail!("can't open output file: %s", *s)
-          }
-        },
-        None => None
-    };
-
-    let st = @mut ConsoleTestState {
-        out: io::stdout(),
-        log_out: log_out,
-        use_color: use_color(),
-        total: 0u,
-        passed: 0u,
-        failed: 0u,
-        ignored: 0u,
-        benchmarked: 0u,
-        failures: ~[]
-    };
-
-    run_tests(opts, tests, |x| callback(&x, st));
-
-    assert!(st.passed + st.failed +
-                 st.ignored + st.benchmarked == st.total);
-    let success = st.failed == 0u;
-
-    if !success {
-        print_failures(st);
-    }
-
-    {
-      let st: &mut ConsoleTestState = st;
-      st.out.write_str(fmt!("\nresult: "));
-      if success {
-          // There's no parallelism at this point so it's safe to use color
-          write_ok(st.out, true);
-      } else {
-          write_failed(st.out, true);
-      }
-      st.out.write_str(fmt!(". %u passed; %u failed; %u ignored\n\n",
-                            st.passed, st.failed, st.ignored));
-    }
-
-    return success;
-
-    fn fmt_bench_samples(bs: &BenchSamples) -> ~str {
-        use stats::Stats;
-        if bs.mb_s != 0 {
-            fmt!("%u ns/iter (+/- %u) = %u MB/s",
-                 bs.ns_iter_samples.median() as uint,
-                 3 * (bs.ns_iter_samples.median_abs_dev() as uint),
-                 bs.mb_s)
-        } else {
-            fmt!("%u ns/iter (+/- %u)",
-                 bs.ns_iter_samples.median() as uint,
-                 3 * (bs.ns_iter_samples.median_abs_dev() as uint))
-        }
-    }
-
-    fn write_log(out: @io::Writer, result: TestResult, test: &TestDesc) {
-        out.write_line(fmt!("%s %s",
-                    match result {
-                        TrOk => ~"ok",
-                        TrFailed => ~"failed",
-                        TrIgnored => ~"ignored",
-                        TrBench(ref bs) => fmt_bench_samples(bs)
-                    }, test.name.to_str()));
-    }
-
-    fn write_ok(out: @io::Writer, use_color: bool) {
-        write_pretty(out, "ok", term::color_green, use_color);
-    }
-
-    fn write_failed(out: @io::Writer, use_color: bool) {
-        write_pretty(out, "FAILED", term::color_red, use_color);
-    }
-
-    fn write_ignored(out: @io::Writer, use_color: bool) {
-        write_pretty(out, "ignored", term::color_yellow, use_color);
-    }
-
-    fn write_bench(out: @io::Writer, use_color: bool) {
-        write_pretty(out, "bench", term::color_cyan, use_color);
-    }
-
-    fn write_pretty(out: @io::Writer,
-                    word: &str,
-                    color: u8,
-                    use_color: bool) {
-        if use_color && term::color_supported() {
-            term::fg(out, color);
-        }
-        out.write_str(word);
-        if use_color && term::color_supported() {
-            term::reset(out);
-        }
-    }
-}
-
-fn print_failures(st: &ConsoleTestState) {
-    st.out.write_line("\nfailures:");
-    let mut failures = ~[];
-    for uint::range(0, vec::uniq_len(&const st.failures)) |i| {
-        let name = copy st.failures[i].name;
-        failures.push(name.to_str());
-    }
-    sort::tim_sort(failures);
-    for failures.each |name| {
-        st.out.write_line(fmt!("    %s", name.to_str()));
-    }
-}
-
-#[test]
-fn should_sort_failures_before_printing_them() {
-    fn dummy() {}
-
-    let s = do io::with_str_writer |wr| {
-        let test_a = TestDesc {
-            name: StaticTestName("a"),
-            ignore: false,
-            should_fail: false
-        };
-
-        let test_b = TestDesc {
-            name: StaticTestName("b"),
-            ignore: false,
-            should_fail: false
-        };
-
-        let st = @ConsoleTestState {
-            out: wr,
-            log_out: option::None,
-            use_color: false,
-            total: 0u,
-            passed: 0u,
-            failed: 0u,
-            ignored: 0u,
-            benchmarked: 0u,
-            failures: ~[test_b, test_a]
-        };
-
-        print_failures(st);
-    };
-
-    let apos = str::find_str(s, ~"a").get();
-    let bpos = str::find_str(s, ~"b").get();
-    assert!(apos < bpos);
-}
-
-fn use_color() -> bool { return get_concurrency() == 1; }
-
-enum TestEvent {
-    TeFiltered(~[TestDesc]),
-    TeWait(TestDesc),
-    TeResult(TestDesc, TestResult),
-}
-
-type MonitorMsg = (TestDesc, TestResult);
-
-fn run_tests(opts: &TestOpts,
-             tests: ~[TestDescAndFn],
-             callback: @fn(e: TestEvent)) {
-
-    let filtered_tests = filter_tests(opts, tests);
-    let filtered_descs = filtered_tests.map(|t| copy t.desc);
-
-    callback(TeFiltered(filtered_descs));
-
-    let (filtered_tests, filtered_benchs) =
-        do vec::partition(filtered_tests) |e| {
-        match e.testfn {
-            StaticTestFn(_) | DynTestFn(_) => true,
-            StaticBenchFn(_) | DynBenchFn(_) => false
-        }
-    };
-
-    // It's tempting to just spawn all the tests at once, but since we have
-    // many tests that run in other processes we would be making a big mess.
-    let concurrency = get_concurrency();
-    debug!("using %u test tasks", concurrency);
-
-    let mut remaining = filtered_tests;
-    vec::reverse(remaining);
-    let mut pending = 0;
-
-    let (p, ch) = stream();
-    let ch = SharedChan::new(ch);
-
-    while pending > 0 || !remaining.is_empty() {
-        while pending < concurrency && !remaining.is_empty() {
-            let test = remaining.pop();
-            if concurrency == 1 {
-                // We are doing one test at a time so we can print the name
-                // of the test before we run it. Useful for debugging tests
-                // that hang forever.
-                callback(TeWait(copy test.desc));
-            }
-            run_test(!opts.run_tests, test, ch.clone());
-            pending += 1;
-        }
-
-        let (desc, result) = p.recv();
-        if concurrency != 1 {
-            callback(TeWait(copy desc));
-        }
-        callback(TeResult(desc, result));
-        pending -= 1;
-    }
-
-    // All benchmarks run at the end, in serial.
-    do vec::consume(filtered_benchs) |_, b| {
-        callback(TeWait(copy b.desc));
-        run_test(!opts.run_benchmarks, b, ch.clone());
-        let (test, result) = p.recv();
-        callback(TeResult(test, result));
-    }
-}
-
-// Windows tends to dislike being overloaded with threads.
-#[cfg(windows)]
-static sched_overcommit : uint = 1;
-
-#[cfg(unix)]
-static sched_overcommit : uint = 4u;
-
-fn get_concurrency() -> uint {
-    unsafe {
-        let threads = rustrt::rust_sched_threads() as uint;
-        if threads == 1 { 1 }
-        else { threads * sched_overcommit }
-    }
-}
-
-#[allow(non_implicitly_copyable_typarams)]
-pub fn filter_tests(
-    opts: &TestOpts,
-    tests: ~[TestDescAndFn]) -> ~[TestDescAndFn]
-{
-    let mut filtered = tests;
-
-    // Remove tests that don't match the test filter
-    filtered = if opts.filter.is_none() {
-        filtered
-    } else {
-        let filter_str =
-            match opts.filter {
-          option::Some(copy f) => f,
-          option::None => ~""
-        };
-
-        fn filter_fn(test: TestDescAndFn, filter_str: &str) ->
-            Option<TestDescAndFn> {
-            if str::contains(test.desc.name.to_str(), filter_str) {
-                return option::Some(test);
-            } else { return option::None; }
-        }
-
-        vec::filter_map(filtered, |x| filter_fn(x, filter_str))
-    };
-
-    // Maybe pull out the ignored test and unignore them
-    filtered = if !opts.run_ignored {
-        filtered
-    } else {
-        fn filter(test: TestDescAndFn) -> Option<TestDescAndFn> {
-            if test.desc.ignore {
-                let TestDescAndFn {desc, testfn} = test;
-                Some(TestDescAndFn {
-                    desc: TestDesc {ignore: false, ..desc},
-                    testfn: testfn
-                })
-            } else {
-                None
-            }
-        };
-        vec::filter_map(filtered, |x| filter(x))
-    };
-
-    // Sort the tests alphabetically
-    fn lteq(t1: &TestDescAndFn, t2: &TestDescAndFn) -> bool {
-        str::le(t1.desc.name.to_str(), t2.desc.name.to_str())
-    }
-    sort::quick_sort(filtered, lteq);
-
-    filtered
-}
-
-struct TestFuture {
-    test: TestDesc,
-    wait: @fn() -> TestResult,
-}
-
-pub fn run_test(force_ignore: bool,
-                test: TestDescAndFn,
-                monitor_ch: SharedChan<MonitorMsg>) {
-
-    let TestDescAndFn {desc, testfn} = test;
-
-    if force_ignore || desc.ignore {
-        monitor_ch.send((desc, TrIgnored));
-        return;
-    }
-
-    fn run_test_inner(desc: TestDesc,
-                      monitor_ch: SharedChan<MonitorMsg>,
-                      testfn: ~fn()) {
-        let testfn_cell = ::core::cell::Cell(testfn);
-        do task::spawn {
-            let mut result_future = None; // task::future_result(builder);
-
-            let mut task = task::task();
-            task.unlinked();
-            task.future_result(|r| { result_future = Some(r) });
-            task.spawn(testfn_cell.take());
-
-            let task_result = result_future.unwrap().recv();
-            let test_result = calc_result(&desc,
-                                          task_result == task::Success);
-            monitor_ch.send((copy desc, test_result));
-        }
-    }
-
-    match testfn {
-        DynBenchFn(benchfn) => {
-            let bs = ::test::bench::benchmark(benchfn);
-            monitor_ch.send((desc, TrBench(bs)));
-            return;
-        }
-        StaticBenchFn(benchfn) => {
-            let bs = ::test::bench::benchmark(benchfn);
-            monitor_ch.send((desc, TrBench(bs)));
-            return;
-        }
-        DynTestFn(f) => run_test_inner(desc, monitor_ch, f),
-        StaticTestFn(f) => run_test_inner(desc, monitor_ch, || f())
-    }
-}
-
-fn calc_result(desc: &TestDesc, task_succeeded: bool) -> TestResult {
-    if task_succeeded {
-        if desc.should_fail { TrFailed }
-        else { TrOk }
-    } else {
-        if desc.should_fail { TrOk }
-        else { TrFailed }
-    }
-}
-
-pub mod bench {
-    use time::precise_time_ns;
-    use test::{BenchHarness, BenchSamples};
-    use stats::Stats;
-    use core::rand::RngUtil;
-
-    pub impl BenchHarness {
-
-        /// Callback for benchmark functions to run in their body.
-        pub fn iter(&mut self, inner:&fn()) {
-            self.ns_start = precise_time_ns();
-            let k = self.iterations;
-            for u64::range(0, k) |_| {
-                inner();
-            }
-            self.ns_end = precise_time_ns();
-        }
-
-        fn ns_elapsed(&mut self) -> u64 {
-            if self.ns_start == 0 || self.ns_end == 0 {
-                0
-            } else {
-                self.ns_end - self.ns_start
-            }
-        }
-
-        fn ns_per_iter(&mut self) -> u64 {
-            if self.iterations == 0 {
-                0
-            } else {
-                self.ns_elapsed() / self.iterations
-            }
-        }
-
-        fn bench_n(&mut self, n: u64, f: &fn(&mut BenchHarness)) {
-            self.iterations = n;
-            debug!("running benchmark for %u iterations",
-                   n as uint);
-            f(self);
-        }
-
-        // This is the Go benchmark algorithm. It produces a single
-        // datapoint and always tries to run for 1s.
-        pub fn go_bench(&mut self, f: &fn(&mut BenchHarness)) {
-
-            // Rounds a number down to the nearest power of 10.
-            fn round_down_10(n: u64) -> u64 {
-                let mut n = n;
-                let mut res = 1;
-                while n > 10 {
-                    n = n / 10;
-                    res *= 10;
-                }
-                res
-            }
-
-            // Rounds x up to a number of the form [1eX, 2eX, 5eX].
-            fn round_up(n: u64) -> u64 {
-                let base = round_down_10(n);
-                if n < (2 * base) {
-                    2 * base
-                } else if n < (5 * base) {
-                    5 * base
-                } else {
-                    10 * base
-                }
-            }
-
-            // Initial bench run to get ballpark figure.
-            let mut n = 1_u64;
-            self.bench_n(n, f);
-
-            while n < 1_000_000_000 &&
-                self.ns_elapsed() < 1_000_000_000 {
-                let last = n;
-
-                // Try to estimate iter count for 1s falling back to 1bn
-                // iterations if first run took < 1ns.
-                if self.ns_per_iter() == 0 {
-                    n = 1_000_000_000;
-                } else {
-                    n = 1_000_000_000 / self.ns_per_iter();
-                }
-
-                n = u64::max(u64::min(n+n/2, 100*last), last+1);
-                n = round_up(n);
-                self.bench_n(n, f);
-            }
-        }
-
-        // This is a more statistics-driven benchmark algorithm.
-        // It stops as quickly as 50ms, so long as the statistical
-        // properties are satisfactory. If those properties are
-        // not met, it may run as long as the Go algorithm.
-        pub fn auto_bench(&mut self, f: &fn(&mut BenchHarness)) -> ~[f64] {
-
-            let mut rng = rand::rng();
-            let mut magnitude = 10;
-            let mut prev_madp = 0.0;
-
-            loop {
-                let n_samples = rng.gen_uint_range(50, 60);
-                let n_iter = rng.gen_uint_range(magnitude,
-                                                magnitude * 2);
-
-                let samples = do vec::from_fn(n_samples) |_| {
-                    self.bench_n(n_iter as u64, f);
-                    self.ns_per_iter() as f64
-                };
-
-                // Eliminate outliers
-                let med = samples.median();
-                let mad = samples.median_abs_dev();
-                let samples = do vec::filter(samples) |f| {
-                    num::abs(*f - med) <= 3.0 * mad
-                };
-
-                debug!("%u samples, median %f, MAD=%f, %u survived filter",
-                       n_samples, med as float, mad as float,
-                       samples.len());
-
-                if samples.len() != 0 {
-                    // If we have _any_ cluster of signal...
-                    let curr_madp = samples.median_abs_dev_pct();
-                    if self.ns_elapsed() > 1_000_000 &&
-                        (curr_madp < 1.0 ||
-                         num::abs(curr_madp - prev_madp) < 0.1) {
-                        return samples;
-                    }
-                    prev_madp = curr_madp;
-
-                    if n_iter > 20_000_000 ||
-                        self.ns_elapsed() > 20_000_000 {
-                        return samples;
-                    }
-                }
-
-                magnitude *= 2;
-            }
-        }
-    }
-
-    pub fn benchmark(f: &fn(&mut BenchHarness)) -> BenchSamples {
-
-        let mut bs = BenchHarness {
-            iterations: 0,
-            ns_start: 0,
-            ns_end: 0,
-            bytes: 0
-        };
-
-        let ns_iter_samples = bs.auto_bench(f);
-
-        let iter_s = 1_000_000_000 / (ns_iter_samples.median() as u64);
-        let mb_s = (bs.bytes * iter_s) / 1_000_000;
-
-        BenchSamples {
-            ns_iter_samples: ns_iter_samples,
-            mb_s: mb_s as uint
-        }
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use test::{TrFailed, TrIgnored, TrOk, filter_tests, parse_opts,
-               TestDesc, TestDescAndFn,
-               StaticTestName, DynTestName, DynTestFn};
-    use test::{TestOpts, run_test};
-
-    use core::either;
-    use core::comm::{stream, SharedChan};
-    use core::option;
-    use core::vec;
-
-    #[test]
-    pub fn do_not_run_ignored_tests() {
-        fn f() { fail!(); }
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: true,
-                should_fail: false
-            },
-            testfn: DynTestFn(|| f()),
-        };
-        let (p, ch) = stream();
-        let ch = SharedChan::new(ch);
-        run_test(false, desc, ch);
-        let (_, res) = p.recv();
-        assert!(res != TrOk);
-    }
-
-    #[test]
-    pub fn ignored_tests_result_in_ignored() {
-        fn f() { }
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: true,
-                should_fail: false
-            },
-            testfn: DynTestFn(|| f()),
-        };
-        let (p, ch) = stream();
-        let ch = SharedChan::new(ch);
-        run_test(false, desc, ch);
-        let (_, res) = p.recv();
-        assert_eq!(res, TrIgnored);
-    }
-
-    #[test]
-    #[ignore(cfg(windows))]
-    fn test_should_fail() {
-        fn f() { fail!(); }
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: false,
-                should_fail: true
-            },
-            testfn: DynTestFn(|| f()),
-        };
-        let (p, ch) = stream();
-        let ch = SharedChan::new(ch);
-        run_test(false, desc, ch);
-        let (_, res) = p.recv();
-        assert_eq!(res, TrOk);
-    }
-
-    #[test]
-    fn test_should_fail_but_succeeds() {
-        fn f() { }
-        let desc = TestDescAndFn {
-            desc: TestDesc {
-                name: StaticTestName("whatever"),
-                ignore: false,
-                should_fail: true
-            },
-            testfn: DynTestFn(|| f()),
-        };
-        let (p, ch) = stream();
-        let ch = SharedChan::new(ch);
-        run_test(false, desc, ch);
-        let (_, res) = p.recv();
-        assert_eq!(res, TrFailed);
-    }
-
-    #[test]
-    fn first_free_arg_should_be_a_filter() {
-        let args = ~[~"progname", ~"filter"];
-        let opts = match parse_opts(args) {
-          either::Left(copy o) => o,
-          _ => fail!("Malformed arg in first_free_arg_should_be_a_filter")
-        };
-        assert!("filter" == (copy opts.filter).get());
-    }
-
-    #[test]
-    fn parse_ignored_flag() {
-        let args = ~[~"progname", ~"filter", ~"--ignored"];
-        let opts = match parse_opts(args) {
-          either::Left(copy o) => o,
-          _ => fail!("Malformed arg in parse_ignored_flag")
-        };
-        assert!((opts.run_ignored));
-    }
-
-    #[test]
-    pub fn filter_for_ignored_option() {
-        fn dummy() {}
-
-        // When we run ignored tests the test filter should filter out all the
-        // unignored tests and flip the ignore flag on the rest to false
-
-        let opts = TestOpts {
-            filter: option::None,
-            run_ignored: true,
-            logfile: option::None,
-            run_tests: true,
-            run_benchmarks: false,
-            save_results: option::None,
-            compare_results: option::None
-        };
-
-        let tests = ~[
-            TestDescAndFn {
-                desc: TestDesc {
-                    name: StaticTestName("1"),
-                    ignore: true,
-                    should_fail: false,
-                },
-                testfn: DynTestFn(|| {}),
-            },
-            TestDescAndFn {
-                desc: TestDesc {
-                    name: StaticTestName("2"),
-                    ignore: false,
-                    should_fail: false
-                },
-                testfn: DynTestFn(|| {}),
-            },
-        ];
-        let filtered = filter_tests(&opts, tests);
-
-        assert_eq!(filtered.len(), 1);
-        assert_eq!(filtered[0].desc.name.to_str(), ~"1");
-        assert!(filtered[0].desc.ignore == false);
-    }
-
-    #[test]
-    pub fn sort_tests() {
-        let opts = TestOpts {
-            filter: option::None,
-            run_ignored: false,
-            logfile: option::None,
-            run_tests: true,
-            run_benchmarks: false,
-            save_results: option::None,
-            compare_results: option::None
-        };
-
-        let names =
-            ~[~"sha1::test", ~"int::test_to_str", ~"int::test_pow",
-             ~"test::do_not_run_ignored_tests",
-             ~"test::ignored_tests_result_in_ignored",
-             ~"test::first_free_arg_should_be_a_filter",
-             ~"test::parse_ignored_flag", ~"test::filter_for_ignored_option",
-             ~"test::sort_tests"];
-        let tests =
-        {
-            fn testfn() { }
-            let mut tests = ~[];
-            for names.each |name| {
-                let test = TestDescAndFn {
-                    desc: TestDesc {
-                        name: DynTestName(copy *name),
-                        ignore: false,
-                        should_fail: false
-                    },
-                    testfn: DynTestFn(copy testfn),
-                };
-                tests.push(test);
-            }
-            tests
-        };
-        let filtered = filter_tests(&opts, tests);
-
-        let expected =
-            ~[~"int::test_pow", ~"int::test_to_str", ~"sha1::test",
-              ~"test::do_not_run_ignored_tests",
-              ~"test::filter_for_ignored_option",
-              ~"test::first_free_arg_should_be_a_filter",
-              ~"test::ignored_tests_result_in_ignored",
-              ~"test::parse_ignored_flag",
-              ~"test::sort_tests"];
-
-        let pairs = vec::zip(expected, filtered);
-
-        for pairs.each |p| {
-            match *p {
-                (ref a, ref b) => {
-                    assert!(*a == b.desc.name.to_str());
-                }
-            }
-        }
-    }
-}
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
deleted file mode 100644
index 565ce2d0dd3..00000000000
--- a/src/libstd/time.rs
+++ /dev/null
@@ -1,1268 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-static NSEC_PER_SEC: i32 = 1_000_000_000_i32;
-
-pub mod rustrt {
-    use super::Tm;
-
-    #[abi = "cdecl"]
-    pub extern {
-        pub unsafe fn get_time(sec: &mut i64, nsec: &mut i32);
-
-        pub unsafe fn precise_time_ns(ns: &mut u64);
-
-        pub unsafe fn rust_tzset();
-        // FIXME: The i64 values can be passed by-val when #2064 is fixed.
-        pub unsafe fn rust_gmtime(sec: i64, nsec: i32, result: &mut Tm);
-        pub unsafe fn rust_localtime(sec: i64, nsec: i32, result: &mut Tm);
-        pub unsafe fn rust_timegm(tm: &Tm, sec: &mut i64);
-        pub unsafe fn rust_mktime(tm: &Tm, sec: &mut i64);
-    }
-}
-
-/// A record specifying a time value in seconds and nanoseconds.
-#[deriving(Eq, Encodable, Decodable)]
-pub struct Timespec { sec: i64, nsec: i32 }
-
-/*
- * Timespec assumes that pre-epoch Timespecs have negative sec and positive
- * nsec fields. Darwin's and Linux's struct timespec functions handle pre-
- * epoch timestamps using a "two steps back, one step forward" representation,
- * though the man pages do not actually document this. For example, the time
- * -1.2 seconds before the epoch is represented by `Timespec { sec: -2_i64,
- * nsec: 800_000_000_i32 }`.
- */
-pub impl Timespec {
-    fn new(sec: i64, nsec: i32) -> Timespec {
-        assert!(nsec >= 0 && nsec < NSEC_PER_SEC);
-        Timespec { sec: sec, nsec: nsec }
-    }
-}
-
-impl Ord for Timespec {
-    fn lt(&self, other: &Timespec) -> bool {
-        self.sec < other.sec ||
-            (self.sec == other.sec && self.nsec < other.nsec)
-    }
-    fn le(&self, other: &Timespec) -> bool { !other.lt(self) }
-    fn ge(&self, other: &Timespec) -> bool { !self.lt(other) }
-    fn gt(&self, other: &Timespec) -> bool { !self.le(other) }
-}
-
-/**
- * Returns the current time as a `timespec` containing the seconds and
- * nanoseconds since 1970-01-01T00:00:00Z.
- */
-pub fn get_time() -> Timespec {
-    unsafe {
-        let mut sec = 0i64;
-        let mut nsec = 0i32;
-        rustrt::get_time(&mut sec, &mut nsec);
-        return Timespec::new(sec, nsec);
-    }
-}
-
-
-/**
- * Returns the current value of a high-resolution performance counter
- * in nanoseconds since an unspecified epoch.
- */
-pub fn precise_time_ns() -> u64 {
-    unsafe {
-        let mut ns = 0u64;
-        rustrt::precise_time_ns(&mut ns);
-        ns
-    }
-}
-
-
-/**
- * Returns the current value of a high-resolution performance counter
- * in seconds since an unspecified epoch.
- */
-pub fn precise_time_s() -> float {
-    return (precise_time_ns() as float) / 1000000000.;
-}
-
-pub fn tzset() {
-    unsafe {
-        rustrt::rust_tzset();
-    }
-}
-
-#[deriving(Eq, Encodable, Decodable)]
-pub struct Tm {
-    tm_sec: i32, // seconds after the minute ~[0-60]
-    tm_min: i32, // minutes after the hour ~[0-59]
-    tm_hour: i32, // hours after midnight ~[0-23]
-    tm_mday: i32, // days of the month ~[1-31]
-    tm_mon: i32, // months since January ~[0-11]
-    tm_year: i32, // years since 1900
-    tm_wday: i32, // days since Sunday ~[0-6]
-    tm_yday: i32, // days since January 1 ~[0-365]
-    tm_isdst: i32, // Daylight Savings Time flag
-    tm_gmtoff: i32, // offset from UTC in seconds
-    tm_zone: ~str, // timezone abbreviation
-    tm_nsec: i32, // nanoseconds
-}
-
-pub fn empty_tm() -> Tm {
-    Tm {
-        tm_sec: 0_i32,
-        tm_min: 0_i32,
-        tm_hour: 0_i32,
-        tm_mday: 0_i32,
-        tm_mon: 0_i32,
-        tm_year: 0_i32,
-        tm_wday: 0_i32,
-        tm_yday: 0_i32,
-        tm_isdst: 0_i32,
-        tm_gmtoff: 0_i32,
-        tm_zone: ~"",
-        tm_nsec: 0_i32,
-    }
-}
-
-/// Returns the specified time in UTC
-pub fn at_utc(clock: Timespec) -> Tm {
-    unsafe {
-        let Timespec { sec, nsec } = clock;
-        let mut tm = empty_tm();
-        rustrt::rust_gmtime(sec, nsec, &mut tm);
-        tm
-    }
-}
-
-/// Returns the current time in UTC
-pub fn now_utc() -> Tm {
-    at_utc(get_time())
-}
-
-/// Returns the specified time in the local timezone
-pub fn at(clock: Timespec) -> Tm {
-    unsafe {
-        let Timespec { sec, nsec } = clock;
-        let mut tm = empty_tm();
-        rustrt::rust_localtime(sec, nsec, &mut tm);
-        tm
-    }
-}
-
-/// Returns the current time in the local timezone
-pub fn now() -> Tm {
-    at(get_time())
-}
-
-/// Parses the time from the string according to the format string.
-pub fn strptime(s: &str, format: &str) -> Result<Tm, ~str> {
-    do_strptime(s, format)
-}
-
-/// Formats the time according to the format string.
-pub fn strftime(format: &str, tm: &Tm) -> ~str {
-    do_strftime(format, tm)
-}
-
-pub impl Tm {
-    /// Convert time to the seconds from January 1, 1970
-    fn to_timespec(&self) -> Timespec {
-        unsafe {
-            let mut sec = 0i64;
-            if self.tm_gmtoff == 0_i32 {
-                rustrt::rust_timegm(self, &mut sec);
-            } else {
-                rustrt::rust_mktime(self, &mut sec);
-            }
-            Timespec::new(sec, self.tm_nsec)
-        }
-    }
-
-    /// Convert time to the local timezone
-    fn to_local(&self) -> Tm {
-        at(self.to_timespec())
-    }
-
-    /// Convert time to the UTC
-    fn to_utc(&self) -> Tm {
-        at_utc(self.to_timespec())
-    }
-
-    /**
-     * Return a string of the current time in the form
-     * "Thu Jan  1 00:00:00 1970".
-     */
-    fn ctime(&self) -> ~str { self.strftime("%c") }
-
-    /// Formats the time according to the format string.
-    fn strftime(&self, format: &str) -> ~str {
-        strftime(format, self)
-    }
-
-    /**
-     * Returns a time string formatted according to RFC 822.
-     *
-     * local: "Thu, 22 Mar 2012 07:53:18 PST"
-     * utc:   "Thu, 22 Mar 2012 14:53:18 UTC"
-     */
-    fn rfc822(&self) -> ~str {
-        if self.tm_gmtoff == 0_i32 {
-            self.strftime("%a, %d %b %Y %T GMT")
-        } else {
-            self.strftime("%a, %d %b %Y %T %Z")
-        }
-    }
-
-    /**
-     * Returns a time string formatted according to RFC 822 with Zulu time.
-     *
-     * local: "Thu, 22 Mar 2012 07:53:18 -0700"
-     * utc:   "Thu, 22 Mar 2012 14:53:18 -0000"
-     */
-    fn rfc822z(&self) -> ~str {
-        self.strftime("%a, %d %b %Y %T %z")
-    }
-
-    /**
-     * Returns a time string formatted according to ISO 8601.
-     *
-     * local: "2012-02-22T07:53:18-07:00"
-     * utc:   "2012-02-22T14:53:18Z"
-     */
-    fn rfc3339(&self) -> ~str {
-        if self.tm_gmtoff == 0_i32 {
-            self.strftime("%Y-%m-%dT%H:%M:%SZ")
-        } else {
-            let s = self.strftime("%Y-%m-%dT%H:%M:%S");
-            let sign = if self.tm_gmtoff > 0_i32 { '+' } else { '-' };
-            let mut m = i32::abs(self.tm_gmtoff) / 60_i32;
-            let h = m / 60_i32;
-            m -= h * 60_i32;
-            s + fmt!("%c%02d:%02d", sign, h as int, m as int)
-        }
-    }
-}
-
-priv fn do_strptime(s: &str, format: &str) -> Result<Tm, ~str> {
-    fn match_str(s: &str, pos: uint, needle: &str) -> bool {
-        let mut i = pos;
-        for str::each(needle) |ch| {
-            if s[i] != ch {
-                return false;
-            }
-            i += 1u;
-        }
-        return true;
-    }
-
-    fn match_strs(ss: &str, pos: uint, strs: &[(~str, i32)])
-      -> Option<(i32, uint)> {
-        let mut i = 0u;
-        let len = strs.len();
-        while i < len {
-            let &(needle, value) = &strs[i];
-
-            if match_str(ss, pos, needle) {
-                return Some((value, pos + str::len(needle)));
-            }
-            i += 1u;
-        }
-
-        None
-    }
-
-    fn match_digits(ss: &str, pos: uint, digits: uint, ws: bool)
-      -> Option<(i32, uint)> {
-        let mut pos = pos;
-        let mut value = 0_i32;
-
-        let mut i = 0u;
-        while i < digits {
-            let range = str::char_range_at(str::to_owned(ss), pos);
-            pos = range.next;
-
-            match range.ch {
-              '0' .. '9' => {
-                value = value * 10_i32 + (range.ch as i32 - '0' as i32);
-              }
-              ' ' if ws => (),
-              _ => return None
-            }
-            i += 1u;
-        }
-
-        Some((value, pos))
-    }
-
-    fn match_digits_in_range(ss: &str, pos: uint, digits: uint, ws: bool,
-                             min: i32, max: i32) -> Option<(i32, uint)> {
-        match match_digits(ss, pos, digits, ws) {
-          Some((val, pos)) if val >= min && val <= max => {
-            Some((val, pos))
-          }
-          _ => None
-        }
-    }
-
-    fn parse_char(s: &str, pos: uint, c: char) -> Result<uint, ~str> {
-        let range = str::char_range_at(s, pos);
-
-        if c == range.ch {
-            Ok(range.next)
-        } else {
-            Err(fmt!("Expected %?, found %?",
-                str::from_char(c),
-                str::from_char(range.ch)))
-        }
-    }
-
-    fn parse_type(s: &str, pos: uint, ch: char, tm: &mut Tm)
-      -> Result<uint, ~str> {
-        match ch {
-          'A' => match match_strs(s, pos, [
-              (~"Sunday", 0_i32),
-              (~"Monday", 1_i32),
-              (~"Tuesday", 2_i32),
-              (~"Wednesday", 3_i32),
-              (~"Thursday", 4_i32),
-              (~"Friday", 5_i32),
-              (~"Saturday", 6_i32)
-          ]) {
-            Some(item) => { let (v, pos) = item; tm.tm_wday = v; Ok(pos) }
-            None => Err(~"Invalid day")
-          },
-          'a' => match match_strs(s, pos, [
-              (~"Sun", 0_i32),
-              (~"Mon", 1_i32),
-              (~"Tue", 2_i32),
-              (~"Wed", 3_i32),
-              (~"Thu", 4_i32),
-              (~"Fri", 5_i32),
-              (~"Sat", 6_i32)
-          ]) {
-            Some(item) => { let (v, pos) = item; tm.tm_wday = v; Ok(pos) }
-            None => Err(~"Invalid day")
-          },
-          'B' => match match_strs(s, pos, [
-              (~"January", 0_i32),
-              (~"February", 1_i32),
-              (~"March", 2_i32),
-              (~"April", 3_i32),
-              (~"May", 4_i32),
-              (~"June", 5_i32),
-              (~"July", 6_i32),
-              (~"August", 7_i32),
-              (~"September", 8_i32),
-              (~"October", 9_i32),
-              (~"November", 10_i32),
-              (~"December", 11_i32)
-          ]) {
-            Some(item) => { let (v, pos) = item; tm.tm_mon = v; Ok(pos) }
-            None => Err(~"Invalid month")
-          },
-          'b' | 'h' => match match_strs(s, pos, [
-              (~"Jan", 0_i32),
-              (~"Feb", 1_i32),
-              (~"Mar", 2_i32),
-              (~"Apr", 3_i32),
-              (~"May", 4_i32),
-              (~"Jun", 5_i32),
-              (~"Jul", 6_i32),
-              (~"Aug", 7_i32),
-              (~"Sep", 8_i32),
-              (~"Oct", 9_i32),
-              (~"Nov", 10_i32),
-              (~"Dec", 11_i32)
-          ]) {
-            Some(item) => { let (v, pos) = item; tm.tm_mon = v; Ok(pos) }
-            None => Err(~"Invalid month")
-          },
-          'C' => match match_digits_in_range(s, pos, 2u, false, 0_i32,
-                                             99_i32) {
-            Some(item) => {
-                let (v, pos) = item;
-                  tm.tm_year += (v * 100_i32) - 1900_i32;
-                  Ok(pos)
-              }
-            None => Err(~"Invalid year")
-          },
-          'c' => {
-            parse_type(s, pos, 'a', &mut *tm)
-                .chain(|pos| parse_char(s, pos, ' '))
-                .chain(|pos| parse_type(s, pos, 'b', &mut *tm))
-                .chain(|pos| parse_char(s, pos, ' '))
-                .chain(|pos| parse_type(s, pos, 'e', &mut *tm))
-                .chain(|pos| parse_char(s, pos, ' '))
-                .chain(|pos| parse_type(s, pos, 'T', &mut *tm))
-                .chain(|pos| parse_char(s, pos, ' '))
-                .chain(|pos| parse_type(s, pos, 'Y', &mut *tm))
-          }
-          'D' | 'x' => {
-            parse_type(s, pos, 'm', &mut *tm)
-                .chain(|pos| parse_char(s, pos, '/'))
-                .chain(|pos| parse_type(s, pos, 'd', &mut *tm))
-                .chain(|pos| parse_char(s, pos, '/'))
-                .chain(|pos| parse_type(s, pos, 'y', &mut *tm))
-          }
-          'd' => match match_digits_in_range(s, pos, 2u, false, 1_i32,
-                                             31_i32) {
-            Some(item) => { let (v, pos) = item; tm.tm_mday = v; Ok(pos) }
-            None => Err(~"Invalid day of the month")
-          },
-          'e' => match match_digits_in_range(s, pos, 2u, true, 1_i32,
-                                             31_i32) {
-            Some(item) => { let (v, pos) = item; tm.tm_mday = v; Ok(pos) }
-            None => Err(~"Invalid day of the month")
-          },
-          'F' => {
-            parse_type(s, pos, 'Y', &mut *tm)
-                .chain(|pos| parse_char(s, pos, '-'))
-                .chain(|pos| parse_type(s, pos, 'm', &mut *tm))
-                .chain(|pos| parse_char(s, pos, '-'))
-                .chain(|pos| parse_type(s, pos, 'd', &mut *tm))
-          }
-          'H' => {
-            match match_digits_in_range(s, pos, 2u, false, 0_i32, 23_i32) {
-              Some(item) => { let (v, pos) = item; tm.tm_hour = v; Ok(pos) }
-              None => Err(~"Invalid hour")
-            }
-          }
-          'I' => {
-            match match_digits_in_range(s, pos, 2u, false, 1_i32, 12_i32) {
-              Some(item) => {
-                  let (v, pos) = item;
-                  tm.tm_hour = if v == 12_i32 { 0_i32 } else { v };
-                  Ok(pos)
-              }
-              None => Err(~"Invalid hour")
-            }
-          }
-          'j' => {
-            match match_digits_in_range(s, pos, 3u, false, 1_i32, 366_i32) {
-              Some(item) => {
-                let (v, pos) = item;
-                tm.tm_yday = v - 1_i32;
-                Ok(pos)
-              }
-              None => Err(~"Invalid day of year")
-            }
-          }
-          'k' => {
-            match match_digits_in_range(s, pos, 2u, true, 0_i32, 23_i32) {
-              Some(item) => { let (v, pos) = item; tm.tm_hour = v; Ok(pos) }
-              None => Err(~"Invalid hour")
-            }
-          }
-          'l' => {
-            match match_digits_in_range(s, pos, 2u, true, 1_i32, 12_i32) {
-              Some(item) => {
-                  let (v, pos) = item;
-                  tm.tm_hour = if v == 12_i32 { 0_i32 } else { v };
-                  Ok(pos)
-              }
-              None => Err(~"Invalid hour")
-            }
-          }
-          'M' => {
-            match match_digits_in_range(s, pos, 2u, false, 0_i32, 59_i32) {
-              Some(item) => { let (v, pos) = item; tm.tm_min = v; Ok(pos) }
-              None => Err(~"Invalid minute")
-            }
-          }
-          'm' => {
-            match match_digits_in_range(s, pos, 2u, false, 1_i32, 12_i32) {
-              Some(item) => {
-                let (v, pos) = item;
-                tm.tm_mon = v - 1_i32;
-                Ok(pos)
-              }
-              None => Err(~"Invalid month")
-            }
-          }
-          'n' => parse_char(s, pos, '\n'),
-          'P' => match match_strs(s, pos,
-                                  [(~"am", 0_i32), (~"pm", 12_i32)]) {
-
-            Some(item) => { let (v, pos) = item; tm.tm_hour += v; Ok(pos) }
-            None => Err(~"Invalid hour")
-          },
-          'p' => match match_strs(s, pos,
-                                  [(~"AM", 0_i32), (~"PM", 12_i32)]) {
-
-            Some(item) => { let (v, pos) = item; tm.tm_hour += v; Ok(pos) }
-            None => Err(~"Invalid hour")
-          },
-          'R' => {
-            parse_type(s, pos, 'H', &mut *tm)
-                .chain(|pos| parse_char(s, pos, ':'))
-                .chain(|pos| parse_type(s, pos, 'M', &mut *tm))
-          }
-          'r' => {
-            parse_type(s, pos, 'I', &mut *tm)
-                .chain(|pos| parse_char(s, pos, ':'))
-                .chain(|pos| parse_type(s, pos, 'M', &mut *tm))
-                .chain(|pos| parse_char(s, pos, ':'))
-                .chain(|pos| parse_type(s, pos, 'S', &mut *tm))
-                .chain(|pos| parse_char(s, pos, ' '))
-                .chain(|pos| parse_type(s, pos, 'p', &mut *tm))
-          }
-          'S' => {
-            match match_digits_in_range(s, pos, 2u, false, 0_i32, 60_i32) {
-              Some(item) => {
-                let (v, pos) = item;
-                tm.tm_sec = v;
-                Ok(pos)
-              }
-              None => Err(~"Invalid second")
-            }
-          }
-          //'s' {}
-          'T' | 'X' => {
-            parse_type(s, pos, 'H', &mut *tm)
-                .chain(|pos| parse_char(s, pos, ':'))
-                .chain(|pos| parse_type(s, pos, 'M', &mut *tm))
-                .chain(|pos| parse_char(s, pos, ':'))
-                .chain(|pos| parse_type(s, pos, 'S', &mut *tm))
-          }
-          't' => parse_char(s, pos, '\t'),
-          'u' => {
-            match match_digits_in_range(s, pos, 1u, false, 1_i32, 7_i32) {
-              Some(item) => {
-                let (v, pos) = item;
-                tm.tm_wday = if v == 7 { 0 } else { v };
-                Ok(pos)
-              }
-              None => Err(~"Invalid day of week")
-            }
-          }
-          'v' => {
-            parse_type(s, pos, 'e', &mut *tm)
-                .chain(|pos|  parse_char(s, pos, '-'))
-                .chain(|pos| parse_type(s, pos, 'b', &mut *tm))
-                .chain(|pos| parse_char(s, pos, '-'))
-                .chain(|pos| parse_type(s, pos, 'Y', &mut *tm))
-          }
-          //'W' {}
-          'w' => {
-            match match_digits_in_range(s, pos, 1u, false, 0_i32, 6_i32) {
-              Some(item) => { let (v, pos) = item; tm.tm_wday = v; Ok(pos) }
-              None => Err(~"Invalid day of week")
-            }
-          }
-          //'X' {}
-          //'x' {}
-          'Y' => {
-            match match_digits(s, pos, 4u, false) {
-              Some(item) => {
-                let (v, pos) = item;
-                tm.tm_year = v - 1900_i32;
-                Ok(pos)
-              }
-              None => Err(~"Invalid year")
-            }
-          }
-          'y' => {
-            match match_digits_in_range(s, pos, 2u, false, 0_i32, 99_i32) {
-              Some(item) => {
-                let (v, pos) = item;
-                tm.tm_year = v;
-                Ok(pos)
-              }
-              None => Err(~"Invalid year")
-            }
-          }
-          'Z' => {
-            if match_str(s, pos, "UTC") || match_str(s, pos, "GMT") {
-                tm.tm_gmtoff = 0_i32;
-                tm.tm_zone = ~"UTC";
-                Ok(pos + 3u)
-            } else {
-                // It's odd, but to maintain compatibility with c's
-                // strptime we ignore the timezone.
-                let mut pos = pos;
-                let len = str::len(s);
-                while pos < len {
-                    let range = str::char_range_at(s, pos);
-                    pos = range.next;
-                    if range.ch == ' ' { break; }
-                }
-
-                Ok(pos)
-            }
-          }
-          'z' => {
-            let range = str::char_range_at(s, pos);
-
-            if range.ch == '+' || range.ch == '-' {
-                match match_digits(s, range.next, 4u, false) {
-                  Some(item) => {
-                    let (v, pos) = item;
-                    if v == 0_i32 {
-                        tm.tm_gmtoff = 0_i32;
-                        tm.tm_zone = ~"UTC";
-                    }
-
-                    Ok(pos)
-                  }
-                  None => Err(~"Invalid zone offset")
-                }
-            } else {
-                Err(~"Invalid zone offset")
-            }
-          }
-          '%' => parse_char(s, pos, '%'),
-          ch => {
-            Err(fmt!("unknown formatting type: %?", str::from_char(ch)))
-          }
-        }
-    }
-
-    do io::with_str_reader(str::to_owned(format)) |rdr| {
-        let mut tm = Tm {
-            tm_sec: 0_i32,
-            tm_min: 0_i32,
-            tm_hour: 0_i32,
-            tm_mday: 0_i32,
-            tm_mon: 0_i32,
-            tm_year: 0_i32,
-            tm_wday: 0_i32,
-            tm_yday: 0_i32,
-            tm_isdst: 0_i32,
-            tm_gmtoff: 0_i32,
-            tm_zone: ~"",
-            tm_nsec: 0_i32,
-        };
-        let mut pos = 0u;
-        let len = str::len(s);
-        let mut result = Err(~"Invalid time");
-
-        while !rdr.eof() && pos < len {
-            let range = str::char_range_at(s, pos);
-            let ch = range.ch;
-            let next = range.next;
-
-            match rdr.read_char() {
-                '%' => {
-                    match parse_type(s, pos, rdr.read_char(), &mut tm) {
-                        Ok(next) => pos = next,
-                        Err(e) => { result = Err(e); break; }
-                    }
-                },
-                c => {
-                    if c != ch { break }
-                    pos = next;
-                }
-            }
-        }
-
-        if pos == len && rdr.eof() {
-            Ok(Tm {
-                tm_sec: tm.tm_sec,
-                tm_min: tm.tm_min,
-                tm_hour: tm.tm_hour,
-                tm_mday: tm.tm_mday,
-                tm_mon: tm.tm_mon,
-                tm_year: tm.tm_year,
-                tm_wday: tm.tm_wday,
-                tm_yday: tm.tm_yday,
-                tm_isdst: tm.tm_isdst,
-                tm_gmtoff: tm.tm_gmtoff,
-                tm_zone: copy tm.tm_zone,
-                tm_nsec: tm.tm_nsec,
-            })
-        } else { result }
-    }
-}
-
-priv fn do_strftime(format: &str, tm: &Tm) -> ~str {
-    fn parse_type(ch: char, tm: &Tm) -> ~str {
-        //FIXME (#2350): Implement missing types.
-      let die = || fmt!("strftime: can't understand this format %c ", ch);
-        match ch {
-          'A' => match tm.tm_wday as int {
-            0 => ~"Sunday",
-            1 => ~"Monday",
-            2 => ~"Tuesday",
-            3 => ~"Wednesday",
-            4 => ~"Thursday",
-            5 => ~"Friday",
-            6 => ~"Saturday",
-            _ => die()
-          },
-         'a' => match tm.tm_wday as int {
-            0 => ~"Sun",
-            1 => ~"Mon",
-            2 => ~"Tue",
-            3 => ~"Wed",
-            4 => ~"Thu",
-            5 => ~"Fri",
-            6 => ~"Sat",
-            _ => die()
-          },
-          'B' => match tm.tm_mon as int {
-            0 => ~"January",
-            1 => ~"February",
-            2 => ~"March",
-            3 => ~"April",
-            4 => ~"May",
-            5 => ~"June",
-            6 => ~"July",
-            7 => ~"August",
-            8 => ~"September",
-            9 => ~"October",
-            10 => ~"November",
-            11 => ~"December",
-            _ => die()
-          },
-          'b' | 'h' => match tm.tm_mon as int {
-            0 => ~"Jan",
-            1 => ~"Feb",
-            2 => ~"Mar",
-            3 => ~"Apr",
-            4 => ~"May",
-            5 => ~"Jun",
-            6 => ~"Jul",
-            7 => ~"Aug",
-            8 => ~"Sep",
-            9 => ~"Oct",
-            10 => ~"Nov",
-            11 => ~"Dec",
-            _  => die()
-          },
-          'C' => fmt!("%02d", (tm.tm_year as int + 1900) / 100),
-          'c' => {
-            fmt!("%s %s %s %s %s",
-                parse_type('a', tm),
-                parse_type('b', tm),
-                parse_type('e', tm),
-                parse_type('T', tm),
-                parse_type('Y', tm))
-          }
-          'D' | 'x' => {
-            fmt!("%s/%s/%s",
-                parse_type('m', tm),
-                parse_type('d', tm),
-                parse_type('y', tm))
-          }
-          'd' => fmt!("%02d", tm.tm_mday as int),
-          'e' => fmt!("%2d", tm.tm_mday as int),
-          'F' => {
-            fmt!("%s-%s-%s",
-                parse_type('Y', tm),
-                parse_type('m', tm),
-                parse_type('d', tm))
-          }
-          //'G' {}
-          //'g' {}
-          'H' => fmt!("%02d", tm.tm_hour as int),
-          'I' => {
-            let mut h = tm.tm_hour as int;
-            if h == 0 { h = 12 }
-            if h > 12 { h -= 12 }
-            fmt!("%02d", h)
-          }
-          'j' => fmt!("%03d", tm.tm_yday as int + 1),
-          'k' => fmt!("%2d", tm.tm_hour as int),
-          'l' => {
-            let mut h = tm.tm_hour as int;
-            if h == 0 { h = 12 }
-            if h > 12 { h -= 12 }
-            fmt!("%2d", h)
-          }
-          'M' => fmt!("%02d", tm.tm_min as int),
-          'm' => fmt!("%02d", tm.tm_mon as int + 1),
-          'n' => ~"\n",
-          'P' => if (tm.tm_hour as int) < 12 { ~"am" } else { ~"pm" },
-          'p' => if (tm.tm_hour as int) < 12 { ~"AM" } else { ~"PM" },
-          'R' => {
-            fmt!("%s:%s",
-                parse_type('H', tm),
-                parse_type('M', tm))
-          }
-          'r' => {
-            fmt!("%s:%s:%s %s",
-                parse_type('I', tm),
-                parse_type('M', tm),
-                parse_type('S', tm),
-                parse_type('p', tm))
-          }
-          'S' => fmt!("%02d", tm.tm_sec as int),
-          's' => fmt!("%d", tm.to_timespec().sec as int),
-          'T' | 'X' => {
-            fmt!("%s:%s:%s",
-                parse_type('H', tm),
-                parse_type('M', tm),
-                parse_type('S', tm))
-          }
-          't' => ~"\t",
-          //'U' {}
-          'u' => {
-            let i = tm.tm_wday as int;
-            int::to_str(if i == 0 { 7 } else { i })
-          }
-          //'V' {}
-          'v' => {
-            fmt!("%s-%s-%s",
-                parse_type('e', tm),
-                parse_type('b', tm),
-                parse_type('Y', tm))
-          }
-          //'W' {}
-          'w' => int::to_str(tm.tm_wday as int),
-          //'X' {}
-          //'x' {}
-          'Y' => int::to_str(tm.tm_year as int + 1900),
-          'y' => fmt!("%02d", (tm.tm_year as int + 1900) % 100),
-          'Z' => copy tm.tm_zone,
-          'z' => {
-            let sign = if tm.tm_gmtoff > 0_i32 { '+' } else { '-' };
-            let mut m = i32::abs(tm.tm_gmtoff) / 60_i32;
-            let h = m / 60_i32;
-            m -= h * 60_i32;
-            fmt!("%c%02d%02d", sign, h as int, m as int)
-          }
-          //'+' {}
-          '%' => ~"%",
-          _   => die()
-        }
-    }
-
-    let mut buf = ~"";
-
-    do io::with_str_reader(str::to_owned(format)) |rdr| {
-        while !rdr.eof() {
-            match rdr.read_char() {
-                '%' => buf += parse_type(rdr.read_char(), tm),
-                ch => str::push_char(&mut buf, ch)
-            }
-        }
-    }
-
-    buf
-}
-
-#[cfg(test)]
-mod tests {
-    use time::*;
-
-    use core::float;
-    use core::os;
-    use core::result;
-    use core::result::{Err, Ok};
-    use core::str;
-
-    fn test_get_time() {
-        static some_recent_date: i64 = 1325376000i64; // 2012-01-01T00:00:00Z
-        static some_future_date: i64 = 1577836800i64; // 2020-01-01T00:00:00Z
-
-        let tv1 = get_time();
-        debug!("tv1=%? sec + %? nsec", tv1.sec as uint, tv1.nsec as uint);
-
-        assert!(tv1.sec > some_recent_date);
-        assert!(tv1.nsec < 1000000000i32);
-
-        let tv2 = get_time();
-        debug!("tv2=%? sec + %? nsec", tv2.sec as uint, tv2.nsec as uint);
-
-        assert!(tv2.sec >= tv1.sec);
-        assert!(tv2.sec < some_future_date);
-        assert!(tv2.nsec < 1000000000i32);
-        if tv2.sec == tv1.sec {
-            assert!(tv2.nsec >= tv1.nsec);
-        }
-    }
-
-    fn test_precise_time() {
-        let s0 = precise_time_s();
-        let ns1 = precise_time_ns();
-
-        debug!("s0=%s sec", float::to_str_digits(s0, 9u));
-        assert!(s0 > 0.);
-        let ns0 = (s0 * 1000000000.) as u64;
-        debug!("ns0=%? ns", ns0);
-
-        debug!("ns1=%? ns", ns0);
-        assert!(ns1 >= ns0);
-
-        let ns2 = precise_time_ns();
-        debug!("ns2=%? ns", ns0);
-        assert!(ns2 >= ns1);
-    }
-
-    fn test_at_utc() {
-        os::setenv(~"TZ", ~"America/Los_Angeles");
-        tzset();
-
-        let time = ::time::Timespec::new(1234567890, 54321);
-        let utc = at_utc(time);
-
-        assert!(utc.tm_sec == 30_i32);
-        assert!(utc.tm_min == 31_i32);
-        assert!(utc.tm_hour == 23_i32);
-        assert!(utc.tm_mday == 13_i32);
-        assert!(utc.tm_mon == 1_i32);
-        assert!(utc.tm_year == 109_i32);
-        assert!(utc.tm_wday == 5_i32);
-        assert!(utc.tm_yday == 43_i32);
-        assert!(utc.tm_isdst == 0_i32);
-        assert!(utc.tm_gmtoff == 0_i32);
-        assert!(utc.tm_zone == ~"UTC");
-        assert!(utc.tm_nsec == 54321_i32);
-    }
-
-    fn test_at() {
-        os::setenv(~"TZ", ~"America/Los_Angeles");
-        tzset();
-
-        let time = ::time::Timespec::new(1234567890, 54321);
-        let local = at(time);
-
-        error!("time_at: %?", local);
-
-        assert!(local.tm_sec == 30_i32);
-        assert!(local.tm_min == 31_i32);
-        assert!(local.tm_hour == 15_i32);
-        assert!(local.tm_mday == 13_i32);
-        assert!(local.tm_mon == 1_i32);
-        assert!(local.tm_year == 109_i32);
-        assert!(local.tm_wday == 5_i32);
-        assert!(local.tm_yday == 43_i32);
-        assert!(local.tm_isdst == 0_i32);
-        assert!(local.tm_gmtoff == -28800_i32);
-
-        // FIXME (#2350): We should probably standardize on the timezone
-        // abbreviation.
-        let zone = &local.tm_zone;
-        assert!(*zone == ~"PST" || *zone == ~"Pacific Standard Time");
-
-        assert!(local.tm_nsec == 54321_i32);
-    }
-
-    fn test_to_timespec() {
-        os::setenv(~"TZ", ~"America/Los_Angeles");
-        tzset();
-
-        let time = ::time::Timespec::new(1234567890, 54321);
-        let utc = at_utc(time);
-
-        assert_eq!(utc.to_timespec(), time);
-        assert_eq!(utc.to_local().to_timespec(), time);
-    }
-
-    fn test_conversions() {
-        os::setenv(~"TZ", ~"America/Los_Angeles");
-        tzset();
-
-        let time = ::time::Timespec::new(1234567890, 54321);
-        let utc = at_utc(time);
-        let local = at(time);
-
-        assert!(local.to_local() == local);
-        assert!(local.to_utc() == utc);
-        assert!(local.to_utc().to_local() == local);
-        assert!(utc.to_utc() == utc);
-        assert!(utc.to_local() == local);
-        assert!(utc.to_local().to_utc() == utc);
-    }
-
-    fn test_strptime() {
-        os::setenv(~"TZ", ~"America/Los_Angeles");
-        tzset();
-
-        match strptime(~"", ~"") {
-          Ok(ref tm) => {
-            assert!(tm.tm_sec == 0_i32);
-            assert!(tm.tm_min == 0_i32);
-            assert!(tm.tm_hour == 0_i32);
-            assert!(tm.tm_mday == 0_i32);
-            assert!(tm.tm_mon == 0_i32);
-            assert!(tm.tm_year == 0_i32);
-            assert!(tm.tm_wday == 0_i32);
-            assert!(tm.tm_isdst == 0_i32);
-            assert!(tm.tm_gmtoff == 0_i32);
-            assert!(tm.tm_zone == ~"");
-            assert!(tm.tm_nsec == 0_i32);
-          }
-          Err(_) => ()
-        }
-
-        let format = ~"%a %b %e %T %Y";
-        assert_eq!(strptime(~"", format), Err(~"Invalid time"));
-        assert!(strptime(~"Fri Feb 13 15:31:30", format)
-            == Err(~"Invalid time"));
-
-        match strptime(~"Fri Feb 13 15:31:30 2009", format) {
-          Err(copy e) => fail!(e),
-          Ok(ref tm) => {
-            assert!(tm.tm_sec == 30_i32);
-            assert!(tm.tm_min == 31_i32);
-            assert!(tm.tm_hour == 15_i32);
-            assert!(tm.tm_mday == 13_i32);
-            assert!(tm.tm_mon == 1_i32);
-            assert!(tm.tm_year == 109_i32);
-            assert!(tm.tm_wday == 5_i32);
-            assert!(tm.tm_yday == 0_i32);
-            assert!(tm.tm_isdst == 0_i32);
-            assert!(tm.tm_gmtoff == 0_i32);
-            assert!(tm.tm_zone == ~"");
-            assert!(tm.tm_nsec == 0_i32);
-          }
-        }
-
-        fn test(s: &str, format: &str) -> bool {
-            match strptime(s, format) {
-              Ok(ref tm) => tm.strftime(format) == str::to_owned(s),
-              Err(copy e) => fail!(e)
-            }
-        }
-
-        for [
-            ~"Sunday",
-            ~"Monday",
-            ~"Tuesday",
-            ~"Wednesday",
-            ~"Thursday",
-            ~"Friday",
-            ~"Saturday"
-        ].each |day| {
-            assert!(test(*day, ~"%A"));
-        }
-
-        for [
-            ~"Sun",
-            ~"Mon",
-            ~"Tue",
-            ~"Wed",
-            ~"Thu",
-            ~"Fri",
-            ~"Sat"
-        ].each |day| {
-            assert!(test(*day, ~"%a"));
-        }
-
-        for [
-            ~"January",
-            ~"February",
-            ~"March",
-            ~"April",
-            ~"May",
-            ~"June",
-            ~"July",
-            ~"August",
-            ~"September",
-            ~"October",
-            ~"November",
-            ~"December"
-        ].each |day| {
-            assert!(test(*day, ~"%B"));
-        }
-
-        for [
-            ~"Jan",
-            ~"Feb",
-            ~"Mar",
-            ~"Apr",
-            ~"May",
-            ~"Jun",
-            ~"Jul",
-            ~"Aug",
-            ~"Sep",
-            ~"Oct",
-            ~"Nov",
-            ~"Dec"
-        ].each |day| {
-            assert!(test(*day, ~"%b"));
-        }
-
-        assert!(test(~"19", ~"%C"));
-        assert!(test(~"Fri Feb 13 23:31:30 2009", ~"%c"));
-        assert!(test(~"02/13/09", ~"%D"));
-        assert!(test(~"03", ~"%d"));
-        assert!(test(~"13", ~"%d"));
-        assert!(test(~" 3", ~"%e"));
-        assert!(test(~"13", ~"%e"));
-        assert!(test(~"2009-02-13", ~"%F"));
-        assert!(test(~"03", ~"%H"));
-        assert!(test(~"13", ~"%H"));
-        assert!(test(~"03", ~"%I")); // FIXME (#2350): flesh out
-        assert!(test(~"11", ~"%I")); // FIXME (#2350): flesh out
-        assert!(test(~"044", ~"%j"));
-        assert!(test(~" 3", ~"%k"));
-        assert!(test(~"13", ~"%k"));
-        assert!(test(~" 1", ~"%l"));
-        assert!(test(~"11", ~"%l"));
-        assert!(test(~"03", ~"%M"));
-        assert!(test(~"13", ~"%M"));
-        assert!(test(~"\n", ~"%n"));
-        assert!(test(~"am", ~"%P"));
-        assert!(test(~"pm", ~"%P"));
-        assert!(test(~"AM", ~"%p"));
-        assert!(test(~"PM", ~"%p"));
-        assert!(test(~"23:31", ~"%R"));
-        assert!(test(~"11:31:30 AM", ~"%r"));
-        assert!(test(~"11:31:30 PM", ~"%r"));
-        assert!(test(~"03", ~"%S"));
-        assert!(test(~"13", ~"%S"));
-        assert!(test(~"15:31:30", ~"%T"));
-        assert!(test(~"\t", ~"%t"));
-        assert!(test(~"1", ~"%u"));
-        assert!(test(~"7", ~"%u"));
-        assert!(test(~"13-Feb-2009", ~"%v"));
-        assert!(test(~"0", ~"%w"));
-        assert!(test(~"6", ~"%w"));
-        assert!(test(~"2009", ~"%Y"));
-        assert!(test(~"09", ~"%y"));
-        assert!(result::unwrap(strptime(~"UTC", ~"%Z")).tm_zone ==
-            ~"UTC");
-        assert!(result::unwrap(strptime(~"PST", ~"%Z")).tm_zone ==
-            ~"");
-        assert!(result::unwrap(strptime(~"-0000", ~"%z")).tm_gmtoff ==
-            0);
-        assert!(result::unwrap(strptime(~"-0800", ~"%z")).tm_gmtoff ==
-            0);
-        assert!(test(~"%", ~"%%"));
-    }
-
-    fn test_ctime() {
-        os::setenv(~"TZ", ~"America/Los_Angeles");
-        tzset();
-
-        let time = ::time::Timespec::new(1234567890, 54321);
-        let utc   = at_utc(time);
-        let local = at(time);
-
-        error!("test_ctime: %? %?", utc.ctime(), local.ctime());
-
-        assert_eq!(utc.ctime(), ~"Fri Feb 13 23:31:30 2009");
-        assert_eq!(local.ctime(), ~"Fri Feb 13 15:31:30 2009");
-    }
-
-    fn test_strftime() {
-        os::setenv(~"TZ", ~"America/Los_Angeles");
-        tzset();
-
-        let time = ::time::Timespec::new(1234567890, 54321);
-        let utc = at_utc(time);
-        let local = at(time);
-
-        assert_eq!(local.strftime(~""), ~"");
-        assert_eq!(local.strftime(~"%A"), ~"Friday");
-        assert_eq!(local.strftime(~"%a"), ~"Fri");
-        assert_eq!(local.strftime(~"%B"), ~"February");
-        assert_eq!(local.strftime(~"%b"), ~"Feb");
-        assert_eq!(local.strftime(~"%C"), ~"20");
-        assert_eq!(local.strftime(~"%c"), ~"Fri Feb 13 15:31:30 2009");
-        assert_eq!(local.strftime(~"%D"), ~"02/13/09");
-        assert_eq!(local.strftime(~"%d"), ~"13");
-        assert_eq!(local.strftime(~"%e"), ~"13");
-        assert_eq!(local.strftime(~"%F"), ~"2009-02-13");
-        // assert!(local.strftime("%G") == "2009");
-        // assert!(local.strftime("%g") == "09");
-        assert_eq!(local.strftime(~"%H"), ~"15");
-        assert_eq!(local.strftime(~"%I"), ~"03");
-        assert_eq!(local.strftime(~"%j"), ~"044");
-        assert_eq!(local.strftime(~"%k"), ~"15");
-        assert_eq!(local.strftime(~"%l"), ~" 3");
-        assert_eq!(local.strftime(~"%M"), ~"31");
-        assert_eq!(local.strftime(~"%m"), ~"02");
-        assert_eq!(local.strftime(~"%n"), ~"\n");
-        assert_eq!(local.strftime(~"%P"), ~"pm");
-        assert_eq!(local.strftime(~"%p"), ~"PM");
-        assert_eq!(local.strftime(~"%R"), ~"15:31");
-        assert_eq!(local.strftime(~"%r"), ~"03:31:30 PM");
-        assert_eq!(local.strftime(~"%S"), ~"30");
-        assert_eq!(local.strftime(~"%s"), ~"1234567890");
-        assert_eq!(local.strftime(~"%T"), ~"15:31:30");
-        assert_eq!(local.strftime(~"%t"), ~"\t");
-        // assert!(local.strftime("%U") == "06");
-        assert_eq!(local.strftime(~"%u"), ~"5");
-        // assert!(local.strftime("%V") == "07");
-        assert_eq!(local.strftime(~"%v"), ~"13-Feb-2009");
-        // assert!(local.strftime("%W") == "06");
-        assert_eq!(local.strftime(~"%w"), ~"5");
-        // handle "%X"
-        // handle "%x"
-        assert_eq!(local.strftime(~"%Y"), ~"2009");
-        assert_eq!(local.strftime(~"%y"), ~"09");
-
-        // FIXME (#2350): We should probably standardize on the timezone
-        // abbreviation.
-        let zone = local.strftime(~"%Z");
-        assert!(zone == ~"PST" || zone == ~"Pacific Standard Time");
-
-        assert_eq!(local.strftime(~"%z"), ~"-0800");
-        assert_eq!(local.strftime(~"%%"), ~"%");
-
-        // FIXME (#2350): We should probably standardize on the timezone
-        // abbreviation.
-        let rfc822 = local.rfc822();
-        let prefix = ~"Fri, 13 Feb 2009 15:31:30 ";
-        assert!(rfc822 == prefix + ~"PST" ||
-                     rfc822 == prefix + ~"Pacific Standard Time");
-
-        assert_eq!(local.ctime(), ~"Fri Feb 13 15:31:30 2009");
-        assert_eq!(local.rfc822z(), ~"Fri, 13 Feb 2009 15:31:30 -0800");
-        assert_eq!(local.rfc3339(), ~"2009-02-13T15:31:30-08:00");
-
-        assert_eq!(utc.ctime(), ~"Fri Feb 13 23:31:30 2009");
-        assert_eq!(utc.rfc822(), ~"Fri, 13 Feb 2009 23:31:30 GMT");
-        assert_eq!(utc.rfc822z(), ~"Fri, 13 Feb 2009 23:31:30 -0000");
-        assert_eq!(utc.rfc3339(), ~"2009-02-13T23:31:30Z");
-    }
-
-    fn test_timespec_eq_ord() {
-        use core::cmp::{eq, ge, gt, le, lt, ne};
-
-        let a = &Timespec::new(-2, 1);
-        let b = &Timespec::new(-1, 2);
-        let c = &Timespec::new(1, 2);
-        let d = &Timespec::new(2, 1);
-        let e = &Timespec::new(2, 1);
-
-        assert!(eq(d, e));
-        assert!(ne(c, e));
-
-        assert!(lt(a, b));
-        assert!(lt(b, c));
-        assert!(lt(c, d));
-
-        assert!(le(a, b));
-        assert!(le(b, c));
-        assert!(le(c, d));
-        assert!(le(d, e));
-        assert!(le(e, d));
-
-        assert!(ge(b, a));
-        assert!(ge(c, b));
-        assert!(ge(d, c));
-        assert!(ge(e, d));
-        assert!(ge(d, e));
-
-        assert!(gt(b, a));
-        assert!(gt(c, b));
-        assert!(gt(d, c));
-    }
-
-    #[test]
-    fn run_tests() {
-        // The tests race on tzset. So instead of having many independent
-        // tests, we will just call the functions now.
-        test_get_time();
-        test_precise_time();
-        test_at_utc();
-        test_at();
-        test_to_timespec();
-        test_conversions();
-        test_strptime();
-        test_ctime();
-        test_strftime();
-        test_timespec_eq_ord();
-    }
-}
diff --git a/src/libstd/timer.rs b/src/libstd/timer.rs
deleted file mode 100644
index 092c718f1ce..00000000000
--- a/src/libstd/timer.rs
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Utilities that leverage libuv's `uv_timer_*` API
-
-use uv;
-use uv::iotask;
-use uv::iotask::IoTask;
-
-use core::cast::transmute;
-use core::cast;
-use core::comm::{stream, Chan, SharedChan, Port, select2i};
-use core::libc::c_void;
-use core::libc;
-
-/**
- * Wait for timeout period then send provided value over a channel
- *
- * This call returns immediately. Useful as the building block for a number
- * of higher-level timer functions.
- *
- * Is not guaranteed to wait for exactly the specified time, but will wait
- * for *at least* that period of time.
- *
- * # Arguments
- *
- * * `hl_loop` - a `uv::hl::high_level_loop` that the tcp request will run on
- * * msecs - a timeout period, in milliseconds, to wait
- * * ch - a channel of type T to send a `val` on
- * * val - a value of type T to send over the provided `ch`
- */
-pub fn delayed_send<T:Owned>(iotask: &IoTask,
-                              msecs: uint,
-                              ch: &Chan<T>,
-                              val: T) {
-    let (timer_done_po, timer_done_ch) = stream::<()>();
-    let timer_done_ch = SharedChan::new(timer_done_ch);
-    let timer = uv::ll::timer_t();
-    let timer_ptr: *uv::ll::uv_timer_t = &timer;
-    do iotask::interact(iotask) |loop_ptr| {
-        unsafe {
-            let init_result = uv::ll::timer_init(loop_ptr, timer_ptr);
-            if (init_result == 0i32) {
-                let start_result = uv::ll::timer_start(
-                    timer_ptr, delayed_send_cb, msecs, 0u);
-                if (start_result == 0i32) {
-                    // Note: putting the channel into a ~
-                    // to cast to *c_void
-                    let timer_done_ch_clone = ~timer_done_ch.clone();
-                    let timer_done_ch_ptr = transmute::<
-                        ~SharedChan<()>, *c_void>(
-                        timer_done_ch_clone);
-                    uv::ll::set_data_for_uv_handle(
-                        timer_ptr,
-                        timer_done_ch_ptr);
-                } else {
-                    let error_msg = uv::ll::get_last_err_info(
-                        loop_ptr);
-                    fail!("timer::delayed_send() start failed: %s", error_msg);
-                }
-            } else {
-                let error_msg = uv::ll::get_last_err_info(loop_ptr);
-                fail!("timer::delayed_send() init failed: %s", error_msg);
-            }
-        }
-    };
-    // delayed_send_cb has been processed by libuv
-    timer_done_po.recv();
-    // notify the caller immediately
-    ch.send(val);
-    // uv_close for this timer has been processed
-    timer_done_po.recv();
-}
-
-/**
- * Blocks the current task for (at least) the specified time period.
- *
- * Is not guaranteed to sleep for exactly the specified time, but will sleep
- * for *at least* that period of time.
- *
- * # Arguments
- *
- * * `iotask` - a `uv::iotask` that the tcp request will run on
- * * msecs - an amount of time, in milliseconds, for the current task to block
- */
-pub fn sleep(iotask: &IoTask, msecs: uint) {
-    let (exit_po, exit_ch) = stream::<()>();
-    delayed_send(iotask, msecs, &exit_ch, ());
-    exit_po.recv();
-}
-
-/**
- * Receive on a port for (up to) a specified time, then return an `Option<T>`
- *
- * This call will block to receive on the provided port for up to the
- * specified timeout. Depending on whether the provided port receives in that
- * time period, `recv_timeout` will return an `Option<T>` representing the
- * result.
- *
- * # Arguments
- *
- * * `iotask' - `uv::iotask` that the tcp request will run on
- * * msecs - an mount of time, in milliseconds, to wait to receive
- * * wait_port - a `core::comm::port<T>` to receive on
- *
- * # Returns
- *
- * An `Option<T>` representing the outcome of the call. If the call `recv`'d
- * on the provided port in the allotted timeout period, then the result will
- * be a `Some(T)`. If not, then `None` will be returned.
- */
-pub fn recv_timeout<T:Copy + Owned>(iotask: &IoTask,
-                                   msecs: uint,
-                                   wait_po: &Port<T>)
-                                   -> Option<T> {
-    let mut (timeout_po, timeout_ch) = stream::<()>();
-    delayed_send(iotask, msecs, &timeout_ch, ());
-
-    // XXX: Workaround due to ports and channels not being &mut. They should
-    // be.
-    unsafe {
-        let wait_po = cast::transmute_mut(wait_po);
-
-        // FIXME: This could be written clearer (#2618)
-        either::either(
-            |_| {
-                None
-            }, |_| {
-                Some(wait_po.recv())
-            }, &select2i(&mut timeout_po, wait_po)
-        )
-    }
-}
-
-// INTERNAL API
-extern fn delayed_send_cb(handle: *uv::ll::uv_timer_t, status: libc::c_int) {
-    unsafe {
-        debug!(
-            "delayed_send_cb handle %? status %?", handle, status);
-        // Faking a borrowed pointer to our ~SharedChan
-        let timer_done_ch_ptr: &*c_void = &uv::ll::get_data_for_uv_handle(
-            handle);
-        let timer_done_ch_ptr = transmute::<&*c_void, &~SharedChan<()>>(
-            timer_done_ch_ptr);
-        let stop_result = uv::ll::timer_stop(handle);
-        if (stop_result == 0i32) {
-            timer_done_ch_ptr.send(());
-            uv::ll::close(handle, delayed_send_close_cb);
-        } else {
-            let loop_ptr = uv::ll::get_loop_for_uv_handle(handle);
-            let error_msg = uv::ll::get_last_err_info(loop_ptr);
-            fail!("timer::sleep() init failed: %s", error_msg);
-        }
-    }
-}
-
-extern fn delayed_send_close_cb(handle: *uv::ll::uv_timer_t) {
-    unsafe {
-        debug!("delayed_send_close_cb handle %?", handle);
-        let timer_done_ch_ptr = uv::ll::get_data_for_uv_handle(handle);
-        let timer_done_ch = transmute::<*c_void, ~SharedChan<()>>(
-            timer_done_ch_ptr);
-        timer_done_ch.send(());
-    }
-}
-
-#[cfg(test)]
-mod test {
-    use timer::*;
-    use uv;
-    use core::cell::Cell;
-    use core::rand::RngUtil;
-    use core::pipes::{stream, SharedChan};
-
-    #[test]
-    fn test_gl_timer_simple_sleep_test() {
-        let hl_loop = &uv::global_loop::get();
-        sleep(hl_loop, 1u);
-    }
-
-    #[test]
-    fn test_gl_timer_sleep_stress1() {
-        let hl_loop = &uv::global_loop::get();
-        for 50u.times {
-            sleep(hl_loop, 1u);
-        }
-    }
-
-    #[test]
-    fn test_gl_timer_sleep_stress2() {
-        let (po, ch) = stream();
-        let ch = SharedChan::new(ch);
-        let hl_loop = &uv::global_loop::get();
-
-        let repeat = 20u;
-        let spec = {
-
-            ~[(1u,  20u),
-             (10u, 10u),
-             (20u, 2u)]
-
-        };
-
-        for repeat.times {
-            let ch = ch.clone();
-            for spec.each |spec| {
-                let (times, maxms) = *spec;
-                let ch = ch.clone();
-                let hl_loop_clone = hl_loop.clone();
-                do task::spawn {
-                    use core::rand::*;
-                    let mut rng = rng();
-                    for times.times {
-                        sleep(&hl_loop_clone, rng.next() as uint % maxms);
-                    }
-                    ch.send(());
-                }
-            }
-        }
-
-        for (repeat * spec.len()).times {
-            po.recv()
-        }
-    }
-
-    // Because valgrind serializes multithreaded programs it can
-    // make timing-sensitive tests fail in wierd ways. In these
-    // next test we run them many times and expect them to pass
-    // the majority of tries.
-
-    #[test]
-    #[cfg(ignore)]
-    fn test_gl_timer_recv_timeout_before_time_passes() {
-        let times = 100;
-        let mut successes = 0;
-        let mut failures = 0;
-        let hl_loop = uv::global_loop::get();
-
-        for (times as uint).times {
-            task::yield();
-
-            let expected = rand::rng().gen_str(16u);
-            let (test_po, test_ch) = stream::<~str>();
-
-            do task::spawn() {
-                delayed_send(hl_loop, 1u, &test_ch, expected);
-            };
-
-            match recv_timeout(hl_loop, 10u, &test_po) {
-              Some(val) => {
-                assert_eq!(val, expected);
-                successes += 1;
-              }
-              _ => failures += 1
-            };
-        }
-
-        assert!(successes > times / 2);
-    }
-
-    #[test]
-    fn test_gl_timer_recv_timeout_after_time_passes() {
-        let times = 100;
-        let mut successes = 0;
-        let mut failures = 0;
-        let hl_loop = uv::global_loop::get();
-
-        for (times as uint).times {
-            let mut rng = rand::rng();
-            let expected = Cell(rng.gen_str(16u));
-            let (test_po, test_ch) = stream::<~str>();
-            let hl_loop_clone = hl_loop.clone();
-            do task::spawn() {
-                delayed_send(&hl_loop_clone, 50u, &test_ch, expected.take());
-            };
-
-            match recv_timeout(&hl_loop, 1u, &test_po) {
-              None => successes += 1,
-              _ => failures += 1
-            };
-        }
-
-        assert!(successes > times / 2);
-    }
-}
diff --git a/src/libstd/to_bytes.rs b/src/libstd/to_bytes.rs
new file mode 100644
index 00000000000..5b66e94c1b4
--- /dev/null
+++ b/src/libstd/to_bytes.rs
@@ -0,0 +1,354 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+The `ToBytes` and `IterBytes` traits
+
+*/
+
+use io;
+use io::Writer;
+use option::{None, Option, Some};
+use old_iter::BaseIter;
+use str;
+
+pub type Cb<'self> = &'self fn(buf: &[u8]) -> bool;
+
+/**
+ * A trait to implement in order to make a type hashable;
+ * This works in combination with the trait `Hash::Hash`, and
+ * may in the future be merged with that trait or otherwise
+ * modified when default methods and trait inheritence are
+ * completed.
+ */
+pub trait IterBytes {
+    /**
+     * Call the provided callback `f` one or more times with
+     * byte-slices that should be used when computing a hash
+     * value or otherwise "flattening" the structure into
+     * a sequence of bytes. The `lsb0` parameter conveys
+     * whether the caller is asking for little-endian bytes
+     * (`true`) or big-endian (`false`); this should only be
+     * relevant in implementations that represent a single
+     * multi-byte datum such as a 32 bit integer or 64 bit
+     * floating-point value. It can be safely ignored for
+     * larger structured types as they are usually processed
+     * left-to-right in declaration order, regardless of
+     * underlying memory endianness.
+     */
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool;
+}
+
+impl IterBytes for bool {
+    #[inline(always)]
+    fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool {
+        f([
+            *self as u8
+        ])
+    }
+}
+
+impl IterBytes for u8 {
+    #[inline(always)]
+    fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool {
+        f([
+            *self
+        ])
+    }
+}
+
+impl IterBytes for u16 {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        if lsb0 {
+            f([
+                *self as u8,
+                (*self >> 8) as u8
+            ])
+        } else {
+            f([
+                (*self >> 8) as u8,
+                *self as u8
+            ])
+        }
+    }
+}
+
+impl IterBytes for u32 {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        if lsb0 {
+            f([
+                *self as u8,
+                (*self >> 8) as u8,
+                (*self >> 16) as u8,
+                (*self >> 24) as u8,
+            ])
+        } else {
+            f([
+                (*self >> 24) as u8,
+                (*self >> 16) as u8,
+                (*self >> 8) as u8,
+                *self as u8
+            ])
+        }
+    }
+}
+
+impl IterBytes for u64 {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        if lsb0 {
+            f([
+                *self as u8,
+                (*self >> 8) as u8,
+                (*self >> 16) as u8,
+                (*self >> 24) as u8,
+                (*self >> 32) as u8,
+                (*self >> 40) as u8,
+                (*self >> 48) as u8,
+                (*self >> 56) as u8
+            ])
+        } else {
+            f([
+                (*self >> 56) as u8,
+                (*self >> 48) as u8,
+                (*self >> 40) as u8,
+                (*self >> 32) as u8,
+                (*self >> 24) as u8,
+                (*self >> 16) as u8,
+                (*self >> 8) as u8,
+                *self as u8
+            ])
+        }
+    }
+}
+
+impl IterBytes for i8 {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        (*self as u8).iter_bytes(lsb0, f)
+    }
+}
+
+impl IterBytes for i16 {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        (*self as u16).iter_bytes(lsb0, f)
+    }
+}
+
+impl IterBytes for i32 {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        (*self as u32).iter_bytes(lsb0, f)
+    }
+}
+
+impl IterBytes for i64 {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        (*self as u64).iter_bytes(lsb0, f)
+    }
+}
+
+impl IterBytes for char {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        (*self as u32).iter_bytes(lsb0, f)
+    }
+}
+
+#[cfg(target_word_size = "32")]
+impl IterBytes for uint {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        (*self as u32).iter_bytes(lsb0, f)
+    }
+}
+
+#[cfg(target_word_size = "64")]
+impl IterBytes for uint {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        (*self as u64).iter_bytes(lsb0, f)
+    }
+}
+
+impl IterBytes for int {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        (*self as uint).iter_bytes(lsb0, f)
+    }
+}
+
+impl<'self,A:IterBytes> IterBytes for &'self [A] {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        self.each(|elt| elt.iter_bytes(lsb0, |b| f(b)))
+    }
+}
+
+impl<A:IterBytes,B:IterBytes> IterBytes for (A,B) {
+  #[inline(always)]
+  fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+    match *self {
+      (ref a, ref b) => { a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) }
+    }
+  }
+}
+
+impl<A:IterBytes,B:IterBytes,C:IterBytes> IterBytes for (A,B,C) {
+  #[inline(always)]
+  fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+    match *self {
+      (ref a, ref b, ref c) => {
+        a.iter_bytes(lsb0, f) && b.iter_bytes(lsb0, f) && c.iter_bytes(lsb0, f)
+      }
+    }
+  }
+}
+
+// Move this to vec, probably.
+fn borrow<'x,A>(a: &'x [A]) -> &'x [A] {
+    a
+}
+
+impl<A:IterBytes> IterBytes for ~[A] {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        borrow(*self).iter_bytes(lsb0, f)
+    }
+}
+
+impl<A:IterBytes> IterBytes for @[A] {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        borrow(*self).iter_bytes(lsb0, f)
+    }
+}
+
+// NOTE: remove all of these after a snapshot, the new for-loop iteration
+//       protocol makes these unnecessary.
+
+#[inline(always)]
+pub fn iter_bytes_2<A:IterBytes,B:IterBytes>(a: &A, b: &B,
+                                             lsb0: bool, z: Cb) -> bool {
+    a.iter_bytes(lsb0, z) && b.iter_bytes(lsb0, z)
+}
+
+pub fn iter_bytes_3<A: IterBytes,
+                    B: IterBytes,
+                    C: IterBytes>(a: &A, b: &B, c: &C, lsb0: bool, z: Cb) -> bool {
+    a.iter_bytes(lsb0, z) && b.iter_bytes(lsb0, z) && c.iter_bytes(lsb0, z)
+}
+
+pub fn iter_bytes_4<A: IterBytes,
+                B: IterBytes,
+                C: IterBytes,
+                D: IterBytes>(a: &A, b: &B, c: &C,
+                              d: &D,
+                              lsb0: bool, z: Cb) -> bool {
+    a.iter_bytes(lsb0, z) && b.iter_bytes(lsb0, z) && c.iter_bytes(lsb0, z) &&
+        d.iter_bytes(lsb0, z)
+}
+
+pub fn iter_bytes_5<A: IterBytes,
+                B: IterBytes,
+                C: IterBytes,
+                D: IterBytes,
+                E: IterBytes>(a: &A, b: &B, c: &C,
+                              d: &D, e: &E,
+                              lsb0: bool, z: Cb) -> bool {
+    a.iter_bytes(lsb0, z) && b.iter_bytes(lsb0, z) && c.iter_bytes(lsb0, z) &&
+        d.iter_bytes(lsb0, z) && e.iter_bytes(lsb0, z)
+}
+
+impl<'self> IterBytes for &'self str {
+    #[inline(always)]
+    fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool {
+        do str::byte_slice(*self) |bytes| {
+            f(bytes)
+        }
+    }
+}
+
+impl IterBytes for ~str {
+    #[inline(always)]
+    fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool {
+        do str::byte_slice(*self) |bytes| {
+            f(bytes)
+        }
+    }
+}
+
+impl IterBytes for @str {
+    #[inline(always)]
+    fn iter_bytes(&self, _lsb0: bool, f: Cb) -> bool {
+        do str::byte_slice(*self) |bytes| {
+            f(bytes)
+        }
+    }
+}
+
+impl<A:IterBytes> IterBytes for Option<A> {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        match *self {
+          Some(ref a) => 0u8.iter_bytes(lsb0, f) && a.iter_bytes(lsb0, f),
+          None => 1u8.iter_bytes(lsb0, f)
+        }
+    }
+}
+
+impl<'self,A:IterBytes> IterBytes for &'self A {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        (**self).iter_bytes(lsb0, f)
+    }
+}
+
+impl<A:IterBytes> IterBytes for @A {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        (**self).iter_bytes(lsb0, f)
+    }
+}
+
+impl<A:IterBytes> IterBytes for ~A {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        (**self).iter_bytes(lsb0, f)
+    }
+}
+
+// NB: raw-pointer IterBytes does _not_ dereference
+// to the target; it just gives you the pointer-bytes.
+impl<A> IterBytes for *const A {
+    #[inline(always)]
+    fn iter_bytes(&self, lsb0: bool, f: Cb) -> bool {
+        (*self as uint).iter_bytes(lsb0, f)
+    }
+}
+
+pub trait ToBytes {
+    fn to_bytes(&self, lsb0: bool) -> ~[u8];
+}
+
+impl<A:IterBytes> ToBytes for A {
+    fn to_bytes(&self, lsb0: bool) -> ~[u8] {
+        do io::with_bytes_writer |wr| {
+            for self.iter_bytes(lsb0) |bytes| {
+                wr.write(bytes)
+            }
+        }
+    }
+}
diff --git a/src/libstd/to_str.rs b/src/libstd/to_str.rs
new file mode 100644
index 00000000000..1469471b7ce
--- /dev/null
+++ b/src/libstd/to_str.rs
@@ -0,0 +1,240 @@
+// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+/*!
+
+The `ToStr` trait for converting to strings
+
+*/
+
+use str::OwnedStr;
+use hashmap::HashMap;
+use hashmap::HashSet;
+use container::Map;
+use hash::Hash;
+use cmp::Eq;
+use old_iter::BaseIter;
+
+pub trait ToStr {
+    fn to_str(&self) -> ~str;
+}
+
+/// Trait for converting a type to a string, consuming it in the process.
+pub trait ToStrConsume {
+    // Cosume and convert to a string.
+    fn to_str_consume(self) -> ~str;
+}
+
+impl ToStr for bool {
+    #[inline(always)]
+    fn to_str(&self) -> ~str { ::bool::to_str(*self) }
+}
+impl ToStr for () {
+    #[inline(always)]
+    fn to_str(&self) -> ~str { ~"()" }
+}
+
+impl<A:ToStr> ToStr for (A,) {
+    #[inline(always)]
+    fn to_str(&self) -> ~str {
+        match *self {
+            (ref a,) => {
+                ~"(" + a.to_str() + ~", " + ~")"
+            }
+        }
+    }
+}
+
+impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> {
+    #[inline(always)]
+    fn to_str(&self) -> ~str {
+        let mut acc = ~"{", first = true;
+        for self.each |key, value| {
+            if first {
+                first = false;
+            }
+            else {
+                acc.push_str(", ");
+            }
+            acc.push_str(key.to_str());
+            acc.push_str(": ");
+            acc.push_str(value.to_str());
+        }
+        acc.push_char('}');
+        acc
+    }
+}
+
+impl<A:ToStr+Hash+Eq> ToStr for HashSet<A> {
+    #[inline(always)]
+    fn to_str(&self) -> ~str {
+    let mut acc = ~"{", first = true;
+    for self.each |element| {
+        if first {
+            first = false;
+        }
+        else {
+            acc.push_str(", ");
+        }
+        acc.push_str(element.to_str());
+    }
+    acc.push_char('}');
+    acc
+    }
+}
+
+impl<A:ToStr,B:ToStr> ToStr for (A, B) {
+    #[inline(always)]
+    fn to_str(&self) -> ~str {
+        // FIXME(#4760): this causes an llvm assertion
+        //let &(ref a, ref b) = self;
+        match *self {
+            (ref a, ref b) => {
+                ~"(" + a.to_str() + ~", " + b.to_str() + ~")"
+            }
+        }
+    }
+}
+
+impl<A:ToStr,B:ToStr,C:ToStr> ToStr for (A, B, C) {
+    #[inline(always)]
+    fn to_str(&self) -> ~str {
+        // FIXME(#4760): this causes an llvm assertion
+        //let &(ref a, ref b, ref c) = self;
+        match *self {
+            (ref a, ref b, ref c) => {
+                fmt!("(%s, %s, %s)",
+                    (*a).to_str(),
+                    (*b).to_str(),
+                    (*c).to_str()
+                )
+            }
+        }
+    }
+}
+
+impl<'self,A:ToStr> ToStr for &'self [A] {
+    #[inline(always)]
+    fn to_str(&self) -> ~str {
+        let mut acc = ~"[", first = true;
+        for self.each |elt| {
+            if first {
+                first = false;
+            }
+            else {
+                acc.push_str(", ");
+            }
+            acc.push_str(elt.to_str());
+        }
+        acc.push_char(']');
+        acc
+    }
+}
+
+impl<A:ToStr> ToStr for ~[A] {
+    #[inline(always)]
+    fn to_str(&self) -> ~str {
+        let mut acc = ~"[", first = true;
+        for self.each |elt| {
+            if first {
+                first = false;
+            }
+            else {
+                acc.push_str(", ");
+            }
+            acc.push_str(elt.to_str());
+        }
+        acc.push_char(']');
+        acc
+    }
+}
+
+impl<A:ToStr> ToStr for @[A] {
+    #[inline(always)]
+    fn to_str(&self) -> ~str {
+        let mut acc = ~"[", first = true;
+        for self.each |elt| {
+            if first {
+                first = false;
+            }
+            else {
+                acc.push_str(", ");
+            }
+            acc.push_str(elt.to_str());
+        }
+        acc.push_char(']');
+        acc
+    }
+}
+
+#[cfg(test)]
+#[allow(non_implicitly_copyable_typarams)]
+mod tests {
+    use hashmap::HashMap;
+    use hashmap::HashSet;
+    use container::Set;
+    #[test]
+    fn test_simple_types() {
+        assert_eq!(1i.to_str(), ~"1");
+        assert_eq!((-1i).to_str(), ~"-1");
+        assert_eq!(200u.to_str(), ~"200");
+        assert_eq!(2u8.to_str(), ~"2");
+        assert_eq!(true.to_str(), ~"true");
+        assert_eq!(false.to_str(), ~"false");
+        assert_eq!(().to_str(), ~"()");
+        assert_eq!((~"hi").to_str(), ~"hi");
+        assert_eq!((@"hi").to_str(), ~"hi");
+    }
+
+    #[test]
+    fn test_tuple_types() {
+        assert_eq!((1, 2).to_str(), ~"(1, 2)");
+        assert_eq!((~"a", ~"b", false).to_str(), ~"(a, b, false)");
+        assert_eq!(((), ((), 100)).to_str(), ~"((), ((), 100))");
+    }
+
+    #[test]
+    fn test_vectors() {
+        let x: ~[int] = ~[];
+        assert_eq!(x.to_str(), ~"[]");
+        assert_eq!((~[1]).to_str(), ~"[1]");
+        assert_eq!((~[1, 2, 3]).to_str(), ~"[1, 2, 3]");
+        assert!((~[~[], ~[1], ~[1, 1]]).to_str() ==
+               ~"[[], [1], [1, 1]]");
+    }
+
+    #[test]
+    fn test_hashmap() {
+        let mut table: HashMap<int, int> = HashMap::new();
+        let empty: HashMap<int, int> = HashMap::new();
+
+        table.insert(3, 4);
+        table.insert(1, 2);
+
+        let table_str = table.to_str();
+
+        assert!(table_str == ~"{1: 2, 3: 4}" || table_str == ~"{3: 4, 1: 2}");
+        assert_eq!(empty.to_str(), ~"{}");
+    }
+
+    #[test]
+    fn test_hashset() {
+        let mut set: HashSet<int> = HashSet::new();
+        let empty_set: HashSet<int> = HashSet::new();
+
+        set.insert(1);
+        set.insert(2);
+
+        let set_str = set.to_str();
+
+        assert!(set_str == ~"{1, 2}" || set_str == ~"{2, 1}");
+        assert_eq!(empty_set.to_str(), ~"{}");
+    }
+}
diff --git a/src/libstd/treemap.rs b/src/libstd/treemap.rs
deleted file mode 100644
index 93f8d06ee08..00000000000
--- a/src/libstd/treemap.rs
+++ /dev/null
@@ -1,1240 +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.
-
-//! An ordered map and set implemented as self-balancing binary search
-//! trees. The only requirement for the types is that the key implements
-//! `TotalOrd`.
-
-use core::iterator::*;
-use core::util::{swap, replace};
-
-// This is implemented as an AA tree, which is a simplified variation of
-// a red-black tree where where red (horizontal) nodes can only be added
-// as a right child. The time complexity is the same, and re-balancing
-// operations are more frequent but also cheaper.
-
-// Future improvements:
-
-// range search - O(log n) retrieval of an iterator from some key
-
-// (possibly) implement the overloads Python does for sets:
-//   * intersection: &
-//   * difference: -
-//   * symmetric difference: ^
-//   * union: |
-// These would be convenient since the methods work like `each`
-
-pub struct TreeMap<K, V> {
-    priv root: Option<~TreeNode<K, V>>,
-    priv length: uint
-}
-
-impl<K: Eq + TotalOrd, V: Eq> Eq for TreeMap<K, V> {
-    fn eq(&self, other: &TreeMap<K, V>) -> bool {
-        if self.len() != other.len() {
-            false
-        } else {
-            let mut x = self.iter();
-            let mut y = other.iter();
-            for self.len().times {
-                if x.next().unwrap() != y.next().unwrap() {
-                    return false
-                }
-            }
-            true
-        }
-    }
-    fn ne(&self, other: &TreeMap<K, V>) -> bool { !self.eq(other) }
-}
-
-// Lexicographical comparison
-fn lt<K: Ord + TotalOrd, V>(a: &TreeMap<K, V>,
-                                 b: &TreeMap<K, V>) -> bool {
-    let mut x = a.iter();
-    let mut y = b.iter();
-
-    let (a_len, b_len) = (a.len(), b.len());
-    for uint::min(a_len, b_len).times {
-        let (key_a,_) = x.next().unwrap();
-        let (key_b,_) = y.next().unwrap();
-        if *key_a < *key_b { return true; }
-        if *key_a > *key_b { return false; }
-    };
-
-    a_len < b_len
-}
-
-impl<K: Ord + TotalOrd, V> Ord for TreeMap<K, V> {
-    #[inline(always)]
-    fn lt(&self, other: &TreeMap<K, V>) -> bool { lt(self, other) }
-    #[inline(always)]
-    fn le(&self, other: &TreeMap<K, V>) -> bool { !lt(other, self) }
-    #[inline(always)]
-    fn ge(&self, other: &TreeMap<K, V>) -> bool { !lt(self, other) }
-    #[inline(always)]
-    fn gt(&self, other: &TreeMap<K, V>) -> bool { lt(other, self) }
-}
-
-impl<K: TotalOrd, V> Container for TreeMap<K, V> {
-    /// Return the number of elements in the map
-    fn len(&const self) -> uint { self.length }
-
-    /// Return true if the map contains no elements
-    fn is_empty(&const self) -> bool { self.root.is_none() }
-}
-
-impl<K: TotalOrd, V> Mutable for TreeMap<K, V> {
-    /// Clear the map, removing all key-value pairs.
-    fn clear(&mut self) {
-        self.root = None;
-        self.length = 0
-    }
-}
-
-impl<K: TotalOrd, V> Map<K, V> for TreeMap<K, V> {
-    /// Return true if the map contains a value for the specified key
-    fn contains_key(&self, key: &K) -> bool {
-        self.find(key).is_some()
-    }
-
-    /// Visit all key-value pairs in order
-    fn each<'a>(&'a self, f: &fn(&'a K, &'a V) -> bool) -> bool {
-        each(&self.root, f)
-    }
-
-    /// Visit all keys in order
-    fn each_key(&self, f: &fn(&K) -> bool) -> bool {
-        self.each(|k, _| f(k))
-    }
-
-    /// Visit all values in order
-    fn each_value<'a>(&'a self, f: &fn(&'a V) -> bool) -> bool {
-        self.each(|_, v| f(v))
-    }
-
-    /// Iterate over the map and mutate the contained values
-    fn mutate_values(&mut self, f: &fn(&K, &mut V) -> bool) -> bool {
-        mutate_values(&mut self.root, f)
-    }
-
-    /// Return a reference to the value corresponding to the key
-    fn find<'a>(&'a self, key: &K) -> Option<&'a V> {
-        let mut current: &'a Option<~TreeNode<K, V>> = &self.root;
-        loop {
-            match *current {
-              Some(ref r) => {
-                match key.cmp(&r.key) {
-                  Less => current = &r.left,
-                  Greater => current = &r.right,
-                  Equal => return Some(&r.value)
-                }
-              }
-              None => return None
-            }
-        }
-    }
-
-    /// Return a mutable reference to the value corresponding to the key
-    #[inline(always)]
-    fn find_mut<'a>(&'a mut self, key: &K) -> Option<&'a mut V> {
-        find_mut(&mut self.root, key)
-    }
-
-    /// Insert a key-value pair into the map. An existing value for a
-    /// key is replaced by the new value. Return true if the key did
-    /// not already exist in the map.
-    fn insert(&mut self, key: K, value: V) -> bool {
-        self.swap(key, value).is_none()
-    }
-
-    /// Remove a key-value pair from the map. Return true if the key
-    /// was present in the map, otherwise false.
-    fn remove(&mut self, key: &K) -> bool {
-        self.pop(key).is_some()
-    }
-
-    /// Insert a key-value pair from the map. If the key already had a value
-    /// present in the map, that value is returned. Otherwise None is returned.
-    fn swap(&mut self, key: K, value: V) -> Option<V> {
-        let ret = insert(&mut self.root, key, value);
-        if ret.is_none() { self.length += 1 }
-        ret
-    }
-
-    /// Removes a key from the map, returning the value at the key if the key
-    /// was previously in the map.
-    fn pop(&mut self, key: &K) -> Option<V> {
-        let ret = remove(&mut self.root, key);
-        if ret.is_some() { self.length -= 1 }
-        ret
-    }
-}
-
-pub impl<K: TotalOrd, V> TreeMap<K, V> {
-    /// Create an empty TreeMap
-    fn new() -> TreeMap<K, V> { TreeMap{root: None, length: 0} }
-
-    /// Visit all key-value pairs in reverse order
-    fn each_reverse<'a>(&'a self, f: &fn(&'a K, &'a V) -> bool) -> bool {
-        each_reverse(&self.root, f)
-    }
-
-    /// Visit all keys in reverse order
-    fn each_key_reverse(&self, f: &fn(&K) -> bool) -> bool {
-        self.each_reverse(|k, _| f(k))
-    }
-
-    /// Visit all values in reverse order
-    fn each_value_reverse(&self, f: &fn(&V) -> bool) -> bool {
-        self.each_reverse(|_, v| f(v))
-    }
-
-    /// Get a lazy iterator over the key-value pairs in the map.
-    /// Requires that it be frozen (immutable).
-    fn iter<'a>(&'a self) -> TreeMapIterator<'a, K, V> {
-        TreeMapIterator{stack: ~[], node: &self.root}
-    }
-}
-
-/// Lazy forward iterator over a map
-pub struct TreeMapIterator<'self, K, V> {
-    priv stack: ~[&'self ~TreeNode<K, V>],
-    priv node: &'self Option<~TreeNode<K, V>>
-}
-
-impl<'self, K, V> Iterator<(&'self K, &'self V)> for TreeMapIterator<'self, K, V> {
-    /// Advance the iterator to the next node (in order) and return a
-    /// tuple with a reference to the key and value. If there are no
-    /// more nodes, return `None`.
-    fn next(&mut self) -> Option<(&'self K, &'self V)> {
-        while !self.stack.is_empty() || self.node.is_some() {
-            match *self.node {
-              Some(ref x) => {
-                self.stack.push(x);
-                self.node = &x.left;
-              }
-              None => {
-                let res = self.stack.pop();
-                self.node = &res.right;
-                return Some((&res.key, &res.value));
-              }
-            }
-        }
-        None
-    }
-}
-
-impl<'self, T> Iterator<&'self T> for TreeSetIterator<'self, T> {
-    /// Advance the iterator to the next node (in order). If there are no more nodes, return `None`.
-    #[inline(always)]
-    fn next(&mut self) -> Option<&'self T> {
-        do self.iter.next().map |&(value, _)| { value }
-    }
-}
-
-pub struct TreeSet<T> {
-    priv map: TreeMap<T, ()>
-}
-
-impl<T: TotalOrd> BaseIter<T> for TreeSet<T> {
-    /// Visit all values in order
-    #[inline(always)]
-    fn each(&self, f: &fn(&T) -> bool) -> bool { self.map.each_key(f) }
-    #[inline(always)]
-    fn size_hint(&self) -> Option<uint> { Some(self.len()) }
-}
-
-impl<T: TotalOrd> ReverseIter<T> for TreeSet<T> {
-    /// Visit all values in reverse order
-    #[inline(always)]
-    fn each_reverse(&self, f: &fn(&T) -> bool) -> bool {
-        self.map.each_key_reverse(f)
-    }
-}
-
-impl<T: Eq + TotalOrd> Eq for TreeSet<T> {
-    #[inline(always)]
-    fn eq(&self, other: &TreeSet<T>) -> bool { self.map == other.map }
-    #[inline(always)]
-    fn ne(&self, other: &TreeSet<T>) -> bool { self.map != other.map }
-}
-
-impl<T: Ord + TotalOrd> Ord for TreeSet<T> {
-    #[inline(always)]
-    fn lt(&self, other: &TreeSet<T>) -> bool { self.map < other.map }
-    #[inline(always)]
-    fn le(&self, other: &TreeSet<T>) -> bool { self.map <= other.map }
-    #[inline(always)]
-    fn ge(&self, other: &TreeSet<T>) -> bool { self.map >= other.map }
-    #[inline(always)]
-    fn gt(&self, other: &TreeSet<T>) -> bool { self.map > other.map }
-}
-
-impl<T: TotalOrd> Container for TreeSet<T> {
-    /// Return the number of elements in the set
-    #[inline(always)]
-    fn len(&const self) -> uint { self.map.len() }
-
-    /// Return true if the set contains no elements
-    #[inline(always)]
-    fn is_empty(&const self) -> bool { self.map.is_empty() }
-}
-
-impl<T: TotalOrd> Mutable for TreeSet<T> {
-    /// Clear the set, removing all values.
-    #[inline(always)]
-    fn clear(&mut self) { self.map.clear() }
-}
-
-impl<T: TotalOrd> Set<T> for TreeSet<T> {
-    /// Return true if the set contains a value
-    #[inline(always)]
-    fn contains(&self, value: &T) -> bool {
-        self.map.contains_key(value)
-    }
-
-    /// Add a value to the set. Return true if the value was not already
-    /// present in the set.
-    #[inline(always)]
-    fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
-
-    /// Remove a value from the set. Return true if the value was
-    /// present in the set.
-    #[inline(always)]
-    fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
-
-    /// Return true if the set has no elements in common with `other`.
-    /// This is equivalent to checking for an empty intersection.
-    fn is_disjoint(&self, other: &TreeSet<T>) -> bool {
-        let mut x = self.iter();
-        let mut y = other.iter();
-        let mut a = x.next();
-        let mut b = y.next();
-        while a.is_some() && b.is_some() {
-            let a1 = a.unwrap();
-            let b1 = b.unwrap();
-            match a1.cmp(b1) {
-              Less => a = x.next(),
-              Greater => b = y.next(),
-              Equal => return false
-            }
-        }
-        true
-    }
-
-    /// Return true if the set is a subset of another
-    #[inline(always)]
-    fn is_subset(&self, other: &TreeSet<T>) -> bool {
-        other.is_superset(self)
-    }
-
-    /// Return true if the set is a superset of another
-    fn is_superset(&self, other: &TreeSet<T>) -> bool {
-        let mut x = self.iter();
-        let mut y = other.iter();
-        let mut a = x.next();
-        let mut b = y.next();
-        while b.is_some() {
-            if a.is_none() {
-                return false
-            }
-
-            let a1 = a.unwrap();
-            let b1 = b.unwrap();
-
-            match a1.cmp(b1) {
-              Less => (),
-              Greater => return false,
-              Equal => b = y.next(),
-            }
-
-            a = x.next();
-        }
-        true
-    }
-
-    /// Visit the values (in-order) representing the difference
-    fn difference(&self, other: &TreeSet<T>, f: &fn(&T) -> bool) -> bool {
-        let mut x = self.iter();
-        let mut y = other.iter();
-
-        let mut a = x.next();
-        let mut b = y.next();
-
-        while a.is_some() {
-            if b.is_none() {
-                return f(a.unwrap()) && x.advance(f);
-            }
-
-            let a1 = a.unwrap();
-            let b1 = b.unwrap();
-
-            let cmp = a1.cmp(b1);
-
-            if cmp == Less {
-                if !f(a1) { return false; }
-                a = x.next();
-            } else {
-                if cmp == Equal { a = x.next() }
-                b = y.next();
-            }
-        }
-        return true;
-    }
-
-    /// Visit the values (in-order) representing the symmetric difference
-    fn symmetric_difference(&self, other: &TreeSet<T>,
-                            f: &fn(&T) -> bool) -> bool {
-        let mut x = self.iter();
-        let mut y = other.iter();
-
-        let mut a = x.next();
-        let mut b = y.next();
-
-        while a.is_some() {
-            if b.is_none() {
-                return f(a.unwrap()) && x.advance(f);
-            }
-
-            let a1 = a.unwrap();
-            let b1 = b.unwrap();
-
-            let cmp = a1.cmp(b1);
-
-            if cmp == Less {
-                if !f(a1) { return false; }
-                a = x.next();
-            } else {
-                if cmp == Greater {
-                    if !f(b1) { return false; }
-                } else {
-                    a = x.next();
-                }
-                b = y.next();
-            }
-        }
-        return b.each(|&x| f(x)) && y.advance(f);
-    }
-
-    /// Visit the values (in-order) representing the intersection
-    fn intersection(&self, other: &TreeSet<T>, f: &fn(&T) -> bool) -> bool {
-        let mut x = self.iter();
-        let mut y = other.iter();
-
-        let mut a = x.next();
-        let mut b = y.next();
-
-        while a.is_some() && b.is_some() {
-            let a1 = a.unwrap();
-            let b1 = b.unwrap();
-
-            let cmp = a1.cmp(b1);
-
-            if cmp == Less {
-                a = x.next();
-            } else {
-                if cmp == Equal {
-                    if !f(a1) { return false }
-                }
-                b = y.next();
-            }
-        }
-        return true;
-    }
-
-    /// Visit the values (in-order) representing the union
-    fn union(&self, other: &TreeSet<T>, f: &fn(&T) -> bool) -> bool {
-        let mut x = self.iter();
-        let mut y = other.iter();
-
-        let mut a = x.next();
-        let mut b = y.next();
-
-        while a.is_some() {
-            if b.is_none() {
-                return f(a.unwrap()) && x.advance(f);
-            }
-
-            let a1 = a.unwrap();
-            let b1 = b.unwrap();
-
-            let cmp = a1.cmp(b1);
-
-            if cmp == Greater {
-                if !f(b1) { return false; }
-                b = y.next();
-            } else {
-                if !f(a1) { return false; }
-                if cmp == Equal {
-                    b = y.next();
-                }
-                a = x.next();
-            }
-        }
-        return b.each(|&x| f(x)) && y.advance(f);
-    }
-}
-
-pub impl <T: TotalOrd> TreeSet<T> {
-    /// Create an empty TreeSet
-    #[inline(always)]
-    fn new() -> TreeSet<T> { TreeSet{map: TreeMap::new()} }
-
-    /// Get a lazy iterator over the values in the set.
-    /// Requires that it be frozen (immutable).
-    #[inline(always)]
-    fn iter<'a>(&'a self) -> TreeSetIterator<'a, T> {
-        TreeSetIterator{iter: self.map.iter()}
-    }
-}
-
-/// Lazy forward iterator over a set
-pub struct TreeSetIterator<'self, T> {
-    priv iter: TreeMapIterator<'self, T, ()>
-}
-
-// Nodes keep track of their level in the tree, starting at 1 in the
-// leaves and with a red child sharing the level of the parent.
-struct TreeNode<K, V> {
-    key: K,
-    value: V,
-    left: Option<~TreeNode<K, V>>,
-    right: Option<~TreeNode<K, V>>,
-    level: uint
-}
-
-pub impl<K: TotalOrd, V> TreeNode<K, V> {
-    #[inline(always)]
-    fn new(key: K, value: V) -> TreeNode<K, V> {
-        TreeNode{key: key, value: value, left: None, right: None, level: 1}
-    }
-}
-
-fn each<'r, K: TotalOrd, V>(node: &'r Option<~TreeNode<K, V>>,
-                            f: &fn(&'r K, &'r V) -> bool) -> bool {
-    node.each(|x| each(&x.left, f) && f(&x.key, &x.value) &&
-                  each(&x.right, f))
-}
-
-fn each_reverse<'r, K: TotalOrd, V>(node: &'r Option<~TreeNode<K, V>>,
-                                    f: &fn(&'r K, &'r V) -> bool) -> bool {
-    node.each(|x| each_reverse(&x.right, f) && f(&x.key, &x.value) &&
-                  each_reverse(&x.left, f))
-}
-
-fn mutate_values<'r, K: TotalOrd, V>(node: &'r mut Option<~TreeNode<K, V>>,
-                                     f: &fn(&'r K, &'r mut V) -> bool)
-                                  -> bool {
-    match *node {
-      Some(~TreeNode{key: ref key, value: ref mut value, left: ref mut left,
-                     right: ref mut right, _}) => {
-        if !mutate_values(left, f) { return false }
-        if !f(key, value) { return false }
-        if !mutate_values(right, f) { return false }
-      }
-      None => return false
-    }
-    true
-}
-
-// Remove left horizontal link by rotating right
-fn skew<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>) {
-    if node.left.map_default(false, |x| x.level == node.level) {
-        let mut save = node.left.swap_unwrap();
-        swap(&mut node.left, &mut save.right); // save.right now None
-        swap(node, &mut save);
-        node.right = Some(save);
-    }
-}
-
-// Remove dual horizontal link by rotating left and increasing level of
-// the parent
-fn split<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>) {
-    if node.right.map_default(false,
-      |x| x.right.map_default(false, |y| y.level == node.level)) {
-        let mut save = node.right.swap_unwrap();
-        swap(&mut node.right, &mut save.left); // save.left now None
-        save.level += 1;
-        swap(node, &mut save);
-        node.left = Some(save);
-    }
-}
-
-fn find_mut<'r, K: TotalOrd, V>(node: &'r mut Option<~TreeNode<K, V>>,
-                                key: &K)
-                             -> Option<&'r mut V> {
-    match *node {
-      Some(ref mut x) => {
-        match key.cmp(&x.key) {
-          Less => find_mut(&mut x.left, key),
-          Greater => find_mut(&mut x.right, key),
-          Equal => Some(&mut x.value),
-        }
-      }
-      None => None
-    }
-}
-
-fn insert<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
-                          key: K, value: V) -> Option<V> {
-    match *node {
-      Some(ref mut save) => {
-        match key.cmp(&save.key) {
-          Less => {
-            let inserted = insert(&mut save.left, key, value);
-            skew(save);
-            split(save);
-            inserted
-          }
-          Greater => {
-            let inserted = insert(&mut save.right, key, value);
-            skew(save);
-            split(save);
-            inserted
-          }
-          Equal => {
-            save.key = key;
-            Some(replace(&mut save.value, value))
-          }
-        }
-      }
-      None => {
-       *node = Some(~TreeNode::new(key, value));
-        None
-      }
-    }
-}
-
-fn remove<K: TotalOrd, V>(node: &mut Option<~TreeNode<K, V>>,
-                          key: &K) -> Option<V> {
-    fn heir_swap<K: TotalOrd, V>(node: &mut ~TreeNode<K, V>,
-                                 child: &mut Option<~TreeNode<K, V>>) {
-        // *could* be done without recursion, but it won't borrow check
-        for child.each_mut |x| {
-            if x.right.is_some() {
-                heir_swap(node, &mut x.right);
-            } else {
-                swap(&mut node.key, &mut x.key);
-                swap(&mut node.value, &mut x.value);
-            }
-        }
-    }
-
-    match *node {
-      None => {
-        return None; // bottom of tree
-      }
-      Some(ref mut save) => {
-        let (ret, rebalance) = match key.cmp(&save.key) {
-          Less => (remove(&mut save.left, key), true),
-          Greater => (remove(&mut save.right, key), true),
-          Equal => {
-            if save.left.is_some() {
-                if save.right.is_some() {
-                    let mut left = save.left.swap_unwrap();
-                    if left.right.is_some() {
-                        heir_swap(save, &mut left.right);
-                    } else {
-                        swap(&mut save.key, &mut left.key);
-                        swap(&mut save.value, &mut left.value);
-                    }
-                    save.left = Some(left);
-                    (remove(&mut save.left, key), true)
-                } else {
-                    let new = save.left.swap_unwrap();
-                    let ~TreeNode{value, _} = replace(save, new);
-                    *save = save.left.swap_unwrap();
-                    (Some(value), true)
-                }
-            } else if save.right.is_some() {
-                let new = save.right.swap_unwrap();
-                let ~TreeNode{value, _} = replace(save, new);
-                (Some(value), true)
-            } else {
-                (None, false)
-            }
-          }
-        };
-
-        if rebalance {
-            let left_level = save.left.map_default(0, |x| x.level);
-            let right_level = save.right.map_default(0, |x| x.level);
-
-            // re-balance, if necessary
-            if left_level < save.level - 1 || right_level < save.level - 1 {
-                save.level -= 1;
-
-                if right_level > save.level {
-                    for save.right.each_mut |x| { x.level = save.level }
-                }
-
-                skew(save);
-
-                for save.right.each_mut |right| {
-                    skew(right);
-                    for right.right.each_mut |x| { skew(x) }
-                }
-
-                split(save);
-                for save.right.each_mut |x| { split(x) }
-            }
-
-            return ret;
-        }
-      }
-    }
-    return match replace(node, None) {
-        Some(~TreeNode{value, _}) => Some(value), None => fail!()
-    };
-}
-
-#[cfg(test)]
-mod test_treemap {
-    use core::iterator::*;
-    use super::*;
-    use core::rand::RngUtil;
-
-    #[test]
-    fn find_empty() {
-        let m = TreeMap::new::<int, int>(); assert!(m.find(&5) == None);
-    }
-
-    #[test]
-    fn find_not_found() {
-        let mut m = TreeMap::new();
-        assert!(m.insert(1, 2));
-        assert!(m.insert(5, 3));
-        assert!(m.insert(9, 3));
-        assert_eq!(m.find(&2), None);
-    }
-
-    #[test]
-    fn test_find_mut() {
-        let mut m = TreeMap::new();
-        assert!(m.insert(1, 12));
-        assert!(m.insert(2, 8));
-        assert!(m.insert(5, 14));
-        let new = 100;
-        match m.find_mut(&5) {
-          None => fail!(), Some(x) => *x = new
-        }
-        assert_eq!(m.find(&5), Some(&new));
-    }
-
-    #[test]
-    fn insert_replace() {
-        let mut m = TreeMap::new();
-        assert!(m.insert(5, 2));
-        assert!(m.insert(2, 9));
-        assert!(!m.insert(2, 11));
-        assert_eq!(m.find(&2).unwrap(), &11);
-    }
-
-    #[test]
-    fn test_clear() {
-        let mut m = TreeMap::new();
-        m.clear();
-        assert!(m.insert(5, 11));
-        assert!(m.insert(12, -3));
-        assert!(m.insert(19, 2));
-        m.clear();
-        assert!(m.find(&5).is_none());
-        assert!(m.find(&12).is_none());
-        assert!(m.find(&19).is_none());
-        assert!(m.is_empty());
-    }
-
-    #[test]
-    fn u8_map() {
-        let mut m = TreeMap::new();
-
-        let k1 = str::to_bytes(~"foo");
-        let k2 = str::to_bytes(~"bar");
-        let v1 = str::to_bytes(~"baz");
-        let v2 = str::to_bytes(~"foobar");
-
-        m.insert(copy k1, copy v1);
-        m.insert(copy k2, copy v2);
-
-        assert_eq!(m.find(&k2), Some(&v2));
-        assert_eq!(m.find(&k1), Some(&v1));
-    }
-
-    fn check_equal<K: Eq + TotalOrd, V: Eq>(ctrl: &[(K, V)],
-                                            map: &TreeMap<K, V>) {
-        assert_eq!(ctrl.is_empty(), map.is_empty());
-        for ctrl.each |x| {
-            let &(k, v) = x;
-            assert!(map.find(&k).unwrap() == &v)
-        }
-        for map.each |map_k, map_v| {
-            let mut found = false;
-            for ctrl.each |x| {
-                let &(ctrl_k, ctrl_v) = x;
-                if *map_k == ctrl_k {
-                    assert!(*map_v == ctrl_v);
-                    found = true;
-                    break;
-                }
-            }
-            assert!(found);
-        }
-    }
-
-    fn check_left<K: TotalOrd, V>(node: &Option<~TreeNode<K, V>>,
-                                  parent: &~TreeNode<K, V>) {
-        match *node {
-          Some(ref r) => {
-            assert_eq!(r.key.cmp(&parent.key), Less);
-            assert!(r.level == parent.level - 1); // left is black
-            check_left(&r.left, r);
-            check_right(&r.right, r, false);
-          }
-          None => assert!(parent.level == 1) // parent is leaf
-        }
-    }
-
-    fn check_right<K: TotalOrd, V>(node: &Option<~TreeNode<K, V>>,
-                                   parent: &~TreeNode<K, V>,
-                                   parent_red: bool) {
-        match *node {
-          Some(ref r) => {
-            assert_eq!(r.key.cmp(&parent.key), Greater);
-            let red = r.level == parent.level;
-            if parent_red { assert!(!red) } // no dual horizontal links
-            // Right red or black
-            assert!(red || r.level == parent.level - 1);
-            check_left(&r.left, r);
-            check_right(&r.right, r, red);
-          }
-          None => assert!(parent.level == 1) // parent is leaf
-        }
-    }
-
-    fn check_structure<K: TotalOrd, V>(map: &TreeMap<K, V>) {
-        match map.root {
-          Some(ref r) => {
-            check_left(&r.left, r);
-            check_right(&r.right, r, false);
-          }
-          None => ()
-        }
-    }
-
-    #[test]
-    fn test_rand_int() {
-        let mut map = TreeMap::new::<int, int>();
-        let mut ctrl = ~[];
-
-        check_equal(ctrl, &map);
-        assert!(map.find(&5).is_none());
-
-        let mut rng = rand::IsaacRng::new_seeded(&[42]);
-
-        for 3.times {
-            for 90.times {
-                let k = rng.gen();
-                let v = rng.gen();
-                if !ctrl.contains(&(k, v)) {
-                    assert!(map.insert(k, v));
-                    ctrl.push((k, v));
-                    check_structure(&map);
-                    check_equal(ctrl, &map);
-                }
-            }
-
-            for 30.times {
-                let r = rng.gen_uint_range(0, ctrl.len());
-                let (key, _) = vec::remove(&mut ctrl, r);
-                assert!(map.remove(&key));
-                check_structure(&map);
-                check_equal(ctrl, &map);
-            }
-        }
-    }
-
-    #[test]
-    fn test_len() {
-        let mut m = TreeMap::new();
-        assert!(m.insert(3, 6));
-        assert_eq!(m.len(), 1);
-        assert!(m.insert(0, 0));
-        assert_eq!(m.len(), 2);
-        assert!(m.insert(4, 8));
-        assert_eq!(m.len(), 3);
-        assert!(m.remove(&3));
-        assert_eq!(m.len(), 2);
-        assert!(!m.remove(&5));
-        assert_eq!(m.len(), 2);
-        assert!(m.insert(2, 4));
-        assert_eq!(m.len(), 3);
-        assert!(m.insert(1, 2));
-        assert_eq!(m.len(), 4);
-    }
-
-    #[test]
-    fn test_each() {
-        let mut m = TreeMap::new();
-
-        assert!(m.insert(3, 6));
-        assert!(m.insert(0, 0));
-        assert!(m.insert(4, 8));
-        assert!(m.insert(2, 4));
-        assert!(m.insert(1, 2));
-
-        let mut n = 0;
-        for m.each |k, v| {
-            assert_eq!(*k, n);
-            assert_eq!(*v, n * 2);
-            n += 1;
-        }
-    }
-
-    #[test]
-    fn test_each_reverse() {
-        let mut m = TreeMap::new();
-
-        assert!(m.insert(3, 6));
-        assert!(m.insert(0, 0));
-        assert!(m.insert(4, 8));
-        assert!(m.insert(2, 4));
-        assert!(m.insert(1, 2));
-
-        let mut n = 4;
-        for m.each_reverse |k, v| {
-            assert_eq!(*k, n);
-            assert_eq!(*v, n * 2);
-            n -= 1;
-        }
-    }
-
-    #[test]
-    fn test_eq() {
-        let mut a = TreeMap::new();
-        let mut b = TreeMap::new();
-
-        assert!(a == b);
-        assert!(a.insert(0, 5));
-        assert!(a != b);
-        assert!(b.insert(0, 4));
-        assert!(a != b);
-        assert!(a.insert(5, 19));
-        assert!(a != b);
-        assert!(!b.insert(0, 5));
-        assert!(a != b);
-        assert!(b.insert(5, 19));
-        assert!(a == b);
-    }
-
-    #[test]
-    fn test_lt() {
-        let mut a = TreeMap::new();
-        let mut b = TreeMap::new();
-
-        assert!(!(a < b) && !(b < a));
-        assert!(b.insert(0, 5));
-        assert!(a < b);
-        assert!(a.insert(0, 7));
-        assert!(!(a < b) && !(b < a));
-        assert!(b.insert(-2, 0));
-        assert!(b < a);
-        assert!(a.insert(-5, 2));
-        assert!(a < b);
-        assert!(a.insert(6, 2));
-        assert!(a < b && !(b < a));
-    }
-
-    #[test]
-    fn test_ord() {
-        let mut a = TreeMap::new();
-        let mut b = TreeMap::new();
-
-        assert!(a <= b && a >= b);
-        assert!(a.insert(1, 1));
-        assert!(a > b && a >= b);
-        assert!(b < a && b <= a);
-        assert!(b.insert(2, 2));
-        assert!(b > a && b >= a);
-        assert!(a < b && a <= b);
-    }
-
-    #[test]
-    fn test_lazy_iterator() {
-        let mut m = TreeMap::new();
-        let (x1, y1) = (2, 5);
-        let (x2, y2) = (9, 12);
-        let (x3, y3) = (20, -3);
-        let (x4, y4) = (29, 5);
-        let (x5, y5) = (103, 3);
-
-        assert!(m.insert(x1, y1));
-        assert!(m.insert(x2, y2));
-        assert!(m.insert(x3, y3));
-        assert!(m.insert(x4, y4));
-        assert!(m.insert(x5, y5));
-
-        let m = m;
-        let mut a = m.iter();
-
-        assert_eq!(a.next().unwrap(), (&x1, &y1));
-        assert_eq!(a.next().unwrap(), (&x2, &y2));
-        assert_eq!(a.next().unwrap(), (&x3, &y3));
-        assert_eq!(a.next().unwrap(), (&x4, &y4));
-        assert_eq!(a.next().unwrap(), (&x5, &y5));
-
-        assert!(a.next().is_none());
-
-        let mut b = m.iter();
-
-        let expected = [(&x1, &y1), (&x2, &y2), (&x3, &y3), (&x4, &y4),
-                        (&x5, &y5)];
-        let mut i = 0;
-
-        for b.advance |x| {
-            assert_eq!(expected[i], x);
-            i += 1;
-
-            if i == 2 {
-                break
-            }
-        }
-
-        for b.advance |x| {
-            assert_eq!(expected[i], x);
-            i += 1;
-        }
-    }
-}
-
-#[cfg(test)]
-mod test_set {
-    use core::iterator::*;
-    use super::*;
-
-    #[test]
-    fn test_clear() {
-        let mut s = TreeSet::new();
-        s.clear();
-        assert!(s.insert(5));
-        assert!(s.insert(12));
-        assert!(s.insert(19));
-        s.clear();
-        assert!(!s.contains(&5));
-        assert!(!s.contains(&12));
-        assert!(!s.contains(&19));
-        assert!(s.is_empty());
-    }
-
-    #[test]
-    fn test_disjoint() {
-        let mut xs = TreeSet::new();
-        let mut ys = TreeSet::new();
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(xs.insert(5));
-        assert!(ys.insert(11));
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(xs.insert(7));
-        assert!(xs.insert(19));
-        assert!(xs.insert(4));
-        assert!(ys.insert(2));
-        assert!(ys.insert(-11));
-        assert!(xs.is_disjoint(&ys));
-        assert!(ys.is_disjoint(&xs));
-        assert!(ys.insert(7));
-        assert!(!xs.is_disjoint(&ys));
-        assert!(!ys.is_disjoint(&xs));
-    }
-
-    #[test]
-    fn test_subset_and_superset() {
-        let mut a = TreeSet::new();
-        assert!(a.insert(0));
-        assert!(a.insert(5));
-        assert!(a.insert(11));
-        assert!(a.insert(7));
-
-        let mut b = TreeSet::new();
-        assert!(b.insert(0));
-        assert!(b.insert(7));
-        assert!(b.insert(19));
-        assert!(b.insert(250));
-        assert!(b.insert(11));
-        assert!(b.insert(200));
-
-        assert!(!a.is_subset(&b));
-        assert!(!a.is_superset(&b));
-        assert!(!b.is_subset(&a));
-        assert!(!b.is_superset(&a));
-
-        assert!(b.insert(5));
-
-        assert!(a.is_subset(&b));
-        assert!(!a.is_superset(&b));
-        assert!(!b.is_subset(&a));
-        assert!(b.is_superset(&a));
-    }
-
-    #[test]
-    fn test_each() {
-        let mut m = TreeSet::new();
-
-        assert!(m.insert(3));
-        assert!(m.insert(0));
-        assert!(m.insert(4));
-        assert!(m.insert(2));
-        assert!(m.insert(1));
-
-        let mut n = 0;
-        for m.each |x| {
-            assert_eq!(*x, n);
-            n += 1
-        }
-    }
-
-    #[test]
-    fn test_each_reverse() {
-        let mut m = TreeSet::new();
-
-        assert!(m.insert(3));
-        assert!(m.insert(0));
-        assert!(m.insert(4));
-        assert!(m.insert(2));
-        assert!(m.insert(1));
-
-        let mut n = 4;
-        for m.each_reverse |x| {
-            assert_eq!(*x, n);
-            n -= 1
-        }
-    }
-
-    fn check(a: &[int], b: &[int], expected: &[int],
-             f: &fn(&TreeSet<int>, &TreeSet<int>, f: &fn(&int) -> bool) -> bool) {
-        let mut set_a = TreeSet::new();
-        let mut set_b = TreeSet::new();
-
-        for a.each |x| { assert!(set_a.insert(*x)) }
-        for b.each |y| { assert!(set_b.insert(*y)) }
-
-        let mut i = 0;
-        for f(&set_a, &set_b) |x| {
-            assert_eq!(*x, expected[i]);
-            i += 1;
-        }
-        assert_eq!(i, expected.len());
-    }
-
-    #[test]
-    fn test_intersection() {
-        fn check_intersection(a: &[int], b: &[int], expected: &[int]) {
-            check(a, b, expected, |x, y, z| x.intersection(y, z))
-        }
-
-        check_intersection([], [], []);
-        check_intersection([1, 2, 3], [], []);
-        check_intersection([], [1, 2, 3], []);
-        check_intersection([2], [1, 2, 3], [2]);
-        check_intersection([1, 2, 3], [2], [2]);
-        check_intersection([11, 1, 3, 77, 103, 5, -5],
-                           [2, 11, 77, -9, -42, 5, 3],
-                           [3, 5, 11, 77]);
-    }
-
-    #[test]
-    fn test_difference() {
-        fn check_difference(a: &[int], b: &[int], expected: &[int]) {
-            check(a, b, expected, |x, y, z| x.difference(y, z))
-        }
-
-        check_difference([], [], []);
-        check_difference([1, 12], [], [1, 12]);
-        check_difference([], [1, 2, 3, 9], []);
-        check_difference([1, 3, 5, 9, 11],
-                         [3, 9],
-                         [1, 5, 11]);
-        check_difference([-5, 11, 22, 33, 40, 42],
-                         [-12, -5, 14, 23, 34, 38, 39, 50],
-                         [11, 22, 33, 40, 42]);
-    }
-
-    #[test]
-    fn test_symmetric_difference() {
-        fn check_symmetric_difference(a: &[int], b: &[int],
-                                      expected: &[int]) {
-            check(a, b, expected, |x, y, z| x.symmetric_difference(y, z))
-        }
-
-        check_symmetric_difference([], [], []);
-        check_symmetric_difference([1, 2, 3], [2], [1, 3]);
-        check_symmetric_difference([2], [1, 2, 3], [1, 3]);
-        check_symmetric_difference([1, 3, 5, 9, 11],
-                                   [-2, 3, 9, 14, 22],
-                                   [-2, 1, 5, 11, 14, 22]);
-    }
-
-    #[test]
-    fn test_union() {
-        fn check_union(a: &[int], b: &[int],
-                                      expected: &[int]) {
-            check(a, b, expected, |x, y, z| x.union(y, z))
-        }
-
-        check_union([], [], []);
-        check_union([1, 2, 3], [2], [1, 2, 3]);
-        check_union([2], [1, 2, 3], [1, 2, 3]);
-        check_union([1, 3, 5, 9, 11, 16, 19, 24],
-                    [-2, 1, 5, 9, 13, 19],
-                    [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]);
-    }
-
-    #[test]
-    fn test_zip() {
-        let mut x = TreeSet::new();
-        x.insert(5u);
-        x.insert(12u);
-        x.insert(11u);
-
-        let mut y = TreeSet::new();
-        y.insert("foo");
-        y.insert("bar");
-
-        let x = x;
-        let y = y;
-        let mut z = x.iter().zip(y.iter());
-
-        // FIXME: #5801: this needs a type hint to compile...
-        let result: Option<(&uint, & &'static str)> = z.next();
-        assert_eq!(result.unwrap(), (&5u, & &"bar"));
-
-        let result: Option<(&uint, & &'static str)> = z.next();
-        assert_eq!(result.unwrap(), (&11u, & &"foo"));
-
-        let result: Option<(&uint, & &'static str)> = z.next();
-        assert!(result.is_none());
-    }
-
-    #[test]
-    fn test_swap() {
-        let mut m = TreeMap::new();
-        assert_eq!(m.swap(1, 2), None);
-        assert_eq!(m.swap(1, 3), Some(2));
-        assert_eq!(m.swap(1, 4), Some(3));
-    }
-
-    #[test]
-    fn test_pop() {
-        let mut m = TreeMap::new();
-        m.insert(1, 2);
-        assert_eq!(m.pop(&1), Some(2));
-        assert_eq!(m.pop(&1), None);
-    }
-}
diff --git a/src/libstd/trie.rs b/src/libstd/trie.rs
new file mode 100644
index 00000000000..13b892e700e
--- /dev/null
+++ b/src/libstd/trie.rs
@@ -0,0 +1,548 @@
+// 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.
+
+//! An ordered map and set for integer keys implemented as a radix trie
+
+use prelude::*;
+use util::{swap, replace};
+
+// FIXME: #5244: need to manually update the TrieNode constructor
+static SHIFT: uint = 4;
+static SIZE: uint = 1 << SHIFT;
+static MASK: uint = SIZE - 1;
+
+enum Child<T> {
+    Internal(~TrieNode<T>),
+    External(uint, T),
+    Nothing
+}
+
+pub struct TrieMap<T> {
+    priv root: TrieNode<T>,
+    priv length: uint
+}
+
+impl<T> Container for TrieMap<T> {
+    /// Return the number of elements in the map
+    #[inline(always)]
+    fn len(&const self) -> uint { self.length }
+
+    /// Return true if the map contains no elements
+    #[inline(always)]
+    fn is_empty(&const self) -> bool { self.len() == 0 }
+}
+
+impl<T> Mutable for TrieMap<T> {
+    /// Clear the map, removing all values.
+    #[inline(always)]
+    fn clear(&mut self) {
+        self.root = TrieNode::new();
+        self.length = 0;
+    }
+}
+
+impl<T> Map<uint, T> for TrieMap<T> {
+    /// Return true if the map contains a value for the specified key
+    #[inline(always)]
+    fn contains_key(&self, key: &uint) -> bool {
+        self.find(key).is_some()
+    }
+
+    /// Visit all key-value pairs in order
+    #[inline(always)]
+    fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
+        self.root.each(f)
+    }
+
+    /// Visit all keys in order
+    #[inline(always)]
+    fn each_key(&self, f: &fn(&uint) -> bool) -> bool {
+        self.each(|k, _| f(k))
+    }
+
+    /// Visit all values in order
+    #[inline(always)]
+    fn each_value<'a>(&'a self, f: &fn(&'a T) -> bool) -> bool {
+        self.each(|_, v| f(v))
+    }
+
+    /// Iterate over the map and mutate the contained values
+    #[inline(always)]
+    fn mutate_values(&mut self, f: &fn(&uint, &mut T) -> bool) -> bool {
+        self.root.mutate_values(f)
+    }
+
+    /// Return a reference to the value corresponding to the key
+    #[inline(hint)]
+    fn find<'a>(&'a self, key: &uint) -> Option<&'a T> {
+        let mut node: &'a TrieNode<T> = &self.root;
+        let mut idx = 0;
+        loop {
+            match node.children[chunk(*key, idx)] {
+              Internal(ref x) => node = &**x,
+              External(stored, ref value) => {
+                if stored == *key {
+                    return Some(value)
+                } else {
+                    return None
+                }
+              }
+              Nothing => return None
+            }
+            idx += 1;
+        }
+    }
+
+    /// Return a mutable reference to the value corresponding to the key
+    #[inline(always)]
+    fn find_mut<'a>(&'a mut self, key: &uint) -> Option<&'a mut T> {
+        find_mut(&mut self.root.children[chunk(*key, 0)], *key, 1)
+    }
+
+    /// Insert a key-value pair into the map. An existing value for a
+    /// key is replaced by the new value. Return true if the key did
+    /// not already exist in the map.
+    #[inline(always)]
+    fn insert(&mut self, key: uint, value: T) -> bool {
+        self.swap(key, value).is_none()
+    }
+
+    /// Remove a key-value pair from the map. Return true if the key
+    /// was present in the map, otherwise false.
+    #[inline(always)]
+    fn remove(&mut self, key: &uint) -> bool {
+        self.pop(key).is_some()
+    }
+
+    /// Insert a key-value pair from the map. If the key already had a value
+    /// present in the map, that value is returned. Otherwise None is returned.
+    fn swap(&mut self, key: uint, value: T) -> Option<T> {
+        let ret = insert(&mut self.root.count,
+                         &mut self.root.children[chunk(key, 0)],
+                         key, value, 1);
+        if ret.is_none() { self.length += 1 }
+        ret
+    }
+
+    /// Removes a key from the map, returning the value at the key if the key
+    /// was previously in the map.
+    fn pop(&mut self, key: &uint) -> Option<T> {
+        let ret = remove(&mut self.root.count,
+                         &mut self.root.children[chunk(*key, 0)],
+                         *key, 1);
+        if ret.is_some() { self.length -= 1 }
+        ret
+    }
+}
+
+pub impl<T> TrieMap<T> {
+    /// Create an empty TrieMap
+    #[inline(always)]
+    fn new() -> TrieMap<T> {
+        TrieMap{root: TrieNode::new(), length: 0}
+    }
+
+    /// Visit all key-value pairs in reverse order
+    #[inline(always)]
+    fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
+        self.root.each_reverse(f)
+    }
+
+    /// Visit all keys in reverse order
+    #[inline(always)]
+    fn each_key_reverse(&self, f: &fn(&uint) -> bool) -> bool {
+        self.each_reverse(|k, _| f(k))
+    }
+
+    /// Visit all values in reverse order
+    #[inline(always)]
+    fn each_value_reverse(&self, f: &fn(&T) -> bool) -> bool {
+        self.each_reverse(|_, v| f(v))
+    }
+}
+
+pub struct TrieSet {
+    priv map: TrieMap<()>
+}
+
+impl BaseIter<uint> for TrieSet {
+    /// Visit all values in order
+    #[inline(always)]
+    fn each(&self, f: &fn(&uint) -> bool) -> bool { self.map.each_key(f) }
+    #[inline(always)]
+    fn size_hint(&self) -> Option<uint> { Some(self.len()) }
+}
+
+impl ReverseIter<uint> for TrieSet {
+    /// Visit all values in reverse order
+    #[inline(always)]
+    fn each_reverse(&self, f: &fn(&uint) -> bool) -> bool {
+        self.map.each_key_reverse(f)
+    }
+}
+
+impl Container for TrieSet {
+    /// Return the number of elements in the set
+    #[inline(always)]
+    fn len(&const self) -> uint { self.map.len() }
+
+    /// Return true if the set contains no elements
+    #[inline(always)]
+    fn is_empty(&const self) -> bool { self.map.is_empty() }
+}
+
+impl Mutable for TrieSet {
+    /// Clear the set, removing all values.
+    #[inline(always)]
+    fn clear(&mut self) { self.map.clear() }
+}
+
+pub impl TrieSet {
+    /// Create an empty TrieSet
+    #[inline(always)]
+    fn new() -> TrieSet {
+        TrieSet{map: TrieMap::new()}
+    }
+
+    /// Return true if the set contains a value
+    #[inline(always)]
+    fn contains(&self, value: &uint) -> bool {
+        self.map.contains_key(value)
+    }
+
+    /// Add a value to the set. Return true if the value was not already
+    /// present in the set.
+    #[inline(always)]
+    fn insert(&mut self, value: uint) -> bool { self.map.insert(value, ()) }
+
+    /// Remove a value from the set. Return true if the value was
+    /// present in the set.
+    #[inline(always)]
+    fn remove(&mut self, value: &uint) -> bool { self.map.remove(value) }
+}
+
+struct TrieNode<T> {
+    count: uint,
+    children: [Child<T>, ..SIZE]
+}
+
+impl<T> TrieNode<T> {
+    #[inline(always)]
+    fn new() -> TrieNode<T> {
+        // FIXME: #5244: [Nothing, ..SIZE] should be possible without Copy
+        TrieNode{count: 0,
+                 children: [Nothing, Nothing, Nothing, Nothing,
+                            Nothing, Nothing, Nothing, Nothing,
+                            Nothing, Nothing, Nothing, Nothing,
+                            Nothing, Nothing, Nothing, Nothing]}
+    }
+}
+
+impl<T> TrieNode<T> {
+    fn each<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
+        for uint::range(0, self.children.len()) |idx| {
+            match self.children[idx] {
+                Internal(ref x) => if !x.each(f) { return false },
+                External(k, ref v) => if !f(&k, v) { return false },
+                Nothing => ()
+            }
+        }
+        true
+    }
+
+    fn each_reverse<'a>(&'a self, f: &fn(&uint, &'a T) -> bool) -> bool {
+        for uint::range_rev(self.children.len(), 0) |idx| {
+            match self.children[idx - 1] {
+                Internal(ref x) => if !x.each_reverse(f) { return false },
+                External(k, ref v) => if !f(&k, v) { return false },
+                Nothing => ()
+            }
+        }
+        true
+    }
+
+    fn mutate_values<'a>(&'a mut self, f: &fn(&uint, &mut T) -> bool) -> bool {
+        for vec::each_mut(self.children) |child| {
+            match *child {
+                Internal(ref mut x) => if !x.mutate_values(f) {
+                    return false
+                },
+                External(k, ref mut v) => if !f(&k, v) { return false },
+                Nothing => ()
+            }
+        }
+        true
+    }
+}
+
+// if this was done via a trait, the key could be generic
+#[inline(always)]
+fn chunk(n: uint, idx: uint) -> uint {
+    let sh = uint::bits - (SHIFT * (idx + 1));
+    (n >> sh) & MASK
+}
+
+fn find_mut<'r, T>(child: &'r mut Child<T>, key: uint, idx: uint) -> Option<&'r mut T> {
+    match *child {
+        External(_, ref mut value) => Some(value),
+        Internal(ref mut x) => find_mut(&mut x.children[chunk(key, idx)], key, idx + 1),
+        Nothing => None
+    }
+}
+
+fn insert<T>(count: &mut uint, child: &mut Child<T>, key: uint, value: T,
+             idx: uint) -> Option<T> {
+    let mut tmp = Nothing;
+    let ret;
+    swap(&mut tmp, child);
+
+    *child = match tmp {
+      External(stored_key, stored_value) => {
+          if stored_key == key {
+              ret = Some(stored_value);
+              External(stored_key, value)
+          } else {
+              // conflict - split the node
+              let mut new = ~TrieNode::new();
+              insert(&mut new.count,
+                     &mut new.children[chunk(stored_key, idx)],
+                     stored_key, stored_value, idx + 1);
+              ret = insert(&mut new.count, &mut new.children[chunk(key, idx)],
+                           key, value, idx + 1);
+              Internal(new)
+          }
+      }
+      Internal(x) => {
+        let mut x = x;
+        ret = insert(&mut x.count, &mut x.children[chunk(key, idx)], key,
+                     value, idx + 1);
+        Internal(x)
+      }
+      Nothing => {
+        *count += 1;
+        ret = None;
+        External(key, value)
+      }
+    };
+    return ret;
+}
+
+fn remove<T>(count: &mut uint, child: &mut Child<T>, key: uint,
+             idx: uint) -> Option<T> {
+    let (ret, this) = match *child {
+      External(stored, _) if stored == key => {
+        match replace(child, Nothing) {
+            External(_, value) => (Some(value), true),
+            _ => fail!()
+        }
+      }
+      External(*) => (None, false),
+      Internal(ref mut x) => {
+          let ret = remove(&mut x.count, &mut x.children[chunk(key, idx)],
+                           key, idx + 1);
+          (ret, x.count == 0)
+      }
+      Nothing => (None, false)
+    };
+
+    if this {
+        *child = Nothing;
+        *count -= 1;
+    }
+    return ret;
+}
+
+#[cfg(test)]
+pub fn check_integrity<T>(trie: &TrieNode<T>) {
+    assert!(trie.count != 0);
+
+    let mut sum = 0;
+
+    for trie.children.each |x| {
+        match *x {
+          Nothing => (),
+          Internal(ref y) => {
+              check_integrity(&**y);
+              sum += 1
+          }
+          External(_, _) => { sum += 1 }
+        }
+    }
+
+    assert_eq!(sum, trie.count);
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use core::option::{Some, None};
+    use uint;
+
+    #[test]
+    fn test_find_mut() {
+        let mut m = TrieMap::new();
+        assert!(m.insert(1, 12));
+        assert!(m.insert(2, 8));
+        assert!(m.insert(5, 14));
+        let new = 100;
+        match m.find_mut(&5) {
+            None => fail!(), Some(x) => *x = new
+        }
+        assert_eq!(m.find(&5), Some(&new));
+    }
+
+    #[test]
+    fn test_step() {
+        let mut trie = TrieMap::new();
+        let n = 300;
+
+        for uint::range_step(1, n, 2) |x| {
+            assert!(trie.insert(x, x + 1));
+            assert!(trie.contains_key(&x));
+            check_integrity(&trie.root);
+        }
+
+        for uint::range_step(0, n, 2) |x| {
+            assert!(!trie.contains_key(&x));
+            assert!(trie.insert(x, x + 1));
+            check_integrity(&trie.root);
+        }
+
+        for uint::range(0, n) |x| {
+            assert!(trie.contains_key(&x));
+            assert!(!trie.insert(x, x + 1));
+            check_integrity(&trie.root);
+        }
+
+        for uint::range_step(1, n, 2) |x| {
+            assert!(trie.remove(&x));
+            assert!(!trie.contains_key(&x));
+            check_integrity(&trie.root);
+        }
+
+        for uint::range_step(0, n, 2) |x| {
+            assert!(trie.contains_key(&x));
+            assert!(!trie.insert(x, x + 1));
+            check_integrity(&trie.root);
+        }
+    }
+
+    #[test]
+    fn test_each() {
+        let mut m = TrieMap::new();
+
+        assert!(m.insert(3, 6));
+        assert!(m.insert(0, 0));
+        assert!(m.insert(4, 8));
+        assert!(m.insert(2, 4));
+        assert!(m.insert(1, 2));
+
+        let mut n = 0;
+        for m.each |k, v| {
+            assert_eq!(*k, n);
+            assert_eq!(*v, n * 2);
+            n += 1;
+        }
+    }
+
+    #[test]
+    fn test_each_break() {
+        let mut m = TrieMap::new();
+
+        for uint::range_rev(uint::max_value, uint::max_value - 10000) |x| {
+            m.insert(x, x / 2);
+        }
+
+        let mut n = uint::max_value - 9999;
+        for m.each |k, v| {
+            if n == uint::max_value - 5000 { break }
+            assert!(n < uint::max_value - 5000);
+
+            assert_eq!(*k, n);
+            assert_eq!(*v, n / 2);
+            n += 1;
+        }
+    }
+
+    #[test]
+    fn test_each_reverse() {
+        let mut m = TrieMap::new();
+
+        assert!(m.insert(3, 6));
+        assert!(m.insert(0, 0));
+        assert!(m.insert(4, 8));
+        assert!(m.insert(2, 4));
+        assert!(m.insert(1, 2));
+
+        let mut n = 4;
+        for m.each_reverse |k, v| {
+            assert_eq!(*k, n);
+            assert_eq!(*v, n * 2);
+            n -= 1;
+        }
+    }
+
+    #[test]
+    fn test_each_reverse_break() {
+        let mut m = TrieMap::new();
+
+        for uint::range_rev(uint::max_value, uint::max_value - 10000) |x| {
+            m.insert(x, x / 2);
+        }
+
+        let mut n = uint::max_value;
+        for m.each_reverse |k, v| {
+            if n == uint::max_value - 5000 { break }
+            assert!(n > uint::max_value - 5000);
+
+            assert_eq!(*k, n);
+            assert_eq!(*v, n / 2);
+            n -= 1;
+        }
+    }
+
+    #[test]
+    fn test_sane_chunk() {
+        let x = 1;
+        let y = 1 << (uint::bits - 1);
+
+        let mut trie = TrieSet::new();
+
+        assert!(trie.insert(x));
+        assert!(trie.insert(y));
+
+        assert_eq!(trie.len(), 2);
+
+        let expected = [x, y];
+
+        let mut i = 0;
+
+        for trie.each |x| {
+            assert_eq!(expected[i], *x);
+            i += 1;
+        }
+    }
+
+    #[test]
+    fn test_swap() {
+        let mut m = TrieMap::new();
+        assert_eq!(m.swap(1, 2), None);
+        assert_eq!(m.swap(1, 3), Some(2));
+        assert_eq!(m.swap(1, 4), Some(3));
+    }
+
+    #[test]
+    fn test_pop() {
+        let mut m = TrieMap::new();
+        m.insert(1, 2);
+        assert_eq!(m.pop(&1), Some(2));
+        assert_eq!(m.pop(&1), None);
+    }
+}
diff --git a/src/libstd/tuple.rs b/src/libstd/tuple.rs
new file mode 100644
index 00000000000..639df89a377
--- /dev/null
+++ b/src/libstd/tuple.rs
@@ -0,0 +1,439 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Operations on tuples
+
+use kinds::Copy;
+use vec;
+
+pub use self::inner::*;
+
+pub trait CopyableTuple<T, U> {
+    fn first(&self) -> T;
+    fn second(&self) -> U;
+    fn swap(&self) -> (U, T);
+}
+
+impl<T:Copy,U:Copy> CopyableTuple<T, U> for (T, U) {
+    /// Return the first element of self
+    #[inline(always)]
+    fn first(&self) -> T {
+        match *self {
+            (t, _) => t,
+        }
+    }
+
+    /// Return the second element of self
+    #[inline(always)]
+    fn second(&self) -> U {
+        match *self {
+            (_, u) => u,
+        }
+    }
+
+    /// Return the results of swapping the two elements of self
+    #[inline(always)]
+    fn swap(&self) -> (U, T) {
+        match *self {
+            (t, u) => (u, t),
+        }
+    }
+}
+
+pub trait ImmutableTuple<T, U> {
+    fn first_ref<'a>(&'a self) -> &'a T;
+    fn second_ref<'a>(&'a self) -> &'a U;
+}
+
+impl<T, U> ImmutableTuple<T, U> for (T, U) {
+    #[inline(always)]
+    fn first_ref<'a>(&'a self) -> &'a T {
+        match *self {
+            (ref t, _) => t,
+        }
+    }
+    #[inline(always)]
+    fn second_ref<'a>(&'a self) -> &'a U {
+        match *self {
+            (_, ref u) => u,
+        }
+    }
+}
+
+pub trait ExtendedTupleOps<A,B> {
+    fn zip(&self) -> ~[(A, B)];
+    fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C];
+}
+
+impl<'self,A:Copy,B:Copy> ExtendedTupleOps<A,B> for (&'self [A], &'self [B]) {
+    #[inline(always)]
+    fn zip(&self) -> ~[(A, B)] {
+        match *self {
+            (ref a, ref b) => {
+                vec::zip_slice(*a, *b)
+            }
+        }
+    }
+
+    #[inline(always)]
+    fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] {
+        match *self {
+            (ref a, ref b) => {
+                vec::map_zip(*a, *b, f)
+            }
+        }
+    }
+}
+
+impl<A:Copy,B:Copy> ExtendedTupleOps<A,B> for (~[A], ~[B]) {
+    #[inline(always)]
+    fn zip(&self) -> ~[(A, B)] {
+        match *self {
+            (ref a, ref b) => {
+                vec::zip_slice(*a, *b)
+            }
+        }
+    }
+
+    #[inline(always)]
+    fn map<C>(&self, f: &fn(a: &A, b: &B) -> C) -> ~[C] {
+        match *self {
+            (ref a, ref b) => {
+                vec::map_zip(*a, *b, f)
+            }
+        }
+    }
+}
+
+// macro for implementing n-ary tuple functions and operations
+
+macro_rules! tuple_impls {
+    ($(
+        ($cloneable_trait:ident, $immutable_trait:ident) {
+            $(($get_fn:ident, $get_ref_fn:ident) -> $T:ident {
+                $get_pattern:pat => $ret:expr
+            })+
+        }
+    )+) => {
+        pub mod inner {
+            use clone::Clone;
+            #[cfg(not(test))] use cmp::*;
+
+            $(
+                pub trait $cloneable_trait<$($T),+> {
+                    $(fn $get_fn(&self) -> $T;)+
+                }
+
+                impl<$($T:Clone),+> $cloneable_trait<$($T),+> for ($($T),+) {
+                    $(
+                        #[inline(always)]
+                        fn $get_fn(&self) -> $T {
+                            self.$get_ref_fn().clone()
+                        }
+                    )+
+                }
+
+                pub trait $immutable_trait<$($T),+> {
+                    $(fn $get_ref_fn<'a>(&'a self) -> &'a $T;)+
+                }
+
+                impl<$($T),+> $immutable_trait<$($T),+> for ($($T),+) {
+                    $(
+                        #[inline(always)]
+                        fn $get_ref_fn<'a>(&'a self) -> &'a $T {
+                            match *self { $get_pattern => $ret }
+                        }
+                    )+
+                }
+
+                impl<$($T:Clone),+> Clone for ($($T),+) {
+                    fn clone(&self) -> ($($T),+) {
+                        ($(self.$get_ref_fn().clone()),+)
+                    }
+                }
+
+                #[cfg(not(test))]
+                impl<$($T:Eq),+> Eq for ($($T),+) {
+                    #[inline(always)]
+                    fn eq(&self, other: &($($T),+)) -> bool {
+                        $(*self.$get_ref_fn() == *other.$get_ref_fn())&&+
+                    }
+                    #[inline(always)]
+                    fn ne(&self, other: &($($T),+)) -> bool {
+                        !(*self == *other)
+                    }
+                }
+
+                #[cfg(not(test))]
+                impl<$($T:TotalEq),+> TotalEq for ($($T),+) {
+                    #[inline(always)]
+                    fn equals(&self, other: &($($T),+)) -> bool {
+                        $(self.$get_ref_fn().equals(other.$get_ref_fn()))&&+
+                    }
+                }
+
+                #[cfg(not(test))]
+                impl<$($T:Ord),+> Ord for ($($T),+) {
+                    #[inline(always)]
+                    fn lt(&self, other: &($($T),+)) -> bool {
+                        lexical_lt!($(self.$get_ref_fn(), other.$get_ref_fn()),+)
+                    }
+                    #[inline(always)]
+                    fn le(&self, other: &($($T),+)) -> bool { !(*other).lt(&(*self)) }
+                    #[inline(always)]
+                    fn ge(&self, other: &($($T),+)) -> bool { !(*self).lt(other) }
+                    #[inline(always)]
+                    fn gt(&self, other: &($($T),+)) -> bool { (*other).lt(&(*self)) }
+                }
+
+                #[cfg(not(test))]
+                impl<$($T:TotalOrd),+> TotalOrd for ($($T),+) {
+                    #[inline]
+                    fn cmp(&self, other: &($($T),+)) -> Ordering {
+                        lexical_cmp!($(self.$get_ref_fn(), other.$get_ref_fn()),+)
+                    }
+                }
+            )+
+        }
+    }
+}
+
+// Constructs an expression that performs a lexical less-than
+// ordering.  The values are interleaved, so the macro invocation for
+// `(a1, a2, a3) < (b1, b2, b3)` would be `lexical_lt!(a1, b1, a2, b2,
+// a3, b3)` (and similarly for `lexical_cmp`)
+macro_rules! lexical_lt {
+    ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
+        if *$a < *$b { true }
+        else if !(*$b < *$a) { lexical_lt!($($rest_a, $rest_b),+) }
+        else { false }
+    };
+    ($a:expr, $b:expr) => { *$a < *$b };
+}
+
+macro_rules! lexical_cmp {
+    ($a:expr, $b:expr, $($rest_a:expr, $rest_b:expr),+) => {
+        match ($a).cmp($b) {
+            Equal => lexical_cmp!($($rest_a, $rest_b),+),
+            ordering   => ordering
+        }
+    };
+    ($a:expr, $b:expr) => { ($a).cmp($b) };
+}
+
+
+tuple_impls! {
+    (CloneableTuple2, ImmutableTuple2) {
+        (n0, n0_ref) -> A { (ref a,_) => a }
+        (n1, n1_ref) -> B { (_,ref b) => b }
+    }
+
+    (CloneableTuple3, ImmutableTuple3) {
+        (n0, n0_ref) -> A { (ref a,_,_) => a }
+        (n1, n1_ref) -> B { (_,ref b,_) => b }
+        (n2, n2_ref) -> C { (_,_,ref c) => c }
+    }
+
+    (CloneableTuple4, ImmutableTuple4) {
+        (n0, n0_ref) -> A { (ref a,_,_,_) => a }
+        (n1, n1_ref) -> B { (_,ref b,_,_) => b }
+        (n2, n2_ref) -> C { (_,_,ref c,_) => c }
+        (n3, n3_ref) -> D { (_,_,_,ref d) => d }
+    }
+
+    (CloneableTuple5, ImmutableTuple5) {
+        (n0, n0_ref) -> A { (ref a,_,_,_,_) => a }
+        (n1, n1_ref) -> B { (_,ref b,_,_,_) => b }
+        (n2, n2_ref) -> C { (_,_,ref c,_,_) => c }
+        (n3, n3_ref) -> D { (_,_,_,ref d,_) => d }
+        (n4, n4_ref) -> E { (_,_,_,_,ref e) => e }
+    }
+
+    (CloneableTuple6, ImmutableTuple6) {
+        (n0, n0_ref) -> A { (ref a,_,_,_,_,_) => a }
+        (n1, n1_ref) -> B { (_,ref b,_,_,_,_) => b }
+        (n2, n2_ref) -> C { (_,_,ref c,_,_,_) => c }
+        (n3, n3_ref) -> D { (_,_,_,ref d,_,_) => d }
+        (n4, n4_ref) -> E { (_,_,_,_,ref e,_) => e }
+        (n5, n5_ref) -> F { (_,_,_,_,_,ref f) => f }
+    }
+
+    (CloneableTuple7, ImmutableTuple7) {
+        (n0, n0_ref) -> A { (ref a,_,_,_,_,_,_) => a }
+        (n1, n1_ref) -> B { (_,ref b,_,_,_,_,_) => b }
+        (n2, n2_ref) -> C { (_,_,ref c,_,_,_,_) => c }
+        (n3, n3_ref) -> D { (_,_,_,ref d,_,_,_) => d }
+        (n4, n4_ref) -> E { (_,_,_,_,ref e,_,_) => e }
+        (n5, n5_ref) -> F { (_,_,_,_,_,ref f,_) => f }
+        (n6, n6_ref) -> G { (_,_,_,_,_,_,ref g) => g }
+    }
+
+    (CloneableTuple8, ImmutableTuple8) {
+        (n0, n0_ref) -> A { (ref a,_,_,_,_,_,_,_) => a }
+        (n1, n1_ref) -> B { (_,ref b,_,_,_,_,_,_) => b }
+        (n2, n2_ref) -> C { (_,_,ref c,_,_,_,_,_) => c }
+        (n3, n3_ref) -> D { (_,_,_,ref d,_,_,_,_) => d }
+        (n4, n4_ref) -> E { (_,_,_,_,ref e,_,_,_) => e }
+        (n5, n5_ref) -> F { (_,_,_,_,_,ref f,_,_) => f }
+        (n6, n6_ref) -> G { (_,_,_,_,_,_,ref g,_) => g }
+        (n7, n7_ref) -> H { (_,_,_,_,_,_,_,ref h) => h }
+    }
+
+    (CloneableTuple9, ImmutableTuple9) {
+        (n0, n0_ref) -> A { (ref a,_,_,_,_,_,_,_,_) => a }
+        (n1, n1_ref) -> B { (_,ref b,_,_,_,_,_,_,_) => b }
+        (n2, n2_ref) -> C { (_,_,ref c,_,_,_,_,_,_) => c }
+        (n3, n3_ref) -> D { (_,_,_,ref d,_,_,_,_,_) => d }
+        (n4, n4_ref) -> E { (_,_,_,_,ref e,_,_,_,_) => e }
+        (n5, n5_ref) -> F { (_,_,_,_,_,ref f,_,_,_) => f }
+        (n6, n6_ref) -> G { (_,_,_,_,_,_,ref g,_,_) => g }
+        (n7, n7_ref) -> H { (_,_,_,_,_,_,_,ref h,_) => h }
+        (n8, n8_ref) -> I { (_,_,_,_,_,_,_,_,ref i) => i }
+    }
+
+    (CloneableTuple10, ImmutableTuple10) {
+        (n0, n0_ref) -> A { (ref a,_,_,_,_,_,_,_,_,_) => a }
+        (n1, n1_ref) -> B { (_,ref b,_,_,_,_,_,_,_,_) => b }
+        (n2, n2_ref) -> C { (_,_,ref c,_,_,_,_,_,_,_) => c }
+        (n3, n3_ref) -> D { (_,_,_,ref d,_,_,_,_,_,_) => d }
+        (n4, n4_ref) -> E { (_,_,_,_,ref e,_,_,_,_,_) => e }
+        (n5, n5_ref) -> F { (_,_,_,_,_,ref f,_,_,_,_) => f }
+        (n6, n6_ref) -> G { (_,_,_,_,_,_,ref g,_,_,_) => g }
+        (n7, n7_ref) -> H { (_,_,_,_,_,_,_,ref h,_,_) => h }
+        (n8, n8_ref) -> I { (_,_,_,_,_,_,_,_,ref i,_) => i }
+        (n9, n9_ref) -> J { (_,_,_,_,_,_,_,_,_,ref j) => j }
+    }
+
+    (CloneableTuple11, ImmutableTuple11) {
+        (n0,  n0_ref)  -> A { (ref a,_,_,_,_,_,_,_,_,_,_) => a }
+        (n1,  n1_ref)  -> B { (_,ref b,_,_,_,_,_,_,_,_,_) => b }
+        (n2,  n2_ref)  -> C { (_,_,ref c,_,_,_,_,_,_,_,_) => c }
+        (n3,  n3_ref)  -> D { (_,_,_,ref d,_,_,_,_,_,_,_) => d }
+        (n4,  n4_ref)  -> E { (_,_,_,_,ref e,_,_,_,_,_,_) => e }
+        (n5,  n5_ref)  -> F { (_,_,_,_,_,ref f,_,_,_,_,_) => f }
+        (n6,  n6_ref)  -> G { (_,_,_,_,_,_,ref g,_,_,_,_) => g }
+        (n7,  n7_ref)  -> H { (_,_,_,_,_,_,_,ref h,_,_,_) => h }
+        (n8,  n8_ref)  -> I { (_,_,_,_,_,_,_,_,ref i,_,_) => i }
+        (n9,  n9_ref)  -> J { (_,_,_,_,_,_,_,_,_,ref j,_) => j }
+        (n10, n10_ref) -> K { (_,_,_,_,_,_,_,_,_,_,ref k) => k }
+    }
+
+    (CloneableTuple12, ImmutableTuple12) {
+        (n0,  n0_ref)  -> A { (ref a,_,_,_,_,_,_,_,_,_,_,_) => a }
+        (n1,  n1_ref)  -> B { (_,ref b,_,_,_,_,_,_,_,_,_,_) => b }
+        (n2,  n2_ref)  -> C { (_,_,ref c,_,_,_,_,_,_,_,_,_) => c }
+        (n3,  n3_ref)  -> D { (_,_,_,ref d,_,_,_,_,_,_,_,_) => d }
+        (n4,  n4_ref)  -> E { (_,_,_,_,ref e,_,_,_,_,_,_,_) => e }
+        (n5,  n5_ref)  -> F { (_,_,_,_,_,ref f,_,_,_,_,_,_) => f }
+        (n6,  n6_ref)  -> G { (_,_,_,_,_,_,ref g,_,_,_,_,_) => g }
+        (n7,  n7_ref)  -> H { (_,_,_,_,_,_,_,ref h,_,_,_,_) => h }
+        (n8,  n8_ref)  -> I { (_,_,_,_,_,_,_,_,ref i,_,_,_) => i }
+        (n9,  n9_ref)  -> J { (_,_,_,_,_,_,_,_,_,ref j,_,_) => j }
+        (n10, n10_ref) -> K { (_,_,_,_,_,_,_,_,_,_,ref k,_) => k }
+        (n11, n11_ref) -> L { (_,_,_,_,_,_,_,_,_,_,_,ref l) => l }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use clone::Clone;
+    use cmp::*;
+
+    #[test]
+    fn test_tuple_ref() {
+        let x = (~"foo", ~"bar");
+        assert_eq!(x.first_ref(), &~"foo");
+        assert_eq!(x.second_ref(), &~"bar");
+    }
+
+    #[test]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_tuple() {
+        assert_eq!((948, 4039.48).first(), 948);
+        assert_eq!((34.5, ~"foo").second(), ~"foo");
+        assert_eq!(('a', 2).swap(), (2, 'a'));
+    }
+
+    #[test]
+    fn test_clone() {
+        let a = (1, ~"2");
+        let b = a.clone();
+        assert_eq!(a.first(), b.first());
+        assert_eq!(a.second(), b.second());
+    }
+
+    #[test]
+    fn test_n_tuple() {
+        let t = (0u8, 1u16, 2u32, 3u64, 4u, 5i8, 6i16, 7i32, 8i64, 9i, 10f32, 11f64);
+        assert_eq!(t.n0(), 0u8);
+        assert_eq!(t.n1(), 1u16);
+        assert_eq!(t.n2(), 2u32);
+        assert_eq!(t.n3(), 3u64);
+        assert_eq!(t.n4(), 4u);
+        assert_eq!(t.n5(), 5i8);
+        assert_eq!(t.n6(), 6i16);
+        assert_eq!(t.n7(), 7i32);
+        assert_eq!(t.n8(), 8i64);
+        assert_eq!(t.n9(), 9i);
+        assert_eq!(t.n10(), 10f32);
+        assert_eq!(t.n11(), 11f64);
+
+        assert_eq!(t.n0_ref(), &0u8);
+        assert_eq!(t.n1_ref(), &1u16);
+        assert_eq!(t.n2_ref(), &2u32);
+        assert_eq!(t.n3_ref(), &3u64);
+        assert_eq!(t.n4_ref(), &4u);
+        assert_eq!(t.n5_ref(), &5i8);
+        assert_eq!(t.n6_ref(), &6i16);
+        assert_eq!(t.n7_ref(), &7i32);
+        assert_eq!(t.n8_ref(), &8i64);
+        assert_eq!(t.n9_ref(), &9i);
+        assert_eq!(t.n10_ref(), &10f32);
+        assert_eq!(t.n11_ref(), &11f64);
+    }
+
+    #[test]
+    fn test_tuple_cmp() {
+        let small = (1u, 2u, 3u), big = (3u, 2u, 1u);
+
+        // Eq
+        assert_eq!(small, small);
+        assert_eq!(big, big);
+        assert!(small != big);
+        assert!(big != small);
+
+        // Ord
+        assert!(small < big);
+        assert!(!(small < small));
+        assert!(!(big < small));
+        assert!(!(big < big));
+
+        assert!(small <= small);
+        assert!(big <= big);
+
+        assert!(big > small);
+        assert!(small >= small);
+        assert!(big >= small);
+        assert!(big >= big);
+
+        // TotalEq
+        assert!(small.equals(&small));
+        assert!(big.equals(&big));
+        assert!(!small.equals(&big));
+        assert!(!big.equals(&small));
+
+        // TotalOrd
+        assert_eq!(small.cmp(&small), Equal);
+        assert_eq!(big.cmp(&big), Equal);
+        assert_eq!(small.cmp(&big), Less);
+        assert_eq!(big.cmp(&small), Greater);
+    }
+}
diff --git a/src/libstd/unicode.rs b/src/libstd/unicode.rs
index 77996de6d83..d6e2c5eee6a 100644
--- a/src/libstd/unicode.rs
+++ b/src/libstd/unicode.rs
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,241 +8,2637 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[forbid(deprecated_mode)];
-
-pub mod icu {
-    pub type UBool = u8;
-    pub type UProperty = int;
-    pub type UChar32 = char;
-
-    pub static TRUE : u8 = 1u8;
-    pub static FALSE : u8 = 1u8;
-
-    pub static UCHAR_ALPHABETIC : UProperty = 0;
-    pub static UCHAR_BINARY_START : UProperty = 0; // = UCHAR_ALPHABETIC
-    pub static UCHAR_ASCII_HEX_DIGIT : UProperty = 1;
-    pub static UCHAR_BIDI_CONTROL : UProperty = 2;
-
-    pub static UCHAR_BIDI_MIRRORED : UProperty = 3;
-    pub static UCHAR_DASH : UProperty = 4;
-    pub static UCHAR_DEFAULT_IGNORABLE_CODE_POINT : UProperty = 5;
-    pub static UCHAR_DEPRECATED : UProperty = 6;
-
-    pub static UCHAR_DIACRITIC : UProperty = 7;
-    pub static UCHAR_EXTENDER : UProperty = 8;
-    pub static UCHAR_FULL_COMPOSITION_EXCLUSION : UProperty = 9;
-    pub static UCHAR_GRAPHEME_BASE : UProperty = 10;
-
-    pub static UCHAR_GRAPHEME_EXTEND : UProperty = 11;
-    pub static UCHAR_GRAPHEME_LINK : UProperty = 12;
-    pub static UCHAR_HEX_DIGIT : UProperty = 13;
-    pub static UCHAR_HYPHEN : UProperty = 14;
-
-    pub static UCHAR_ID_CONTINUE : UProperty = 15;
-    pub static UCHAR_ID_START : UProperty = 16;
-    pub static UCHAR_IDEOGRAPHIC : UProperty = 17;
-    pub static UCHAR_IDS_BINARY_OPERATOR : UProperty = 18;
-
-    pub static UCHAR_IDS_TRINARY_OPERATOR : UProperty = 19;
-    pub static UCHAR_JOIN_CONTROL : UProperty = 20;
-    pub static UCHAR_LOGICAL_ORDER_EXCEPTION : UProperty = 21;
-    pub static UCHAR_LOWERCASE : UProperty = 22;
-
-    pub static UCHAR_MATH : UProperty = 23;
-    pub static UCHAR_NONCHARACTER_CODE_POINT : UProperty = 24;
-    pub static UCHAR_QUOTATION_MARK : UProperty = 25;
-    pub static UCHAR_RADICAL : UProperty = 26;
-
-    pub static UCHAR_SOFT_DOTTED : UProperty = 27;
-    pub static UCHAR_TERMINAL_PUNCTUATION : UProperty = 28;
-    pub static UCHAR_UNIFIED_IDEOGRAPH : UProperty = 29;
-    pub static UCHAR_UPPERCASE : UProperty = 30;
-
-    pub static UCHAR_WHITE_SPACE : UProperty = 31;
-    pub static UCHAR_XID_CONTINUE : UProperty = 32;
-    pub static UCHAR_XID_START : UProperty = 33;
-    pub static UCHAR_CASE_SENSITIVE : UProperty = 34;
-
-    pub static UCHAR_S_TERM : UProperty = 35;
-    pub static UCHAR_VARIATION_SELECTOR : UProperty = 36;
-    pub static UCHAR_NFD_INERT : UProperty = 37;
-    pub static UCHAR_NFKD_INERT : UProperty = 38;
-
-    pub static UCHAR_NFC_INERT : UProperty = 39;
-    pub static UCHAR_NFKC_INERT : UProperty = 40;
-    pub static UCHAR_SEGMENT_STARTER : UProperty = 41;
-    pub static UCHAR_PATTERN_SYNTAX : UProperty = 42;
-
-    pub static UCHAR_PATTERN_WHITE_SPACE : UProperty = 43;
-    pub static UCHAR_POSIX_ALNUM : UProperty = 44;
-    pub static UCHAR_POSIX_BLANK : UProperty = 45;
-    pub static UCHAR_POSIX_GRAPH : UProperty = 46;
-
-    pub static UCHAR_POSIX_PRINT : UProperty = 47;
-    pub static UCHAR_POSIX_XDIGIT : UProperty = 48;
-    pub static UCHAR_CASED : UProperty = 49;
-    pub static UCHAR_CASE_IGNORABLE : UProperty = 50;
-
-    pub static UCHAR_CHANGES_WHEN_LOWERCASED : UProperty = 51;
-    pub static UCHAR_CHANGES_WHEN_UPPERCASED : UProperty = 52;
-    pub static UCHAR_CHANGES_WHEN_TITLECASED : UProperty = 53;
-    pub static UCHAR_CHANGES_WHEN_CASEFOLDED : UProperty = 54;
-
-    pub static UCHAR_CHANGES_WHEN_CASEMAPPED : UProperty = 55;
-    pub static UCHAR_CHANGES_WHEN_NFKC_CASEFOLDED : UProperty = 56;
-    pub static UCHAR_BINARY_LIMIT : UProperty = 57;
-    pub static UCHAR_BIDI_CLASS : UProperty = 0x1000;
-
-    pub static UCHAR_INT_START : UProperty = 0x1000; // UCHAR_BIDI_CLASS
-    pub static UCHAR_BLOCK : UProperty = 0x1001;
-    pub static UCHAR_CANONICAL_COMBINING_CLASS : UProperty = 0x1002;
-    pub static UCHAR_DECOMPOSITION_TYPE : UProperty = 0x1003;
-
-    pub static UCHAR_EAST_ASIAN_WIDTH : UProperty = 0x1004;
-    pub static UCHAR_GENERAL_CATEGORY : UProperty = 0x1005;
-    pub static UCHAR_JOINING_GROUP : UProperty = 0x1006;
-    pub static UCHAR_JOINING_TYPE : UProperty = 0x1007;
-
-    pub static UCHAR_LINE_BREAK : UProperty = 0x1008;
-    pub static UCHAR_NUMERIC_TYPE : UProperty = 0x1009;
-    pub static UCHAR_SCRIPT : UProperty = 0x100A;
-    pub static UCHAR_HANGUL_SYLLABLE_TYPE : UProperty = 0x100B;
-
-    pub static UCHAR_NFD_QUICK_CHECK : UProperty = 0x100C;
-    pub static UCHAR_NFKD_QUICK_CHECK : UProperty = 0x100D;
-    pub static UCHAR_NFC_QUICK_CHECK : UProperty = 0x100E;
-    pub static UCHAR_NFKC_QUICK_CHECK : UProperty = 0x100F;
-
-    pub static UCHAR_LEAD_CANONICAL_COMBINING_CLASS : UProperty = 0x1010;
-    pub static UCHAR_TRAIL_CANONICAL_COMBINING_CLASS : UProperty = 0x1011;
-    pub static UCHAR_GRAPHEME_CLUSTER_BREAK : UProperty = 0x1012;
-    pub static UCHAR_SENTENCE_BREAK : UProperty = 0x1013;
-
-    pub static UCHAR_WORD_BREAK : UProperty = 0x1014;
-    pub static UCHAR_INT_LIMIT : UProperty = 0x1015;
-
-    pub static UCHAR_GENERAL_CATEGORY_MASK : UProperty = 0x2000;
-    pub static UCHAR_MASK_START : UProperty = 0x2000;
-    // = UCHAR_GENERAL_CATEGORY_MASK
-    pub static UCHAR_MASK_LIMIT : UProperty = 0x2001;
-
-    pub static UCHAR_NUMERIC_VALUE : UProperty = 0x3000;
-    pub static UCHAR_DOUBLE_START : UProperty = 0x3000;
-    // = UCHAR_NUMERIC_VALUE
-    pub static UCHAR_DOUBLE_LIMIT : UProperty = 0x3001;
-
-    pub static UCHAR_AGE : UProperty = 0x4000;
-    pub static UCHAR_STRING_START : UProperty = 0x4000; // = UCHAR_AGE
-    pub static UCHAR_BIDI_MIRRORING_GLYPH : UProperty = 0x4001;
-    pub static UCHAR_CASE_FOLDING : UProperty = 0x4002;
-
-    pub static UCHAR_ISO_COMMENT : UProperty = 0x4003;
-    pub static UCHAR_LOWERCASE_MAPPING : UProperty = 0x4004;
-    pub static UCHAR_NAME : UProperty = 0x4005;
-    pub static UCHAR_SIMPLE_CASE_FOLDING : UProperty = 0x4006;
-
-    pub static UCHAR_SIMPLE_LOWERCASE_MAPPING : UProperty = 0x4007;
-    pub static UCHAR_SIMPLE_TITLECASE_MAPPING : UProperty = 0x4008;
-    pub static UCHAR_SIMPLE_UPPERCASE_MAPPING : UProperty = 0x4009;
-    pub static UCHAR_TITLECASE_MAPPING : UProperty = 0x400A;
-
-    pub static UCHAR_UNICODE_1_NAME : UProperty = 0x400B;
-    pub static UCHAR_UPPERCASE_MAPPING : UProperty = 0x400C;
-    pub static UCHAR_STRING_LIMIT : UProperty = 0x400D;
-
-    pub static UCHAR_SCRIPT_EXTENSIONS : UProperty = 0x7000;
-    pub static UCHAR_OTHER_PROPERTY_START : UProperty = 0x7000;
-    // = UCHAR_SCRIPT_EXTENSIONS;
-    pub static UCHAR_OTHER_PROPERTY_LIMIT : UProperty = 0x7001;
-
-    pub static UCHAR_INVALID_CODE : UProperty = -1;
-
-    pub mod libicu {
-        #[link_name = "icuuc"]
-        #[abi = "cdecl"]
-        pub extern {
-            unsafe fn u_hasBinaryProperty(c: UChar32, which: UProperty)
-                                       -> UBool;
-            unsafe fn u_isdigit(c: UChar32) -> UBool;
-            unsafe fn u_islower(c: UChar32) -> UBool;
-            unsafe fn u_isspace(c: UChar32) -> UBool;
-            unsafe fn u_isupper(c: UChar32) -> UBool;
-            unsafe fn u_tolower(c: UChar32) -> UChar32;
-            unsafe fn u_toupper(c: UChar32) -> UChar32;
-        }
+#[doc(hidden)]; // FIXME #3538
+
+// The following code was generated by "src/etc/unicode.py"
+
+pub mod general_category {
+
+    fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
+        use cmp::{Equal, Less, Greater};
+        use vec::bsearch;
+        use option::None;
+        (do bsearch(r) |&(lo,hi)| {
+            if lo <= c && c <= hi { Equal }
+            else if hi < c { Less }
+            else { Greater }
+        }) != None
     }
-}
 
-pub fn is_XID_start(c: char) -> bool {
-    return icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START)
-        == icu::TRUE;
-}
 
-pub fn is_XID_continue(c: char) -> bool {
-    return icu::libicu::u_hasBinaryProperty(c, icu::UCHAR_XID_START)
-        == icu::TRUE;
-}
+    static Cc_table : &'static [(char,char)] = &[
+        ('\x00', '\x1f'), ('\x7f', '\x9f')
+    ];
 
-/*
-Function: is_digit
+    pub fn Cc(c: char) -> bool {
+        bsearch_range_table(c, Cc_table)
+    }
 
-Returns true if a character is a digit.
-*/
-pub fn is_digit(c: char) -> bool {
-    return icu::libicu::u_isdigit(c) == icu::TRUE;
-}
+    static Cf_table : &'static [(char,char)] = &[
+        ('\xad', '\xad'), ('\u0600', '\u0604'),
+        ('\u06dd', '\u06dd'), ('\u070f', '\u070f'),
+        ('\u200b', '\u200f'), ('\u202a', '\u202e'),
+        ('\u2060', '\u206f'), ('\ufeff', '\ufeff'),
+        ('\ufff9', '\ufffb'), ('\U000110bd', '\U000110bd'),
+        ('\U0001d173', '\U0001d17a'), ('\U000e0001', '\U000e007f')
+    ];
 
-/*
-Function: is_lower
+    pub fn Cf(c: char) -> bool {
+        bsearch_range_table(c, Cf_table)
+    }
 
-Returns true if a character is a lowercase letter.
-*/
-pub fn is_lower(c: char) -> bool {
-    return icu::libicu::u_islower(c) == icu::TRUE;
-}
+    static Co_table : &'static [(char,char)] = &[
+        ('\ue000', '\uf8ff')
+    ];
 
-/*
-Function: is_space
+    pub fn Co(c: char) -> bool {
+        bsearch_range_table(c, Co_table)
+    }
 
-Returns true if a character is space.
-*/
-pub fn is_space(c: char) -> bool {
-    return icu::libicu::u_isspace(c) == icu::TRUE;
-}
+    static Cs_table : &'static [(char,char)] = &[
+        ('\ud800', '\udfff')
+    ];
+
+    pub fn Cs(c: char) -> bool {
+        bsearch_range_table(c, Cs_table)
+    }
+
+    static Ll_table : &'static [(char,char)] = &[
+        ('\x61', '\x7a'), ('\xb5', '\xb5'),
+        ('\xdf', '\xf6'), ('\xf8', '\xff'),
+        ('\u0101', '\u0101'), ('\u0103', '\u0103'),
+        ('\u0105', '\u0105'), ('\u0107', '\u0107'),
+        ('\u0109', '\u0109'), ('\u010b', '\u010b'),
+        ('\u010d', '\u010d'), ('\u010f', '\u010f'),
+        ('\u0111', '\u0111'), ('\u0113', '\u0113'),
+        ('\u0115', '\u0115'), ('\u0117', '\u0117'),
+        ('\u0119', '\u0119'), ('\u011b', '\u011b'),
+        ('\u011d', '\u011d'), ('\u011f', '\u011f'),
+        ('\u0121', '\u0121'), ('\u0123', '\u0123'),
+        ('\u0125', '\u0125'), ('\u0127', '\u0127'),
+        ('\u0129', '\u0129'), ('\u012b', '\u012b'),
+        ('\u012d', '\u012d'), ('\u012f', '\u012f'),
+        ('\u0131', '\u0131'), ('\u0133', '\u0133'),
+        ('\u0135', '\u0135'), ('\u0137', '\u0138'),
+        ('\u013a', '\u013a'), ('\u013c', '\u013c'),
+        ('\u013e', '\u013e'), ('\u0140', '\u0140'),
+        ('\u0142', '\u0142'), ('\u0144', '\u0144'),
+        ('\u0146', '\u0146'), ('\u0148', '\u0149'),
+        ('\u014b', '\u014b'), ('\u014d', '\u014d'),
+        ('\u014f', '\u014f'), ('\u0151', '\u0151'),
+        ('\u0153', '\u0153'), ('\u0155', '\u0155'),
+        ('\u0157', '\u0157'), ('\u0159', '\u0159'),
+        ('\u015b', '\u015b'), ('\u015d', '\u015d'),
+        ('\u015f', '\u015f'), ('\u0161', '\u0161'),
+        ('\u0163', '\u0163'), ('\u0165', '\u0165'),
+        ('\u0167', '\u0167'), ('\u0169', '\u0169'),
+        ('\u016b', '\u016b'), ('\u016d', '\u016d'),
+        ('\u016f', '\u016f'), ('\u0171', '\u0171'),
+        ('\u0173', '\u0173'), ('\u0175', '\u0175'),
+        ('\u0177', '\u0177'), ('\u017a', '\u017a'),
+        ('\u017c', '\u017c'), ('\u017e', '\u0180'),
+        ('\u0183', '\u0183'), ('\u0185', '\u0185'),
+        ('\u0188', '\u0188'), ('\u018c', '\u018d'),
+        ('\u0192', '\u0192'), ('\u0195', '\u0195'),
+        ('\u0199', '\u019b'), ('\u019e', '\u019e'),
+        ('\u01a1', '\u01a1'), ('\u01a3', '\u01a3'),
+        ('\u01a5', '\u01a5'), ('\u01a8', '\u01a8'),
+        ('\u01aa', '\u01ab'), ('\u01ad', '\u01ad'),
+        ('\u01b0', '\u01b0'), ('\u01b4', '\u01b4'),
+        ('\u01b6', '\u01b6'), ('\u01b9', '\u01ba'),
+        ('\u01bd', '\u01bf'), ('\u01c6', '\u01c6'),
+        ('\u01c9', '\u01c9'), ('\u01cc', '\u01cc'),
+        ('\u01ce', '\u01ce'), ('\u01d0', '\u01d0'),
+        ('\u01d2', '\u01d2'), ('\u01d4', '\u01d4'),
+        ('\u01d6', '\u01d6'), ('\u01d8', '\u01d8'),
+        ('\u01da', '\u01da'), ('\u01dc', '\u01dd'),
+        ('\u01df', '\u01df'), ('\u01e1', '\u01e1'),
+        ('\u01e3', '\u01e3'), ('\u01e5', '\u01e5'),
+        ('\u01e7', '\u01e7'), ('\u01e9', '\u01e9'),
+        ('\u01eb', '\u01eb'), ('\u01ed', '\u01ed'),
+        ('\u01ef', '\u01f0'), ('\u01f3', '\u01f3'),
+        ('\u01f5', '\u01f5'), ('\u01f9', '\u01f9'),
+        ('\u01fb', '\u01fb'), ('\u01fd', '\u01fd'),
+        ('\u01ff', '\u01ff'), ('\u0201', '\u0201'),
+        ('\u0203', '\u0203'), ('\u0205', '\u0205'),
+        ('\u0207', '\u0207'), ('\u0209', '\u0209'),
+        ('\u020b', '\u020b'), ('\u020d', '\u020d'),
+        ('\u020f', '\u020f'), ('\u0211', '\u0211'),
+        ('\u0213', '\u0213'), ('\u0215', '\u0215'),
+        ('\u0217', '\u0217'), ('\u0219', '\u0219'),
+        ('\u021b', '\u021b'), ('\u021d', '\u021d'),
+        ('\u021f', '\u021f'), ('\u0221', '\u0221'),
+        ('\u0223', '\u0223'), ('\u0225', '\u0225'),
+        ('\u0227', '\u0227'), ('\u0229', '\u0229'),
+        ('\u022b', '\u022b'), ('\u022d', '\u022d'),
+        ('\u022f', '\u022f'), ('\u0231', '\u0231'),
+        ('\u0233', '\u0239'), ('\u023c', '\u023c'),
+        ('\u023f', '\u0240'), ('\u0242', '\u0242'),
+        ('\u0247', '\u0247'), ('\u0249', '\u0249'),
+        ('\u024b', '\u024b'), ('\u024d', '\u024d'),
+        ('\u024f', '\u0293'), ('\u0295', '\u02af'),
+        ('\u0371', '\u0371'), ('\u0373', '\u0373'),
+        ('\u0377', '\u0377'), ('\u037b', '\u037d'),
+        ('\u0390', '\u0390'), ('\u03ac', '\u03ce'),
+        ('\u03d0', '\u03d1'), ('\u03d5', '\u03d7'),
+        ('\u03d9', '\u03d9'), ('\u03db', '\u03db'),
+        ('\u03dd', '\u03dd'), ('\u03df', '\u03df'),
+        ('\u03e1', '\u03e1'), ('\u03e3', '\u03e3'),
+        ('\u03e5', '\u03e5'), ('\u03e7', '\u03e7'),
+        ('\u03e9', '\u03e9'), ('\u03eb', '\u03eb'),
+        ('\u03ed', '\u03ed'), ('\u03ef', '\u03f3'),
+        ('\u03f5', '\u03f5'), ('\u03f8', '\u03f8'),
+        ('\u03fb', '\u03fc'), ('\u0430', '\u045f'),
+        ('\u0461', '\u0461'), ('\u0463', '\u0463'),
+        ('\u0465', '\u0465'), ('\u0467', '\u0467'),
+        ('\u0469', '\u0469'), ('\u046b', '\u046b'),
+        ('\u046d', '\u046d'), ('\u046f', '\u046f'),
+        ('\u0471', '\u0471'), ('\u0473', '\u0473'),
+        ('\u0475', '\u0475'), ('\u0477', '\u0477'),
+        ('\u0479', '\u0479'), ('\u047b', '\u047b'),
+        ('\u047d', '\u047d'), ('\u047f', '\u047f'),
+        ('\u0481', '\u0481'), ('\u048b', '\u048b'),
+        ('\u048d', '\u048d'), ('\u048f', '\u048f'),
+        ('\u0491', '\u0491'), ('\u0493', '\u0493'),
+        ('\u0495', '\u0495'), ('\u0497', '\u0497'),
+        ('\u0499', '\u0499'), ('\u049b', '\u049b'),
+        ('\u049d', '\u049d'), ('\u049f', '\u049f'),
+        ('\u04a1', '\u04a1'), ('\u04a3', '\u04a3'),
+        ('\u04a5', '\u04a5'), ('\u04a7', '\u04a7'),
+        ('\u04a9', '\u04a9'), ('\u04ab', '\u04ab'),
+        ('\u04ad', '\u04ad'), ('\u04af', '\u04af'),
+        ('\u04b1', '\u04b1'), ('\u04b3', '\u04b3'),
+        ('\u04b5', '\u04b5'), ('\u04b7', '\u04b7'),
+        ('\u04b9', '\u04b9'), ('\u04bb', '\u04bb'),
+        ('\u04bd', '\u04bd'), ('\u04bf', '\u04bf'),
+        ('\u04c2', '\u04c2'), ('\u04c4', '\u04c4'),
+        ('\u04c6', '\u04c6'), ('\u04c8', '\u04c8'),
+        ('\u04ca', '\u04ca'), ('\u04cc', '\u04cc'),
+        ('\u04ce', '\u04cf'), ('\u04d1', '\u04d1'),
+        ('\u04d3', '\u04d3'), ('\u04d5', '\u04d5'),
+        ('\u04d7', '\u04d7'), ('\u04d9', '\u04d9'),
+        ('\u04db', '\u04db'), ('\u04dd', '\u04dd'),
+        ('\u04df', '\u04df'), ('\u04e1', '\u04e1'),
+        ('\u04e3', '\u04e3'), ('\u04e5', '\u04e5'),
+        ('\u04e7', '\u04e7'), ('\u04e9', '\u04e9'),
+        ('\u04eb', '\u04eb'), ('\u04ed', '\u04ed'),
+        ('\u04ef', '\u04ef'), ('\u04f1', '\u04f1'),
+        ('\u04f3', '\u04f3'), ('\u04f5', '\u04f5'),
+        ('\u04f7', '\u04f7'), ('\u04f9', '\u04f9'),
+        ('\u04fb', '\u04fb'), ('\u04fd', '\u04fd'),
+        ('\u04ff', '\u04ff'), ('\u0501', '\u0501'),
+        ('\u0503', '\u0503'), ('\u0505', '\u0505'),
+        ('\u0507', '\u0507'), ('\u0509', '\u0509'),
+        ('\u050b', '\u050b'), ('\u050d', '\u050d'),
+        ('\u050f', '\u050f'), ('\u0511', '\u0511'),
+        ('\u0513', '\u0513'), ('\u0515', '\u0515'),
+        ('\u0517', '\u0517'), ('\u0519', '\u0519'),
+        ('\u051b', '\u051b'), ('\u051d', '\u051d'),
+        ('\u051f', '\u051f'), ('\u0521', '\u0521'),
+        ('\u0523', '\u0523'), ('\u0525', '\u0525'),
+        ('\u0527', '\u0527'), ('\u0561', '\u0587'),
+        ('\u1d00', '\u1d2b'), ('\u1d6b', '\u1d77'),
+        ('\u1d79', '\u1d9a'), ('\u1e01', '\u1e01'),
+        ('\u1e03', '\u1e03'), ('\u1e05', '\u1e05'),
+        ('\u1e07', '\u1e07'), ('\u1e09', '\u1e09'),
+        ('\u1e0b', '\u1e0b'), ('\u1e0d', '\u1e0d'),
+        ('\u1e0f', '\u1e0f'), ('\u1e11', '\u1e11'),
+        ('\u1e13', '\u1e13'), ('\u1e15', '\u1e15'),
+        ('\u1e17', '\u1e17'), ('\u1e19', '\u1e19'),
+        ('\u1e1b', '\u1e1b'), ('\u1e1d', '\u1e1d'),
+        ('\u1e1f', '\u1e1f'), ('\u1e21', '\u1e21'),
+        ('\u1e23', '\u1e23'), ('\u1e25', '\u1e25'),
+        ('\u1e27', '\u1e27'), ('\u1e29', '\u1e29'),
+        ('\u1e2b', '\u1e2b'), ('\u1e2d', '\u1e2d'),
+        ('\u1e2f', '\u1e2f'), ('\u1e31', '\u1e31'),
+        ('\u1e33', '\u1e33'), ('\u1e35', '\u1e35'),
+        ('\u1e37', '\u1e37'), ('\u1e39', '\u1e39'),
+        ('\u1e3b', '\u1e3b'), ('\u1e3d', '\u1e3d'),
+        ('\u1e3f', '\u1e3f'), ('\u1e41', '\u1e41'),
+        ('\u1e43', '\u1e43'), ('\u1e45', '\u1e45'),
+        ('\u1e47', '\u1e47'), ('\u1e49', '\u1e49'),
+        ('\u1e4b', '\u1e4b'), ('\u1e4d', '\u1e4d'),
+        ('\u1e4f', '\u1e4f'), ('\u1e51', '\u1e51'),
+        ('\u1e53', '\u1e53'), ('\u1e55', '\u1e55'),
+        ('\u1e57', '\u1e57'), ('\u1e59', '\u1e59'),
+        ('\u1e5b', '\u1e5b'), ('\u1e5d', '\u1e5d'),
+        ('\u1e5f', '\u1e5f'), ('\u1e61', '\u1e61'),
+        ('\u1e63', '\u1e63'), ('\u1e65', '\u1e65'),
+        ('\u1e67', '\u1e67'), ('\u1e69', '\u1e69'),
+        ('\u1e6b', '\u1e6b'), ('\u1e6d', '\u1e6d'),
+        ('\u1e6f', '\u1e6f'), ('\u1e71', '\u1e71'),
+        ('\u1e73', '\u1e73'), ('\u1e75', '\u1e75'),
+        ('\u1e77', '\u1e77'), ('\u1e79', '\u1e79'),
+        ('\u1e7b', '\u1e7b'), ('\u1e7d', '\u1e7d'),
+        ('\u1e7f', '\u1e7f'), ('\u1e81', '\u1e81'),
+        ('\u1e83', '\u1e83'), ('\u1e85', '\u1e85'),
+        ('\u1e87', '\u1e87'), ('\u1e89', '\u1e89'),
+        ('\u1e8b', '\u1e8b'), ('\u1e8d', '\u1e8d'),
+        ('\u1e8f', '\u1e8f'), ('\u1e91', '\u1e91'),
+        ('\u1e93', '\u1e93'), ('\u1e95', '\u1e9d'),
+        ('\u1e9f', '\u1e9f'), ('\u1ea1', '\u1ea1'),
+        ('\u1ea3', '\u1ea3'), ('\u1ea5', '\u1ea5'),
+        ('\u1ea7', '\u1ea7'), ('\u1ea9', '\u1ea9'),
+        ('\u1eab', '\u1eab'), ('\u1ead', '\u1ead'),
+        ('\u1eaf', '\u1eaf'), ('\u1eb1', '\u1eb1'),
+        ('\u1eb3', '\u1eb3'), ('\u1eb5', '\u1eb5'),
+        ('\u1eb7', '\u1eb7'), ('\u1eb9', '\u1eb9'),
+        ('\u1ebb', '\u1ebb'), ('\u1ebd', '\u1ebd'),
+        ('\u1ebf', '\u1ebf'), ('\u1ec1', '\u1ec1'),
+        ('\u1ec3', '\u1ec3'), ('\u1ec5', '\u1ec5'),
+        ('\u1ec7', '\u1ec7'), ('\u1ec9', '\u1ec9'),
+        ('\u1ecb', '\u1ecb'), ('\u1ecd', '\u1ecd'),
+        ('\u1ecf', '\u1ecf'), ('\u1ed1', '\u1ed1'),
+        ('\u1ed3', '\u1ed3'), ('\u1ed5', '\u1ed5'),
+        ('\u1ed7', '\u1ed7'), ('\u1ed9', '\u1ed9'),
+        ('\u1edb', '\u1edb'), ('\u1edd', '\u1edd'),
+        ('\u1edf', '\u1edf'), ('\u1ee1', '\u1ee1'),
+        ('\u1ee3', '\u1ee3'), ('\u1ee5', '\u1ee5'),
+        ('\u1ee7', '\u1ee7'), ('\u1ee9', '\u1ee9'),
+        ('\u1eeb', '\u1eeb'), ('\u1eed', '\u1eed'),
+        ('\u1eef', '\u1eef'), ('\u1ef1', '\u1ef1'),
+        ('\u1ef3', '\u1ef3'), ('\u1ef5', '\u1ef5'),
+        ('\u1ef7', '\u1ef7'), ('\u1ef9', '\u1ef9'),
+        ('\u1efb', '\u1efb'), ('\u1efd', '\u1efd'),
+        ('\u1eff', '\u1f07'), ('\u1f10', '\u1f15'),
+        ('\u1f20', '\u1f27'), ('\u1f30', '\u1f37'),
+        ('\u1f40', '\u1f45'), ('\u1f50', '\u1f57'),
+        ('\u1f60', '\u1f67'), ('\u1f70', '\u1f87'),
+        ('\u1f90', '\u1f97'), ('\u1fa0', '\u1fa7'),
+        ('\u1fb0', '\u1fb7'), ('\u1fbe', '\u1fbe'),
+        ('\u1fc2', '\u1fc7'), ('\u1fd0', '\u1fd7'),
+        ('\u1fe0', '\u1fe7'), ('\u1ff2', '\u1ff7'),
+        ('\u210a', '\u210a'), ('\u210e', '\u210f'),
+        ('\u2113', '\u2113'), ('\u212f', '\u212f'),
+        ('\u2134', '\u2134'), ('\u2139', '\u2139'),
+        ('\u213c', '\u213d'), ('\u2146', '\u2149'),
+        ('\u214e', '\u214e'), ('\u2184', '\u2184'),
+        ('\u2c30', '\u2c5e'), ('\u2c61', '\u2c61'),
+        ('\u2c65', '\u2c66'), ('\u2c68', '\u2c68'),
+        ('\u2c6a', '\u2c6a'), ('\u2c6c', '\u2c6c'),
+        ('\u2c71', '\u2c71'), ('\u2c73', '\u2c74'),
+        ('\u2c76', '\u2c7b'), ('\u2c81', '\u2c81'),
+        ('\u2c83', '\u2c83'), ('\u2c85', '\u2c85'),
+        ('\u2c87', '\u2c87'), ('\u2c89', '\u2c89'),
+        ('\u2c8b', '\u2c8b'), ('\u2c8d', '\u2c8d'),
+        ('\u2c8f', '\u2c8f'), ('\u2c91', '\u2c91'),
+        ('\u2c93', '\u2c93'), ('\u2c95', '\u2c95'),
+        ('\u2c97', '\u2c97'), ('\u2c99', '\u2c99'),
+        ('\u2c9b', '\u2c9b'), ('\u2c9d', '\u2c9d'),
+        ('\u2c9f', '\u2c9f'), ('\u2ca1', '\u2ca1'),
+        ('\u2ca3', '\u2ca3'), ('\u2ca5', '\u2ca5'),
+        ('\u2ca7', '\u2ca7'), ('\u2ca9', '\u2ca9'),
+        ('\u2cab', '\u2cab'), ('\u2cad', '\u2cad'),
+        ('\u2caf', '\u2caf'), ('\u2cb1', '\u2cb1'),
+        ('\u2cb3', '\u2cb3'), ('\u2cb5', '\u2cb5'),
+        ('\u2cb7', '\u2cb7'), ('\u2cb9', '\u2cb9'),
+        ('\u2cbb', '\u2cbb'), ('\u2cbd', '\u2cbd'),
+        ('\u2cbf', '\u2cbf'), ('\u2cc1', '\u2cc1'),
+        ('\u2cc3', '\u2cc3'), ('\u2cc5', '\u2cc5'),
+        ('\u2cc7', '\u2cc7'), ('\u2cc9', '\u2cc9'),
+        ('\u2ccb', '\u2ccb'), ('\u2ccd', '\u2ccd'),
+        ('\u2ccf', '\u2ccf'), ('\u2cd1', '\u2cd1'),
+        ('\u2cd3', '\u2cd3'), ('\u2cd5', '\u2cd5'),
+        ('\u2cd7', '\u2cd7'), ('\u2cd9', '\u2cd9'),
+        ('\u2cdb', '\u2cdb'), ('\u2cdd', '\u2cdd'),
+        ('\u2cdf', '\u2cdf'), ('\u2ce1', '\u2ce1'),
+        ('\u2ce3', '\u2ce4'), ('\u2cec', '\u2cec'),
+        ('\u2cee', '\u2cee'), ('\u2cf3', '\u2cf3'),
+        ('\u2d00', '\u2d2d'), ('\ua641', '\ua641'),
+        ('\ua643', '\ua643'), ('\ua645', '\ua645'),
+        ('\ua647', '\ua647'), ('\ua649', '\ua649'),
+        ('\ua64b', '\ua64b'), ('\ua64d', '\ua64d'),
+        ('\ua64f', '\ua64f'), ('\ua651', '\ua651'),
+        ('\ua653', '\ua653'), ('\ua655', '\ua655'),
+        ('\ua657', '\ua657'), ('\ua659', '\ua659'),
+        ('\ua65b', '\ua65b'), ('\ua65d', '\ua65d'),
+        ('\ua65f', '\ua65f'), ('\ua661', '\ua661'),
+        ('\ua663', '\ua663'), ('\ua665', '\ua665'),
+        ('\ua667', '\ua667'), ('\ua669', '\ua669'),
+        ('\ua66b', '\ua66b'), ('\ua66d', '\ua66d'),
+        ('\ua681', '\ua681'), ('\ua683', '\ua683'),
+        ('\ua685', '\ua685'), ('\ua687', '\ua687'),
+        ('\ua689', '\ua689'), ('\ua68b', '\ua68b'),
+        ('\ua68d', '\ua68d'), ('\ua68f', '\ua68f'),
+        ('\ua691', '\ua691'), ('\ua693', '\ua693'),
+        ('\ua695', '\ua695'), ('\ua697', '\ua697'),
+        ('\ua723', '\ua723'), ('\ua725', '\ua725'),
+        ('\ua727', '\ua727'), ('\ua729', '\ua729'),
+        ('\ua72b', '\ua72b'), ('\ua72d', '\ua72d'),
+        ('\ua72f', '\ua731'), ('\ua733', '\ua733'),
+        ('\ua735', '\ua735'), ('\ua737', '\ua737'),
+        ('\ua739', '\ua739'), ('\ua73b', '\ua73b'),
+        ('\ua73d', '\ua73d'), ('\ua73f', '\ua73f'),
+        ('\ua741', '\ua741'), ('\ua743', '\ua743'),
+        ('\ua745', '\ua745'), ('\ua747', '\ua747'),
+        ('\ua749', '\ua749'), ('\ua74b', '\ua74b'),
+        ('\ua74d', '\ua74d'), ('\ua74f', '\ua74f'),
+        ('\ua751', '\ua751'), ('\ua753', '\ua753'),
+        ('\ua755', '\ua755'), ('\ua757', '\ua757'),
+        ('\ua759', '\ua759'), ('\ua75b', '\ua75b'),
+        ('\ua75d', '\ua75d'), ('\ua75f', '\ua75f'),
+        ('\ua761', '\ua761'), ('\ua763', '\ua763'),
+        ('\ua765', '\ua765'), ('\ua767', '\ua767'),
+        ('\ua769', '\ua769'), ('\ua76b', '\ua76b'),
+        ('\ua76d', '\ua76d'), ('\ua76f', '\ua76f'),
+        ('\ua771', '\ua778'), ('\ua77a', '\ua77a'),
+        ('\ua77c', '\ua77c'), ('\ua77f', '\ua77f'),
+        ('\ua781', '\ua781'), ('\ua783', '\ua783'),
+        ('\ua785', '\ua785'), ('\ua787', '\ua787'),
+        ('\ua78c', '\ua78c'), ('\ua78e', '\ua78e'),
+        ('\ua791', '\ua791'), ('\ua793', '\ua793'),
+        ('\ua7a1', '\ua7a1'), ('\ua7a3', '\ua7a3'),
+        ('\ua7a5', '\ua7a5'), ('\ua7a7', '\ua7a7'),
+        ('\ua7a9', '\ua7a9'), ('\ua7fa', '\ua7fa'),
+        ('\ufb00', '\ufb17'), ('\uff41', '\uff5a'),
+        ('\U00010428', '\U0001044f'), ('\U0001d41a', '\U0001d433'),
+        ('\U0001d44e', '\U0001d467'), ('\U0001d482', '\U0001d49b'),
+        ('\U0001d4b6', '\U0001d4cf'), ('\U0001d4ea', '\U0001d503'),
+        ('\U0001d51e', '\U0001d537'), ('\U0001d552', '\U0001d56b'),
+        ('\U0001d586', '\U0001d59f'), ('\U0001d5ba', '\U0001d5d3'),
+        ('\U0001d5ee', '\U0001d607'), ('\U0001d622', '\U0001d63b'),
+        ('\U0001d656', '\U0001d66f'), ('\U0001d68a', '\U0001d6a5'),
+        ('\U0001d6c2', '\U0001d6da'), ('\U0001d6dc', '\U0001d6e1'),
+        ('\U0001d6fc', '\U0001d714'), ('\U0001d716', '\U0001d71b'),
+        ('\U0001d736', '\U0001d74e'), ('\U0001d750', '\U0001d755'),
+        ('\U0001d770', '\U0001d788'), ('\U0001d78a', '\U0001d78f'),
+        ('\U0001d7aa', '\U0001d7c2'), ('\U0001d7c4', '\U0001d7c9'),
+        ('\U0001d7cb', '\U0001d7cb')
+    ];
+
+    pub fn Ll(c: char) -> bool {
+        bsearch_range_table(c, Ll_table)
+    }
+
+    static Lm_table : &'static [(char,char)] = &[
+        ('\u02b0', '\u02c1'), ('\u02c6', '\u02d1'),
+        ('\u02e0', '\u02e4'), ('\u02ec', '\u02ec'),
+        ('\u02ee', '\u02ee'), ('\u0374', '\u0374'),
+        ('\u037a', '\u037a'), ('\u0559', '\u0559'),
+        ('\u0640', '\u0640'), ('\u06e5', '\u06e6'),
+        ('\u07f4', '\u07f5'), ('\u07fa', '\u07fa'),
+        ('\u081a', '\u081a'), ('\u0824', '\u0824'),
+        ('\u0828', '\u0828'), ('\u0971', '\u0971'),
+        ('\u0e46', '\u0e46'), ('\u0ec6', '\u0ec6'),
+        ('\u10fc', '\u10fc'), ('\u17d7', '\u17d7'),
+        ('\u1843', '\u1843'), ('\u1aa7', '\u1aa7'),
+        ('\u1c78', '\u1c7d'), ('\u1d2c', '\u1d6a'),
+        ('\u1d78', '\u1d78'), ('\u1d9b', '\u1dbf'),
+        ('\u2071', '\u2071'), ('\u207f', '\u207f'),
+        ('\u2090', '\u209c'), ('\u2c7c', '\u2c7d'),
+        ('\u2d6f', '\u2d6f'), ('\u2e2f', '\u2e2f'),
+        ('\u3005', '\u3005'), ('\u3031', '\u3035'),
+        ('\u303b', '\u303b'), ('\u309d', '\u309e'),
+        ('\u30fc', '\u30fe'), ('\ua015', '\ua015'),
+        ('\ua4f8', '\ua4fd'), ('\ua60c', '\ua60c'),
+        ('\ua67f', '\ua67f'), ('\ua717', '\ua71f'),
+        ('\ua770', '\ua770'), ('\ua788', '\ua788'),
+        ('\ua7f8', '\ua7f9'), ('\ua9cf', '\ua9cf'),
+        ('\uaa70', '\uaa70'), ('\uaadd', '\uaadd'),
+        ('\uaaf3', '\uaaf4'), ('\uff70', '\uff70'),
+        ('\uff9e', '\uff9f'), ('\U00016f93', '\U00016f9f')
+    ];
+
+    pub fn Lm(c: char) -> bool {
+        bsearch_range_table(c, Lm_table)
+    }
+
+    static Lo_table : &'static [(char,char)] = &[
+        ('\xaa', '\xaa'), ('\xba', '\xba'),
+        ('\u01bb', '\u01bb'), ('\u01c0', '\u01c3'),
+        ('\u0294', '\u0294'), ('\u05d0', '\u05f2'),
+        ('\u0620', '\u063f'), ('\u0641', '\u064a'),
+        ('\u066e', '\u066f'), ('\u0671', '\u06d3'),
+        ('\u06d5', '\u06d5'), ('\u06ee', '\u06ef'),
+        ('\u06fa', '\u06fc'), ('\u06ff', '\u06ff'),
+        ('\u0710', '\u0710'), ('\u0712', '\u072f'),
+        ('\u074d', '\u07a5'), ('\u07b1', '\u07b1'),
+        ('\u07ca', '\u07ea'), ('\u0800', '\u0815'),
+        ('\u0840', '\u0858'), ('\u08a0', '\u08ac'),
+        ('\u0904', '\u0939'), ('\u093d', '\u093d'),
+        ('\u0950', '\u0950'), ('\u0958', '\u0961'),
+        ('\u0972', '\u097f'), ('\u0985', '\u09b9'),
+        ('\u09bd', '\u09bd'), ('\u09ce', '\u09ce'),
+        ('\u09dc', '\u09e1'), ('\u09f0', '\u09f1'),
+        ('\u0a05', '\u0a39'), ('\u0a59', '\u0a5e'),
+        ('\u0a72', '\u0a74'), ('\u0a85', '\u0ab9'),
+        ('\u0abd', '\u0abd'), ('\u0ad0', '\u0ae1'),
+        ('\u0b05', '\u0b39'), ('\u0b3d', '\u0b3d'),
+        ('\u0b5c', '\u0b61'), ('\u0b71', '\u0b71'),
+        ('\u0b83', '\u0bb9'), ('\u0bd0', '\u0bd0'),
+        ('\u0c05', '\u0c3d'), ('\u0c58', '\u0c61'),
+        ('\u0c85', '\u0cb9'), ('\u0cbd', '\u0cbd'),
+        ('\u0cde', '\u0ce1'), ('\u0cf1', '\u0cf2'),
+        ('\u0d05', '\u0d3d'), ('\u0d4e', '\u0d4e'),
+        ('\u0d60', '\u0d61'), ('\u0d7a', '\u0d7f'),
+        ('\u0d85', '\u0dc6'), ('\u0e01', '\u0e30'),
+        ('\u0e32', '\u0e33'), ('\u0e40', '\u0e45'),
+        ('\u0e81', '\u0eb0'), ('\u0eb2', '\u0eb3'),
+        ('\u0ebd', '\u0ec4'), ('\u0edc', '\u0f00'),
+        ('\u0f40', '\u0f6c'), ('\u0f88', '\u0f8c'),
+        ('\u1000', '\u102a'), ('\u103f', '\u103f'),
+        ('\u1050', '\u1055'), ('\u105a', '\u105d'),
+        ('\u1061', '\u1061'), ('\u1065', '\u1066'),
+        ('\u106e', '\u1070'), ('\u1075', '\u1081'),
+        ('\u108e', '\u108e'), ('\u10d0', '\u10fa'),
+        ('\u10fd', '\u135a'), ('\u1380', '\u138f'),
+        ('\u13a0', '\u13f4'), ('\u1401', '\u166c'),
+        ('\u166f', '\u167f'), ('\u1681', '\u169a'),
+        ('\u16a0', '\u16ea'), ('\u1700', '\u1711'),
+        ('\u1720', '\u1731'), ('\u1740', '\u1751'),
+        ('\u1760', '\u1770'), ('\u1780', '\u17b3'),
+        ('\u17dc', '\u17dc'), ('\u1820', '\u1842'),
+        ('\u1844', '\u18a8'), ('\u18aa', '\u191c'),
+        ('\u1950', '\u19ab'), ('\u19c1', '\u19c7'),
+        ('\u1a00', '\u1a16'), ('\u1a20', '\u1a54'),
+        ('\u1b05', '\u1b33'), ('\u1b45', '\u1b4b'),
+        ('\u1b83', '\u1ba0'), ('\u1bae', '\u1baf'),
+        ('\u1bba', '\u1be5'), ('\u1c00', '\u1c23'),
+        ('\u1c4d', '\u1c4f'), ('\u1c5a', '\u1c77'),
+        ('\u1ce9', '\u1cec'), ('\u1cee', '\u1cf1'),
+        ('\u1cf5', '\u1cf6'), ('\u2135', '\u2138'),
+        ('\u2d30', '\u2d67'), ('\u2d80', '\u2dde'),
+        ('\u3006', '\u3006'), ('\u303c', '\u303c'),
+        ('\u3041', '\u3096'), ('\u309f', '\u309f'),
+        ('\u30a1', '\u30fa'), ('\u30ff', '\u318e'),
+        ('\u31a0', '\u31ba'), ('\u31f0', '\u31ff'),
+        ('\u3400', '\u4db5'), ('\u4e00', '\ua014'),
+        ('\ua016', '\ua48c'), ('\ua4d0', '\ua4f7'),
+        ('\ua500', '\ua60b'), ('\ua610', '\ua61f'),
+        ('\ua62a', '\ua62b'), ('\ua66e', '\ua66e'),
+        ('\ua6a0', '\ua6e5'), ('\ua7fb', '\ua801'),
+        ('\ua803', '\ua805'), ('\ua807', '\ua80a'),
+        ('\ua80c', '\ua822'), ('\ua840', '\ua873'),
+        ('\ua882', '\ua8b3'), ('\ua8f2', '\ua8f7'),
+        ('\ua8fb', '\ua8fb'), ('\ua90a', '\ua925'),
+        ('\ua930', '\ua946'), ('\ua960', '\ua97c'),
+        ('\ua984', '\ua9b2'), ('\uaa00', '\uaa28'),
+        ('\uaa40', '\uaa42'), ('\uaa44', '\uaa4b'),
+        ('\uaa60', '\uaa6f'), ('\uaa71', '\uaa76'),
+        ('\uaa7a', '\uaa7a'), ('\uaa80', '\uaaaf'),
+        ('\uaab1', '\uaab1'), ('\uaab5', '\uaab6'),
+        ('\uaab9', '\uaabd'), ('\uaac0', '\uaac0'),
+        ('\uaac2', '\uaadc'), ('\uaae0', '\uaaea'),
+        ('\uaaf2', '\uaaf2'), ('\uab01', '\uabe2'),
+        ('\uac00', '\ud7fb'), ('\uf900', '\ufad9'),
+        ('\ufb1d', '\ufb1d'), ('\ufb1f', '\ufb28'),
+        ('\ufb2a', '\ufbb1'), ('\ufbd3', '\ufd3d'),
+        ('\ufd50', '\ufdfb'), ('\ufe70', '\ufefc'),
+        ('\uff66', '\uff6f'), ('\uff71', '\uff9d'),
+        ('\uffa0', '\uffdc'), ('\U00010000', '\U000100fa'),
+        ('\U00010280', '\U0001031e'), ('\U00010330', '\U00010340'),
+        ('\U00010342', '\U00010349'), ('\U00010380', '\U0001039d'),
+        ('\U000103a0', '\U000103cf'), ('\U00010450', '\U0001049d'),
+        ('\U00010800', '\U00010855'), ('\U00010900', '\U00010915'),
+        ('\U00010920', '\U00010939'), ('\U00010980', '\U00010a00'),
+        ('\U00010a10', '\U00010a33'), ('\U00010a60', '\U00010a7c'),
+        ('\U00010b00', '\U00010b35'), ('\U00010b40', '\U00010b55'),
+        ('\U00010b60', '\U00010b72'), ('\U00010c00', '\U00010c48'),
+        ('\U00011003', '\U00011037'), ('\U00011083', '\U000110af'),
+        ('\U000110d0', '\U000110e8'), ('\U00011103', '\U00011126'),
+        ('\U00011183', '\U000111b2'), ('\U000111c1', '\U000111c4'),
+        ('\U00011680', '\U000116aa'), ('\U00012000', '\U0001236e'),
+        ('\U00013000', '\U00016f50'), ('\U0001b000', '\U0001b001'),
+        ('\U0001ee00', '\U0001eebb'), ('\U00020000', '\U0002fa1d')
+    ];
+
+    pub fn Lo(c: char) -> bool {
+        bsearch_range_table(c, Lo_table)
+    }
+
+    static Lt_table : &'static [(char,char)] = &[
+        ('\u01c5', '\u01c5'), ('\u01c8', '\u01c8'),
+        ('\u01cb', '\u01cb'), ('\u01f2', '\u01f2'),
+        ('\u1f88', '\u1f8f'), ('\u1f98', '\u1f9f'),
+        ('\u1fa8', '\u1faf'), ('\u1fbc', '\u1fbc'),
+        ('\u1fcc', '\u1fcc'), ('\u1ffc', '\u1ffc')
+    ];
+
+    pub fn Lt(c: char) -> bool {
+        bsearch_range_table(c, Lt_table)
+    }
+
+    static Lu_table : &'static [(char,char)] = &[
+        ('\x41', '\x5a'), ('\xc0', '\xd6'),
+        ('\xd8', '\xde'), ('\u0100', '\u0100'),
+        ('\u0102', '\u0102'), ('\u0104', '\u0104'),
+        ('\u0106', '\u0106'), ('\u0108', '\u0108'),
+        ('\u010a', '\u010a'), ('\u010c', '\u010c'),
+        ('\u010e', '\u010e'), ('\u0110', '\u0110'),
+        ('\u0112', '\u0112'), ('\u0114', '\u0114'),
+        ('\u0116', '\u0116'), ('\u0118', '\u0118'),
+        ('\u011a', '\u011a'), ('\u011c', '\u011c'),
+        ('\u011e', '\u011e'), ('\u0120', '\u0120'),
+        ('\u0122', '\u0122'), ('\u0124', '\u0124'),
+        ('\u0126', '\u0126'), ('\u0128', '\u0128'),
+        ('\u012a', '\u012a'), ('\u012c', '\u012c'),
+        ('\u012e', '\u012e'), ('\u0130', '\u0130'),
+        ('\u0132', '\u0132'), ('\u0134', '\u0134'),
+        ('\u0136', '\u0136'), ('\u0139', '\u0139'),
+        ('\u013b', '\u013b'), ('\u013d', '\u013d'),
+        ('\u013f', '\u013f'), ('\u0141', '\u0141'),
+        ('\u0143', '\u0143'), ('\u0145', '\u0145'),
+        ('\u0147', '\u0147'), ('\u014a', '\u014a'),
+        ('\u014c', '\u014c'), ('\u014e', '\u014e'),
+        ('\u0150', '\u0150'), ('\u0152', '\u0152'),
+        ('\u0154', '\u0154'), ('\u0156', '\u0156'),
+        ('\u0158', '\u0158'), ('\u015a', '\u015a'),
+        ('\u015c', '\u015c'), ('\u015e', '\u015e'),
+        ('\u0160', '\u0160'), ('\u0162', '\u0162'),
+        ('\u0164', '\u0164'), ('\u0166', '\u0166'),
+        ('\u0168', '\u0168'), ('\u016a', '\u016a'),
+        ('\u016c', '\u016c'), ('\u016e', '\u016e'),
+        ('\u0170', '\u0170'), ('\u0172', '\u0172'),
+        ('\u0174', '\u0174'), ('\u0176', '\u0176'),
+        ('\u0178', '\u0179'), ('\u017b', '\u017b'),
+        ('\u017d', '\u017d'), ('\u0181', '\u0182'),
+        ('\u0184', '\u0184'), ('\u0186', '\u0187'),
+        ('\u0189', '\u018b'), ('\u018e', '\u0191'),
+        ('\u0193', '\u0194'), ('\u0196', '\u0198'),
+        ('\u019c', '\u019d'), ('\u019f', '\u01a0'),
+        ('\u01a2', '\u01a2'), ('\u01a4', '\u01a4'),
+        ('\u01a6', '\u01a7'), ('\u01a9', '\u01a9'),
+        ('\u01ac', '\u01ac'), ('\u01ae', '\u01af'),
+        ('\u01b1', '\u01b3'), ('\u01b5', '\u01b5'),
+        ('\u01b7', '\u01b8'), ('\u01bc', '\u01bc'),
+        ('\u01c4', '\u01c4'), ('\u01c7', '\u01c7'),
+        ('\u01ca', '\u01ca'), ('\u01cd', '\u01cd'),
+        ('\u01cf', '\u01cf'), ('\u01d1', '\u01d1'),
+        ('\u01d3', '\u01d3'), ('\u01d5', '\u01d5'),
+        ('\u01d7', '\u01d7'), ('\u01d9', '\u01d9'),
+        ('\u01db', '\u01db'), ('\u01de', '\u01de'),
+        ('\u01e0', '\u01e0'), ('\u01e2', '\u01e2'),
+        ('\u01e4', '\u01e4'), ('\u01e6', '\u01e6'),
+        ('\u01e8', '\u01e8'), ('\u01ea', '\u01ea'),
+        ('\u01ec', '\u01ec'), ('\u01ee', '\u01ee'),
+        ('\u01f1', '\u01f1'), ('\u01f4', '\u01f4'),
+        ('\u01f6', '\u01f8'), ('\u01fa', '\u01fa'),
+        ('\u01fc', '\u01fc'), ('\u01fe', '\u01fe'),
+        ('\u0200', '\u0200'), ('\u0202', '\u0202'),
+        ('\u0204', '\u0204'), ('\u0206', '\u0206'),
+        ('\u0208', '\u0208'), ('\u020a', '\u020a'),
+        ('\u020c', '\u020c'), ('\u020e', '\u020e'),
+        ('\u0210', '\u0210'), ('\u0212', '\u0212'),
+        ('\u0214', '\u0214'), ('\u0216', '\u0216'),
+        ('\u0218', '\u0218'), ('\u021a', '\u021a'),
+        ('\u021c', '\u021c'), ('\u021e', '\u021e'),
+        ('\u0220', '\u0220'), ('\u0222', '\u0222'),
+        ('\u0224', '\u0224'), ('\u0226', '\u0226'),
+        ('\u0228', '\u0228'), ('\u022a', '\u022a'),
+        ('\u022c', '\u022c'), ('\u022e', '\u022e'),
+        ('\u0230', '\u0230'), ('\u0232', '\u0232'),
+        ('\u023a', '\u023b'), ('\u023d', '\u023e'),
+        ('\u0241', '\u0241'), ('\u0243', '\u0246'),
+        ('\u0248', '\u0248'), ('\u024a', '\u024a'),
+        ('\u024c', '\u024c'), ('\u024e', '\u024e'),
+        ('\u0370', '\u0370'), ('\u0372', '\u0372'),
+        ('\u0376', '\u0376'), ('\u0386', '\u0386'),
+        ('\u0388', '\u038f'), ('\u0391', '\u03ab'),
+        ('\u03cf', '\u03cf'), ('\u03d2', '\u03d4'),
+        ('\u03d8', '\u03d8'), ('\u03da', '\u03da'),
+        ('\u03dc', '\u03dc'), ('\u03de', '\u03de'),
+        ('\u03e0', '\u03e0'), ('\u03e2', '\u03e2'),
+        ('\u03e4', '\u03e4'), ('\u03e6', '\u03e6'),
+        ('\u03e8', '\u03e8'), ('\u03ea', '\u03ea'),
+        ('\u03ec', '\u03ec'), ('\u03ee', '\u03ee'),
+        ('\u03f4', '\u03f4'), ('\u03f7', '\u03f7'),
+        ('\u03f9', '\u03fa'), ('\u03fd', '\u042f'),
+        ('\u0460', '\u0460'), ('\u0462', '\u0462'),
+        ('\u0464', '\u0464'), ('\u0466', '\u0466'),
+        ('\u0468', '\u0468'), ('\u046a', '\u046a'),
+        ('\u046c', '\u046c'), ('\u046e', '\u046e'),
+        ('\u0470', '\u0470'), ('\u0472', '\u0472'),
+        ('\u0474', '\u0474'), ('\u0476', '\u0476'),
+        ('\u0478', '\u0478'), ('\u047a', '\u047a'),
+        ('\u047c', '\u047c'), ('\u047e', '\u047e'),
+        ('\u0480', '\u0480'), ('\u048a', '\u048a'),
+        ('\u048c', '\u048c'), ('\u048e', '\u048e'),
+        ('\u0490', '\u0490'), ('\u0492', '\u0492'),
+        ('\u0494', '\u0494'), ('\u0496', '\u0496'),
+        ('\u0498', '\u0498'), ('\u049a', '\u049a'),
+        ('\u049c', '\u049c'), ('\u049e', '\u049e'),
+        ('\u04a0', '\u04a0'), ('\u04a2', '\u04a2'),
+        ('\u04a4', '\u04a4'), ('\u04a6', '\u04a6'),
+        ('\u04a8', '\u04a8'), ('\u04aa', '\u04aa'),
+        ('\u04ac', '\u04ac'), ('\u04ae', '\u04ae'),
+        ('\u04b0', '\u04b0'), ('\u04b2', '\u04b2'),
+        ('\u04b4', '\u04b4'), ('\u04b6', '\u04b6'),
+        ('\u04b8', '\u04b8'), ('\u04ba', '\u04ba'),
+        ('\u04bc', '\u04bc'), ('\u04be', '\u04be'),
+        ('\u04c0', '\u04c1'), ('\u04c3', '\u04c3'),
+        ('\u04c5', '\u04c5'), ('\u04c7', '\u04c7'),
+        ('\u04c9', '\u04c9'), ('\u04cb', '\u04cb'),
+        ('\u04cd', '\u04cd'), ('\u04d0', '\u04d0'),
+        ('\u04d2', '\u04d2'), ('\u04d4', '\u04d4'),
+        ('\u04d6', '\u04d6'), ('\u04d8', '\u04d8'),
+        ('\u04da', '\u04da'), ('\u04dc', '\u04dc'),
+        ('\u04de', '\u04de'), ('\u04e0', '\u04e0'),
+        ('\u04e2', '\u04e2'), ('\u04e4', '\u04e4'),
+        ('\u04e6', '\u04e6'), ('\u04e8', '\u04e8'),
+        ('\u04ea', '\u04ea'), ('\u04ec', '\u04ec'),
+        ('\u04ee', '\u04ee'), ('\u04f0', '\u04f0'),
+        ('\u04f2', '\u04f2'), ('\u04f4', '\u04f4'),
+        ('\u04f6', '\u04f6'), ('\u04f8', '\u04f8'),
+        ('\u04fa', '\u04fa'), ('\u04fc', '\u04fc'),
+        ('\u04fe', '\u04fe'), ('\u0500', '\u0500'),
+        ('\u0502', '\u0502'), ('\u0504', '\u0504'),
+        ('\u0506', '\u0506'), ('\u0508', '\u0508'),
+        ('\u050a', '\u050a'), ('\u050c', '\u050c'),
+        ('\u050e', '\u050e'), ('\u0510', '\u0510'),
+        ('\u0512', '\u0512'), ('\u0514', '\u0514'),
+        ('\u0516', '\u0516'), ('\u0518', '\u0518'),
+        ('\u051a', '\u051a'), ('\u051c', '\u051c'),
+        ('\u051e', '\u051e'), ('\u0520', '\u0520'),
+        ('\u0522', '\u0522'), ('\u0524', '\u0524'),
+        ('\u0526', '\u0526'), ('\u0531', '\u0556'),
+        ('\u10a0', '\u10cd'), ('\u1e00', '\u1e00'),
+        ('\u1e02', '\u1e02'), ('\u1e04', '\u1e04'),
+        ('\u1e06', '\u1e06'), ('\u1e08', '\u1e08'),
+        ('\u1e0a', '\u1e0a'), ('\u1e0c', '\u1e0c'),
+        ('\u1e0e', '\u1e0e'), ('\u1e10', '\u1e10'),
+        ('\u1e12', '\u1e12'), ('\u1e14', '\u1e14'),
+        ('\u1e16', '\u1e16'), ('\u1e18', '\u1e18'),
+        ('\u1e1a', '\u1e1a'), ('\u1e1c', '\u1e1c'),
+        ('\u1e1e', '\u1e1e'), ('\u1e20', '\u1e20'),
+        ('\u1e22', '\u1e22'), ('\u1e24', '\u1e24'),
+        ('\u1e26', '\u1e26'), ('\u1e28', '\u1e28'),
+        ('\u1e2a', '\u1e2a'), ('\u1e2c', '\u1e2c'),
+        ('\u1e2e', '\u1e2e'), ('\u1e30', '\u1e30'),
+        ('\u1e32', '\u1e32'), ('\u1e34', '\u1e34'),
+        ('\u1e36', '\u1e36'), ('\u1e38', '\u1e38'),
+        ('\u1e3a', '\u1e3a'), ('\u1e3c', '\u1e3c'),
+        ('\u1e3e', '\u1e3e'), ('\u1e40', '\u1e40'),
+        ('\u1e42', '\u1e42'), ('\u1e44', '\u1e44'),
+        ('\u1e46', '\u1e46'), ('\u1e48', '\u1e48'),
+        ('\u1e4a', '\u1e4a'), ('\u1e4c', '\u1e4c'),
+        ('\u1e4e', '\u1e4e'), ('\u1e50', '\u1e50'),
+        ('\u1e52', '\u1e52'), ('\u1e54', '\u1e54'),
+        ('\u1e56', '\u1e56'), ('\u1e58', '\u1e58'),
+        ('\u1e5a', '\u1e5a'), ('\u1e5c', '\u1e5c'),
+        ('\u1e5e', '\u1e5e'), ('\u1e60', '\u1e60'),
+        ('\u1e62', '\u1e62'), ('\u1e64', '\u1e64'),
+        ('\u1e66', '\u1e66'), ('\u1e68', '\u1e68'),
+        ('\u1e6a', '\u1e6a'), ('\u1e6c', '\u1e6c'),
+        ('\u1e6e', '\u1e6e'), ('\u1e70', '\u1e70'),
+        ('\u1e72', '\u1e72'), ('\u1e74', '\u1e74'),
+        ('\u1e76', '\u1e76'), ('\u1e78', '\u1e78'),
+        ('\u1e7a', '\u1e7a'), ('\u1e7c', '\u1e7c'),
+        ('\u1e7e', '\u1e7e'), ('\u1e80', '\u1e80'),
+        ('\u1e82', '\u1e82'), ('\u1e84', '\u1e84'),
+        ('\u1e86', '\u1e86'), ('\u1e88', '\u1e88'),
+        ('\u1e8a', '\u1e8a'), ('\u1e8c', '\u1e8c'),
+        ('\u1e8e', '\u1e8e'), ('\u1e90', '\u1e90'),
+        ('\u1e92', '\u1e92'), ('\u1e94', '\u1e94'),
+        ('\u1e9e', '\u1e9e'), ('\u1ea0', '\u1ea0'),
+        ('\u1ea2', '\u1ea2'), ('\u1ea4', '\u1ea4'),
+        ('\u1ea6', '\u1ea6'), ('\u1ea8', '\u1ea8'),
+        ('\u1eaa', '\u1eaa'), ('\u1eac', '\u1eac'),
+        ('\u1eae', '\u1eae'), ('\u1eb0', '\u1eb0'),
+        ('\u1eb2', '\u1eb2'), ('\u1eb4', '\u1eb4'),
+        ('\u1eb6', '\u1eb6'), ('\u1eb8', '\u1eb8'),
+        ('\u1eba', '\u1eba'), ('\u1ebc', '\u1ebc'),
+        ('\u1ebe', '\u1ebe'), ('\u1ec0', '\u1ec0'),
+        ('\u1ec2', '\u1ec2'), ('\u1ec4', '\u1ec4'),
+        ('\u1ec6', '\u1ec6'), ('\u1ec8', '\u1ec8'),
+        ('\u1eca', '\u1eca'), ('\u1ecc', '\u1ecc'),
+        ('\u1ece', '\u1ece'), ('\u1ed0', '\u1ed0'),
+        ('\u1ed2', '\u1ed2'), ('\u1ed4', '\u1ed4'),
+        ('\u1ed6', '\u1ed6'), ('\u1ed8', '\u1ed8'),
+        ('\u1eda', '\u1eda'), ('\u1edc', '\u1edc'),
+        ('\u1ede', '\u1ede'), ('\u1ee0', '\u1ee0'),
+        ('\u1ee2', '\u1ee2'), ('\u1ee4', '\u1ee4'),
+        ('\u1ee6', '\u1ee6'), ('\u1ee8', '\u1ee8'),
+        ('\u1eea', '\u1eea'), ('\u1eec', '\u1eec'),
+        ('\u1eee', '\u1eee'), ('\u1ef0', '\u1ef0'),
+        ('\u1ef2', '\u1ef2'), ('\u1ef4', '\u1ef4'),
+        ('\u1ef6', '\u1ef6'), ('\u1ef8', '\u1ef8'),
+        ('\u1efa', '\u1efa'), ('\u1efc', '\u1efc'),
+        ('\u1efe', '\u1efe'), ('\u1f08', '\u1f0f'),
+        ('\u1f18', '\u1f1d'), ('\u1f28', '\u1f2f'),
+        ('\u1f38', '\u1f3f'), ('\u1f48', '\u1f4d'),
+        ('\u1f59', '\u1f5f'), ('\u1f68', '\u1f6f'),
+        ('\u1fb8', '\u1fbb'), ('\u1fc8', '\u1fcb'),
+        ('\u1fd8', '\u1fdb'), ('\u1fe8', '\u1fec'),
+        ('\u1ff8', '\u1ffb'), ('\u2102', '\u2102'),
+        ('\u2107', '\u2107'), ('\u210b', '\u210d'),
+        ('\u2110', '\u2112'), ('\u2115', '\u2115'),
+        ('\u2119', '\u211d'), ('\u2124', '\u2124'),
+        ('\u2126', '\u2126'), ('\u2128', '\u2128'),
+        ('\u212a', '\u212d'), ('\u2130', '\u2133'),
+        ('\u213e', '\u213f'), ('\u2145', '\u2145'),
+        ('\u2183', '\u2183'), ('\u2c00', '\u2c2e'),
+        ('\u2c60', '\u2c60'), ('\u2c62', '\u2c64'),
+        ('\u2c67', '\u2c67'), ('\u2c69', '\u2c69'),
+        ('\u2c6b', '\u2c6b'), ('\u2c6d', '\u2c70'),
+        ('\u2c72', '\u2c72'), ('\u2c75', '\u2c75'),
+        ('\u2c7e', '\u2c80'), ('\u2c82', '\u2c82'),
+        ('\u2c84', '\u2c84'), ('\u2c86', '\u2c86'),
+        ('\u2c88', '\u2c88'), ('\u2c8a', '\u2c8a'),
+        ('\u2c8c', '\u2c8c'), ('\u2c8e', '\u2c8e'),
+        ('\u2c90', '\u2c90'), ('\u2c92', '\u2c92'),
+        ('\u2c94', '\u2c94'), ('\u2c96', '\u2c96'),
+        ('\u2c98', '\u2c98'), ('\u2c9a', '\u2c9a'),
+        ('\u2c9c', '\u2c9c'), ('\u2c9e', '\u2c9e'),
+        ('\u2ca0', '\u2ca0'), ('\u2ca2', '\u2ca2'),
+        ('\u2ca4', '\u2ca4'), ('\u2ca6', '\u2ca6'),
+        ('\u2ca8', '\u2ca8'), ('\u2caa', '\u2caa'),
+        ('\u2cac', '\u2cac'), ('\u2cae', '\u2cae'),
+        ('\u2cb0', '\u2cb0'), ('\u2cb2', '\u2cb2'),
+        ('\u2cb4', '\u2cb4'), ('\u2cb6', '\u2cb6'),
+        ('\u2cb8', '\u2cb8'), ('\u2cba', '\u2cba'),
+        ('\u2cbc', '\u2cbc'), ('\u2cbe', '\u2cbe'),
+        ('\u2cc0', '\u2cc0'), ('\u2cc2', '\u2cc2'),
+        ('\u2cc4', '\u2cc4'), ('\u2cc6', '\u2cc6'),
+        ('\u2cc8', '\u2cc8'), ('\u2cca', '\u2cca'),
+        ('\u2ccc', '\u2ccc'), ('\u2cce', '\u2cce'),
+        ('\u2cd0', '\u2cd0'), ('\u2cd2', '\u2cd2'),
+        ('\u2cd4', '\u2cd4'), ('\u2cd6', '\u2cd6'),
+        ('\u2cd8', '\u2cd8'), ('\u2cda', '\u2cda'),
+        ('\u2cdc', '\u2cdc'), ('\u2cde', '\u2cde'),
+        ('\u2ce0', '\u2ce0'), ('\u2ce2', '\u2ce2'),
+        ('\u2ceb', '\u2ceb'), ('\u2ced', '\u2ced'),
+        ('\u2cf2', '\u2cf2'), ('\ua640', '\ua640'),
+        ('\ua642', '\ua642'), ('\ua644', '\ua644'),
+        ('\ua646', '\ua646'), ('\ua648', '\ua648'),
+        ('\ua64a', '\ua64a'), ('\ua64c', '\ua64c'),
+        ('\ua64e', '\ua64e'), ('\ua650', '\ua650'),
+        ('\ua652', '\ua652'), ('\ua654', '\ua654'),
+        ('\ua656', '\ua656'), ('\ua658', '\ua658'),
+        ('\ua65a', '\ua65a'), ('\ua65c', '\ua65c'),
+        ('\ua65e', '\ua65e'), ('\ua660', '\ua660'),
+        ('\ua662', '\ua662'), ('\ua664', '\ua664'),
+        ('\ua666', '\ua666'), ('\ua668', '\ua668'),
+        ('\ua66a', '\ua66a'), ('\ua66c', '\ua66c'),
+        ('\ua680', '\ua680'), ('\ua682', '\ua682'),
+        ('\ua684', '\ua684'), ('\ua686', '\ua686'),
+        ('\ua688', '\ua688'), ('\ua68a', '\ua68a'),
+        ('\ua68c', '\ua68c'), ('\ua68e', '\ua68e'),
+        ('\ua690', '\ua690'), ('\ua692', '\ua692'),
+        ('\ua694', '\ua694'), ('\ua696', '\ua696'),
+        ('\ua722', '\ua722'), ('\ua724', '\ua724'),
+        ('\ua726', '\ua726'), ('\ua728', '\ua728'),
+        ('\ua72a', '\ua72a'), ('\ua72c', '\ua72c'),
+        ('\ua72e', '\ua72e'), ('\ua732', '\ua732'),
+        ('\ua734', '\ua734'), ('\ua736', '\ua736'),
+        ('\ua738', '\ua738'), ('\ua73a', '\ua73a'),
+        ('\ua73c', '\ua73c'), ('\ua73e', '\ua73e'),
+        ('\ua740', '\ua740'), ('\ua742', '\ua742'),
+        ('\ua744', '\ua744'), ('\ua746', '\ua746'),
+        ('\ua748', '\ua748'), ('\ua74a', '\ua74a'),
+        ('\ua74c', '\ua74c'), ('\ua74e', '\ua74e'),
+        ('\ua750', '\ua750'), ('\ua752', '\ua752'),
+        ('\ua754', '\ua754'), ('\ua756', '\ua756'),
+        ('\ua758', '\ua758'), ('\ua75a', '\ua75a'),
+        ('\ua75c', '\ua75c'), ('\ua75e', '\ua75e'),
+        ('\ua760', '\ua760'), ('\ua762', '\ua762'),
+        ('\ua764', '\ua764'), ('\ua766', '\ua766'),
+        ('\ua768', '\ua768'), ('\ua76a', '\ua76a'),
+        ('\ua76c', '\ua76c'), ('\ua76e', '\ua76e'),
+        ('\ua779', '\ua779'), ('\ua77b', '\ua77b'),
+        ('\ua77d', '\ua77e'), ('\ua780', '\ua780'),
+        ('\ua782', '\ua782'), ('\ua784', '\ua784'),
+        ('\ua786', '\ua786'), ('\ua78b', '\ua78b'),
+        ('\ua78d', '\ua78d'), ('\ua790', '\ua790'),
+        ('\ua792', '\ua792'), ('\ua7a0', '\ua7a0'),
+        ('\ua7a2', '\ua7a2'), ('\ua7a4', '\ua7a4'),
+        ('\ua7a6', '\ua7a6'), ('\ua7a8', '\ua7a8'),
+        ('\ua7aa', '\ua7aa'), ('\uff21', '\uff3a'),
+        ('\U00010400', '\U00010427'), ('\U0001d400', '\U0001d419'),
+        ('\U0001d434', '\U0001d44d'), ('\U0001d468', '\U0001d481'),
+        ('\U0001d49c', '\U0001d4b5'), ('\U0001d4d0', '\U0001d4e9'),
+        ('\U0001d504', '\U0001d51c'), ('\U0001d538', '\U0001d550'),
+        ('\U0001d56c', '\U0001d585'), ('\U0001d5a0', '\U0001d5b9'),
+        ('\U0001d5d4', '\U0001d5ed'), ('\U0001d608', '\U0001d621'),
+        ('\U0001d63c', '\U0001d655'), ('\U0001d670', '\U0001d689'),
+        ('\U0001d6a8', '\U0001d6c0'), ('\U0001d6e2', '\U0001d6fa'),
+        ('\U0001d71c', '\U0001d734'), ('\U0001d756', '\U0001d76e'),
+        ('\U0001d790', '\U0001d7a8'), ('\U0001d7ca', '\U0001d7ca')
+    ];
+
+    pub fn Lu(c: char) -> bool {
+        bsearch_range_table(c, Lu_table)
+    }
+
+    static Mc_table : &'static [(char,char)] = &[
+        ('\u0903', '\u0903'), ('\u093b', '\u093b'),
+        ('\u093e', '\u0940'), ('\u0949', '\u094c'),
+        ('\u094e', '\u094f'), ('\u0982', '\u0983'),
+        ('\u09be', '\u09c0'), ('\u09c7', '\u09cc'),
+        ('\u09d7', '\u09d7'), ('\u0a03', '\u0a03'),
+        ('\u0a3e', '\u0a40'), ('\u0a83', '\u0a83'),
+        ('\u0abe', '\u0ac0'), ('\u0ac9', '\u0acc'),
+        ('\u0b02', '\u0b03'), ('\u0b3e', '\u0b3e'),
+        ('\u0b40', '\u0b40'), ('\u0b47', '\u0b4c'),
+        ('\u0b57', '\u0b57'), ('\u0bbe', '\u0bbf'),
+        ('\u0bc1', '\u0bcc'), ('\u0bd7', '\u0bd7'),
+        ('\u0c01', '\u0c03'), ('\u0c41', '\u0c44'),
+        ('\u0c82', '\u0c83'), ('\u0cbe', '\u0cbe'),
+        ('\u0cc0', '\u0cc4'), ('\u0cc7', '\u0ccb'),
+        ('\u0cd5', '\u0cd6'), ('\u0d02', '\u0d03'),
+        ('\u0d3e', '\u0d40'), ('\u0d46', '\u0d4c'),
+        ('\u0d57', '\u0d57'), ('\u0d82', '\u0d83'),
+        ('\u0dcf', '\u0dd1'), ('\u0dd8', '\u0df3'),
+        ('\u0f3e', '\u0f3f'), ('\u0f7f', '\u0f7f'),
+        ('\u102b', '\u102c'), ('\u1031', '\u1031'),
+        ('\u1038', '\u1038'), ('\u103b', '\u103c'),
+        ('\u1056', '\u1057'), ('\u1062', '\u1064'),
+        ('\u1067', '\u106d'), ('\u1083', '\u1084'),
+        ('\u1087', '\u108c'), ('\u108f', '\u108f'),
+        ('\u109a', '\u109c'), ('\u17b6', '\u17b6'),
+        ('\u17be', '\u17c5'), ('\u17c7', '\u17c8'),
+        ('\u1923', '\u1926'), ('\u1929', '\u1931'),
+        ('\u1933', '\u1938'), ('\u19b0', '\u19c0'),
+        ('\u19c8', '\u19c9'), ('\u1a19', '\u1a1b'),
+        ('\u1a55', '\u1a55'), ('\u1a57', '\u1a57'),
+        ('\u1a61', '\u1a61'), ('\u1a63', '\u1a64'),
+        ('\u1a6d', '\u1a72'), ('\u1b04', '\u1b04'),
+        ('\u1b35', '\u1b35'), ('\u1b3b', '\u1b3b'),
+        ('\u1b3d', '\u1b41'), ('\u1b43', '\u1b44'),
+        ('\u1b82', '\u1b82'), ('\u1ba1', '\u1ba1'),
+        ('\u1ba6', '\u1ba7'), ('\u1baa', '\u1baa'),
+        ('\u1bac', '\u1bad'), ('\u1be7', '\u1be7'),
+        ('\u1bea', '\u1bec'), ('\u1bee', '\u1bee'),
+        ('\u1bf2', '\u1bf3'), ('\u1c24', '\u1c2b'),
+        ('\u1c34', '\u1c35'), ('\u1ce1', '\u1ce1'),
+        ('\u1cf2', '\u1cf3'), ('\u302e', '\u302f'),
+        ('\ua823', '\ua824'), ('\ua827', '\ua827'),
+        ('\ua880', '\ua881'), ('\ua8b4', '\ua8c3'),
+        ('\ua952', '\ua953'), ('\ua983', '\ua983'),
+        ('\ua9b4', '\ua9b5'), ('\ua9ba', '\ua9bb'),
+        ('\ua9bd', '\ua9c0'), ('\uaa2f', '\uaa30'),
+        ('\uaa33', '\uaa34'), ('\uaa4d', '\uaa4d'),
+        ('\uaa7b', '\uaa7b'), ('\uaaeb', '\uaaeb'),
+        ('\uaaee', '\uaaef'), ('\uaaf5', '\uaaf5'),
+        ('\uabe3', '\uabe4'), ('\uabe6', '\uabe7'),
+        ('\uabe9', '\uabea'), ('\uabec', '\uabec'),
+        ('\U00011000', '\U00011000'), ('\U00011002', '\U00011002'),
+        ('\U00011082', '\U00011082'), ('\U000110b0', '\U000110b2'),
+        ('\U000110b7', '\U000110b8'), ('\U0001112c', '\U0001112c'),
+        ('\U00011182', '\U00011182'), ('\U000111b3', '\U000111b5'),
+        ('\U000111bf', '\U000111c0'), ('\U000116ac', '\U000116ac'),
+        ('\U000116ae', '\U000116af'), ('\U000116b6', '\U000116b6'),
+        ('\U00016f51', '\U00016f7e'), ('\U0001d165', '\U0001d166'),
+        ('\U0001d16d', '\U0001d172')
+    ];
+
+    pub fn Mc(c: char) -> bool {
+        bsearch_range_table(c, Mc_table)
+    }
+
+    static Me_table : &'static [(char,char)] = &[
+        ('\u0488', '\u0489'), ('\u20dd', '\u20e0'),
+        ('\u20e2', '\u20e4'), ('\ua670', '\ua672')
+    ];
+
+    pub fn Me(c: char) -> bool {
+        bsearch_range_table(c, Me_table)
+    }
+
+    static Mn_table : &'static [(char,char)] = &[
+        ('\u0300', '\u036f'), ('\u0483', '\u0487'),
+        ('\u0591', '\u05bd'), ('\u05bf', '\u05bf'),
+        ('\u05c1', '\u05c2'), ('\u05c4', '\u05c5'),
+        ('\u05c7', '\u05c7'), ('\u0610', '\u061a'),
+        ('\u064b', '\u065f'), ('\u0670', '\u0670'),
+        ('\u06d6', '\u06dc'), ('\u06df', '\u06e4'),
+        ('\u06e7', '\u06e8'), ('\u06ea', '\u06ed'),
+        ('\u0711', '\u0711'), ('\u0730', '\u074a'),
+        ('\u07a6', '\u07b0'), ('\u07eb', '\u07f3'),
+        ('\u0816', '\u0819'), ('\u081b', '\u0823'),
+        ('\u0825', '\u0827'), ('\u0829', '\u082d'),
+        ('\u0859', '\u085b'), ('\u08e4', '\u0902'),
+        ('\u093a', '\u093a'), ('\u093c', '\u093c'),
+        ('\u0941', '\u0948'), ('\u094d', '\u094d'),
+        ('\u0951', '\u0957'), ('\u0962', '\u0963'),
+        ('\u0981', '\u0981'), ('\u09bc', '\u09bc'),
+        ('\u09c1', '\u09c4'), ('\u09cd', '\u09cd'),
+        ('\u09e2', '\u09e3'), ('\u0a01', '\u0a02'),
+        ('\u0a3c', '\u0a3c'), ('\u0a41', '\u0a51'),
+        ('\u0a70', '\u0a71'), ('\u0a75', '\u0a82'),
+        ('\u0abc', '\u0abc'), ('\u0ac1', '\u0ac8'),
+        ('\u0acd', '\u0acd'), ('\u0ae2', '\u0ae3'),
+        ('\u0b01', '\u0b01'), ('\u0b3c', '\u0b3c'),
+        ('\u0b3f', '\u0b3f'), ('\u0b41', '\u0b44'),
+        ('\u0b4d', '\u0b56'), ('\u0b62', '\u0b63'),
+        ('\u0b82', '\u0b82'), ('\u0bc0', '\u0bc0'),
+        ('\u0bcd', '\u0bcd'), ('\u0c3e', '\u0c40'),
+        ('\u0c46', '\u0c56'), ('\u0c62', '\u0c63'),
+        ('\u0cbc', '\u0cbc'), ('\u0cbf', '\u0cbf'),
+        ('\u0cc6', '\u0cc6'), ('\u0ccc', '\u0ccd'),
+        ('\u0ce2', '\u0ce3'), ('\u0d41', '\u0d44'),
+        ('\u0d4d', '\u0d4d'), ('\u0d62', '\u0d63'),
+        ('\u0dca', '\u0dca'), ('\u0dd2', '\u0dd6'),
+        ('\u0e31', '\u0e31'), ('\u0e34', '\u0e3a'),
+        ('\u0e47', '\u0e4e'), ('\u0eb1', '\u0eb1'),
+        ('\u0eb4', '\u0ebc'), ('\u0ec8', '\u0ecd'),
+        ('\u0f18', '\u0f19'), ('\u0f35', '\u0f35'),
+        ('\u0f37', '\u0f37'), ('\u0f39', '\u0f39'),
+        ('\u0f71', '\u0f7e'), ('\u0f80', '\u0f84'),
+        ('\u0f86', '\u0f87'), ('\u0f8d', '\u0fbc'),
+        ('\u0fc6', '\u0fc6'), ('\u102d', '\u1030'),
+        ('\u1032', '\u1037'), ('\u1039', '\u103a'),
+        ('\u103d', '\u103e'), ('\u1058', '\u1059'),
+        ('\u105e', '\u1060'), ('\u1071', '\u1074'),
+        ('\u1082', '\u1082'), ('\u1085', '\u1086'),
+        ('\u108d', '\u108d'), ('\u109d', '\u109d'),
+        ('\u135d', '\u135f'), ('\u1712', '\u1714'),
+        ('\u1732', '\u1734'), ('\u1752', '\u1753'),
+        ('\u1772', '\u1773'), ('\u17b4', '\u17b5'),
+        ('\u17b7', '\u17bd'), ('\u17c6', '\u17c6'),
+        ('\u17c9', '\u17d3'), ('\u17dd', '\u17dd'),
+        ('\u180b', '\u180d'), ('\u18a9', '\u18a9'),
+        ('\u1920', '\u1922'), ('\u1927', '\u1928'),
+        ('\u1932', '\u1932'), ('\u1939', '\u193b'),
+        ('\u1a17', '\u1a18'), ('\u1a56', '\u1a56'),
+        ('\u1a58', '\u1a60'), ('\u1a62', '\u1a62'),
+        ('\u1a65', '\u1a6c'), ('\u1a73', '\u1a7f'),
+        ('\u1b00', '\u1b03'), ('\u1b34', '\u1b34'),
+        ('\u1b36', '\u1b3a'), ('\u1b3c', '\u1b3c'),
+        ('\u1b42', '\u1b42'), ('\u1b6b', '\u1b73'),
+        ('\u1b80', '\u1b81'), ('\u1ba2', '\u1ba5'),
+        ('\u1ba8', '\u1ba9'), ('\u1bab', '\u1bab'),
+        ('\u1be6', '\u1be6'), ('\u1be8', '\u1be9'),
+        ('\u1bed', '\u1bed'), ('\u1bef', '\u1bf1'),
+        ('\u1c2c', '\u1c33'), ('\u1c36', '\u1c37'),
+        ('\u1cd0', '\u1cd2'), ('\u1cd4', '\u1ce0'),
+        ('\u1ce2', '\u1ce8'), ('\u1ced', '\u1ced'),
+        ('\u1cf4', '\u1cf4'), ('\u1dc0', '\u1dff'),
+        ('\u20d0', '\u20dc'), ('\u20e1', '\u20e1'),
+        ('\u20e5', '\u20f0'), ('\u2cef', '\u2cf1'),
+        ('\u2d7f', '\u2d7f'), ('\u2de0', '\u2dff'),
+        ('\u302a', '\u302d'), ('\u3099', '\u309a'),
+        ('\ua66f', '\ua66f'), ('\ua674', '\ua67d'),
+        ('\ua69f', '\ua69f'), ('\ua6f0', '\ua6f1'),
+        ('\ua802', '\ua802'), ('\ua806', '\ua806'),
+        ('\ua80b', '\ua80b'), ('\ua825', '\ua826'),
+        ('\ua8c4', '\ua8c4'), ('\ua8e0', '\ua8f1'),
+        ('\ua926', '\ua92d'), ('\ua947', '\ua951'),
+        ('\ua980', '\ua982'), ('\ua9b3', '\ua9b3'),
+        ('\ua9b6', '\ua9b9'), ('\ua9bc', '\ua9bc'),
+        ('\uaa29', '\uaa2e'), ('\uaa31', '\uaa32'),
+        ('\uaa35', '\uaa36'), ('\uaa43', '\uaa43'),
+        ('\uaa4c', '\uaa4c'), ('\uaab0', '\uaab0'),
+        ('\uaab2', '\uaab4'), ('\uaab7', '\uaab8'),
+        ('\uaabe', '\uaabf'), ('\uaac1', '\uaac1'),
+        ('\uaaec', '\uaaed'), ('\uaaf6', '\uaaf6'),
+        ('\uabe5', '\uabe5'), ('\uabe8', '\uabe8'),
+        ('\uabed', '\uabed'), ('\ufb1e', '\ufb1e'),
+        ('\ufe00', '\ufe0f'), ('\ufe20', '\ufe26'),
+        ('\U000101fd', '\U000101fd'), ('\U00010a01', '\U00010a0f'),
+        ('\U00010a38', '\U00010a3f'), ('\U00011001', '\U00011001'),
+        ('\U00011038', '\U00011046'), ('\U00011080', '\U00011081'),
+        ('\U000110b3', '\U000110b6'), ('\U000110b9', '\U000110ba'),
+        ('\U00011100', '\U00011102'), ('\U00011127', '\U0001112b'),
+        ('\U0001112d', '\U00011134'), ('\U00011180', '\U00011181'),
+        ('\U000111b6', '\U000111be'), ('\U000116ab', '\U000116ab'),
+        ('\U000116ad', '\U000116ad'), ('\U000116b0', '\U000116b5'),
+        ('\U000116b7', '\U000116b7'), ('\U00016f8f', '\U00016f92'),
+        ('\U0001d167', '\U0001d169'), ('\U0001d17b', '\U0001d182'),
+        ('\U0001d185', '\U0001d18b'), ('\U0001d1aa', '\U0001d1ad'),
+        ('\U0001d242', '\U0001d244'), ('\U000e0100', '\U000e01ef')
+    ];
+
+    pub fn Mn(c: char) -> bool {
+        bsearch_range_table(c, Mn_table)
+    }
+
+    static Nd_table : &'static [(char,char)] = &[
+        ('\x30', '\x39'), ('\u0660', '\u0669'),
+        ('\u06f0', '\u06f9'), ('\u07c0', '\u07c9'),
+        ('\u0966', '\u096f'), ('\u09e6', '\u09ef'),
+        ('\u0a66', '\u0a6f'), ('\u0ae6', '\u0aef'),
+        ('\u0b66', '\u0b6f'), ('\u0be6', '\u0bef'),
+        ('\u0c66', '\u0c6f'), ('\u0ce6', '\u0cef'),
+        ('\u0d66', '\u0d6f'), ('\u0e50', '\u0e59'),
+        ('\u0ed0', '\u0ed9'), ('\u0f20', '\u0f29'),
+        ('\u1040', '\u1049'), ('\u1090', '\u1099'),
+        ('\u17e0', '\u17e9'), ('\u1810', '\u1819'),
+        ('\u1946', '\u194f'), ('\u19d0', '\u19d9'),
+        ('\u1a80', '\u1a99'), ('\u1b50', '\u1b59'),
+        ('\u1bb0', '\u1bb9'), ('\u1c40', '\u1c49'),
+        ('\u1c50', '\u1c59'), ('\ua620', '\ua629'),
+        ('\ua8d0', '\ua8d9'), ('\ua900', '\ua909'),
+        ('\ua9d0', '\ua9d9'), ('\uaa50', '\uaa59'),
+        ('\uabf0', '\uabf9'), ('\uff10', '\uff19'),
+        ('\U000104a0', '\U000104a9'), ('\U00011066', '\U0001106f'),
+        ('\U000110f0', '\U000110f9'), ('\U00011136', '\U0001113f'),
+        ('\U000111d0', '\U000111d9'), ('\U000116c0', '\U000116c9'),
+        ('\U0001d7ce', '\U0001d7ff')
+    ];
+
+    pub fn Nd(c: char) -> bool {
+        bsearch_range_table(c, Nd_table)
+    }
+
+    static Nl_table : &'static [(char,char)] = &[
+        ('\u16ee', '\u16f0'), ('\u2160', '\u2182'),
+        ('\u2185', '\u2188'), ('\u3007', '\u3007'),
+        ('\u3021', '\u3029'), ('\u3038', '\u303a'),
+        ('\ua6e6', '\ua6ef'), ('\U00010140', '\U00010174'),
+        ('\U00010341', '\U00010341'), ('\U0001034a', '\U0001034a'),
+        ('\U000103d1', '\U000103d5'), ('\U00012400', '\U00012462')
+    ];
+
+    pub fn Nl(c: char) -> bool {
+        bsearch_range_table(c, Nl_table)
+    }
+
+    static No_table : &'static [(char,char)] = &[
+        ('\xb2', '\xb3'), ('\xb9', '\xb9'),
+        ('\xbc', '\xbe'), ('\u09f4', '\u09f9'),
+        ('\u0b72', '\u0b77'), ('\u0bf0', '\u0bf2'),
+        ('\u0c78', '\u0c7e'), ('\u0d70', '\u0d75'),
+        ('\u0f2a', '\u0f33'), ('\u1369', '\u137c'),
+        ('\u17f0', '\u17f9'), ('\u19da', '\u19da'),
+        ('\u2070', '\u2070'), ('\u2074', '\u2079'),
+        ('\u2080', '\u2089'), ('\u2150', '\u215f'),
+        ('\u2189', '\u2189'), ('\u2460', '\u249b'),
+        ('\u24ea', '\u24ff'), ('\u2776', '\u2793'),
+        ('\u2cfd', '\u2cfd'), ('\u3192', '\u3195'),
+        ('\u3220', '\u3229'), ('\u3248', '\u324f'),
+        ('\u3251', '\u325f'), ('\u3280', '\u3289'),
+        ('\u32b1', '\u32bf'), ('\ua830', '\ua835'),
+        ('\U00010107', '\U00010133'), ('\U00010175', '\U00010178'),
+        ('\U0001018a', '\U0001018a'), ('\U00010320', '\U00010323'),
+        ('\U00010858', '\U0001085f'), ('\U00010916', '\U0001091b'),
+        ('\U00010a40', '\U00010a47'), ('\U00010a7d', '\U00010a7e'),
+        ('\U00010b58', '\U00010b5f'), ('\U00010b78', '\U00010b7f'),
+        ('\U00010e60', '\U00010e7e'), ('\U00011052', '\U00011065'),
+        ('\U0001d360', '\U0001d371'), ('\U0001f100', '\U0001f10a')
+    ];
+
+    pub fn No(c: char) -> bool {
+        bsearch_range_table(c, No_table)
+    }
 
-/*
-Function: is_upper
+    static Pc_table : &'static [(char,char)] = &[
+        ('\x5f', '\x5f'), ('\u203f', '\u2040'),
+        ('\u2054', '\u2054'), ('\ufe33', '\ufe34'),
+        ('\ufe4d', '\ufe4f'), ('\uff3f', '\uff3f')
+    ];
+
+    pub fn Pc(c: char) -> bool {
+        bsearch_range_table(c, Pc_table)
+    }
+
+    static Pd_table : &'static [(char,char)] = &[
+        ('\x2d', '\x2d'), ('\u058a', '\u058a'),
+        ('\u05be', '\u05be'), ('\u1400', '\u1400'),
+        ('\u1806', '\u1806'), ('\u2010', '\u2015'),
+        ('\u2e17', '\u2e17'), ('\u2e1a', '\u2e1a'),
+        ('\u2e3a', '\u2e3b'), ('\u301c', '\u301c'),
+        ('\u3030', '\u3030'), ('\u30a0', '\u30a0'),
+        ('\ufe31', '\ufe32'), ('\ufe58', '\ufe58'),
+        ('\ufe63', '\ufe63'), ('\uff0d', '\uff0d')
+    ];
+
+    pub fn Pd(c: char) -> bool {
+        bsearch_range_table(c, Pd_table)
+    }
+
+    static Pe_table : &'static [(char,char)] = &[
+        ('\x29', '\x29'), ('\x5d', '\x5d'),
+        ('\x7d', '\x7d'), ('\u0f3b', '\u0f3b'),
+        ('\u0f3d', '\u0f3d'), ('\u169c', '\u169c'),
+        ('\u2046', '\u2046'), ('\u207e', '\u207e'),
+        ('\u208e', '\u208e'), ('\u232a', '\u232a'),
+        ('\u2769', '\u2769'), ('\u276b', '\u276b'),
+        ('\u276d', '\u276d'), ('\u276f', '\u276f'),
+        ('\u2771', '\u2771'), ('\u2773', '\u2773'),
+        ('\u2775', '\u2775'), ('\u27c6', '\u27c6'),
+        ('\u27e7', '\u27e7'), ('\u27e9', '\u27e9'),
+        ('\u27eb', '\u27eb'), ('\u27ed', '\u27ed'),
+        ('\u27ef', '\u27ef'), ('\u2984', '\u2984'),
+        ('\u2986', '\u2986'), ('\u2988', '\u2988'),
+        ('\u298a', '\u298a'), ('\u298c', '\u298c'),
+        ('\u298e', '\u298e'), ('\u2990', '\u2990'),
+        ('\u2992', '\u2992'), ('\u2994', '\u2994'),
+        ('\u2996', '\u2996'), ('\u2998', '\u2998'),
+        ('\u29d9', '\u29d9'), ('\u29db', '\u29db'),
+        ('\u29fd', '\u29fd'), ('\u2e23', '\u2e23'),
+        ('\u2e25', '\u2e25'), ('\u2e27', '\u2e27'),
+        ('\u2e29', '\u2e29'), ('\u3009', '\u3009'),
+        ('\u300b', '\u300b'), ('\u300d', '\u300d'),
+        ('\u300f', '\u300f'), ('\u3011', '\u3011'),
+        ('\u3015', '\u3015'), ('\u3017', '\u3017'),
+        ('\u3019', '\u3019'), ('\u301b', '\u301b'),
+        ('\u301e', '\u301f'), ('\ufd3f', '\ufd3f'),
+        ('\ufe18', '\ufe18'), ('\ufe36', '\ufe36'),
+        ('\ufe38', '\ufe38'), ('\ufe3a', '\ufe3a'),
+        ('\ufe3c', '\ufe3c'), ('\ufe3e', '\ufe3e'),
+        ('\ufe40', '\ufe40'), ('\ufe42', '\ufe42'),
+        ('\ufe44', '\ufe44'), ('\ufe48', '\ufe48'),
+        ('\ufe5a', '\ufe5a'), ('\ufe5c', '\ufe5c'),
+        ('\ufe5e', '\ufe5e'), ('\uff09', '\uff09'),
+        ('\uff3d', '\uff3d'), ('\uff5d', '\uff5d'),
+        ('\uff60', '\uff60'), ('\uff63', '\uff63')
+    ];
+
+    pub fn Pe(c: char) -> bool {
+        bsearch_range_table(c, Pe_table)
+    }
+
+    static Pf_table : &'static [(char,char)] = &[
+        ('\xbb', '\xbb'), ('\u2019', '\u2019'),
+        ('\u201d', '\u201d'), ('\u203a', '\u203a'),
+        ('\u2e03', '\u2e03'), ('\u2e05', '\u2e05'),
+        ('\u2e0a', '\u2e0a'), ('\u2e0d', '\u2e0d'),
+        ('\u2e1d', '\u2e1d'), ('\u2e21', '\u2e21')
+    ];
+
+    pub fn Pf(c: char) -> bool {
+        bsearch_range_table(c, Pf_table)
+    }
+
+    static Pi_table : &'static [(char,char)] = &[
+        ('\xab', '\xab'), ('\u2018', '\u2018'),
+        ('\u201b', '\u201c'), ('\u201f', '\u201f'),
+        ('\u2039', '\u2039'), ('\u2e02', '\u2e02'),
+        ('\u2e04', '\u2e04'), ('\u2e09', '\u2e09'),
+        ('\u2e0c', '\u2e0c'), ('\u2e1c', '\u2e1c'),
+        ('\u2e20', '\u2e20')
+    ];
+
+    pub fn Pi(c: char) -> bool {
+        bsearch_range_table(c, Pi_table)
+    }
+
+    static Po_table : &'static [(char,char)] = &[
+        ('\x21', '\x23'), ('\x25', '\x27'),
+        ('\x2a', '\x2a'), ('\x2c', '\x2c'),
+        ('\x2e', '\x2f'), ('\x3a', '\x3b'),
+        ('\x3f', '\x40'), ('\x5c', '\x5c'),
+        ('\xa1', '\xa1'), ('\xa7', '\xa7'),
+        ('\xb6', '\xb7'), ('\xbf', '\xbf'),
+        ('\u037e', '\u037e'), ('\u0387', '\u0387'),
+        ('\u055a', '\u055f'), ('\u0589', '\u0589'),
+        ('\u05c0', '\u05c0'), ('\u05c3', '\u05c3'),
+        ('\u05c6', '\u05c6'), ('\u05f3', '\u05f4'),
+        ('\u0609', '\u060a'), ('\u060c', '\u060d'),
+        ('\u061b', '\u061f'), ('\u066a', '\u066d'),
+        ('\u06d4', '\u06d4'), ('\u0700', '\u070d'),
+        ('\u07f7', '\u07f9'), ('\u0830', '\u083e'),
+        ('\u085e', '\u085e'), ('\u0964', '\u0965'),
+        ('\u0970', '\u0970'), ('\u0af0', '\u0af0'),
+        ('\u0df4', '\u0df4'), ('\u0e4f', '\u0e4f'),
+        ('\u0e5a', '\u0e5b'), ('\u0f04', '\u0f12'),
+        ('\u0f14', '\u0f14'), ('\u0f85', '\u0f85'),
+        ('\u0fd0', '\u0fd4'), ('\u0fd9', '\u0fda'),
+        ('\u104a', '\u104f'), ('\u10fb', '\u10fb'),
+        ('\u1360', '\u1368'), ('\u166d', '\u166e'),
+        ('\u16eb', '\u16ed'), ('\u1735', '\u1736'),
+        ('\u17d4', '\u17d6'), ('\u17d8', '\u17da'),
+        ('\u1800', '\u1805'), ('\u1807', '\u180a'),
+        ('\u1944', '\u1945'), ('\u1a1e', '\u1a1f'),
+        ('\u1aa0', '\u1aa6'), ('\u1aa8', '\u1aad'),
+        ('\u1b5a', '\u1b60'), ('\u1bfc', '\u1bff'),
+        ('\u1c3b', '\u1c3f'), ('\u1c7e', '\u1cc7'),
+        ('\u1cd3', '\u1cd3'), ('\u2016', '\u2017'),
+        ('\u2020', '\u2027'), ('\u2030', '\u2038'),
+        ('\u203b', '\u203e'), ('\u2041', '\u2043'),
+        ('\u2047', '\u2051'), ('\u2053', '\u2053'),
+        ('\u2055', '\u205e'), ('\u2cf9', '\u2cfc'),
+        ('\u2cfe', '\u2cff'), ('\u2d70', '\u2d70'),
+        ('\u2e00', '\u2e01'), ('\u2e06', '\u2e08'),
+        ('\u2e0b', '\u2e0b'), ('\u2e0e', '\u2e16'),
+        ('\u2e18', '\u2e19'), ('\u2e1b', '\u2e1b'),
+        ('\u2e1e', '\u2e1f'), ('\u2e2a', '\u2e2e'),
+        ('\u2e30', '\u2e39'), ('\u3001', '\u3003'),
+        ('\u303d', '\u303d'), ('\u30fb', '\u30fb'),
+        ('\ua4fe', '\ua4ff'), ('\ua60d', '\ua60f'),
+        ('\ua673', '\ua673'), ('\ua67e', '\ua67e'),
+        ('\ua6f2', '\ua6f7'), ('\ua874', '\ua877'),
+        ('\ua8ce', '\ua8cf'), ('\ua8f8', '\ua8fa'),
+        ('\ua92e', '\ua92f'), ('\ua95f', '\ua95f'),
+        ('\ua9c1', '\ua9cd'), ('\ua9de', '\ua9df'),
+        ('\uaa5c', '\uaa5f'), ('\uaade', '\uaadf'),
+        ('\uaaf0', '\uaaf1'), ('\uabeb', '\uabeb'),
+        ('\ufe10', '\ufe16'), ('\ufe19', '\ufe19'),
+        ('\ufe30', '\ufe30'), ('\ufe45', '\ufe46'),
+        ('\ufe49', '\ufe4c'), ('\ufe50', '\ufe57'),
+        ('\ufe5f', '\ufe61'), ('\ufe68', '\ufe68'),
+        ('\ufe6a', '\ufe6b'), ('\uff01', '\uff03'),
+        ('\uff05', '\uff07'), ('\uff0a', '\uff0a'),
+        ('\uff0c', '\uff0c'), ('\uff0e', '\uff0f'),
+        ('\uff1a', '\uff1b'), ('\uff1f', '\uff20'),
+        ('\uff3c', '\uff3c'), ('\uff61', '\uff61'),
+        ('\uff64', '\uff65'), ('\U00010100', '\U00010102'),
+        ('\U0001039f', '\U0001039f'), ('\U000103d0', '\U000103d0'),
+        ('\U00010857', '\U00010857'), ('\U0001091f', '\U0001091f'),
+        ('\U0001093f', '\U0001093f'), ('\U00010a50', '\U00010a58'),
+        ('\U00010a7f', '\U00010a7f'), ('\U00010b39', '\U00010b3f'),
+        ('\U00011047', '\U0001104d'), ('\U000110bb', '\U000110bc'),
+        ('\U000110be', '\U000110c1'), ('\U00011140', '\U00011143'),
+        ('\U000111c5', '\U000111c8'), ('\U00012470', '\U00012473')
+    ];
+
+    pub fn Po(c: char) -> bool {
+        bsearch_range_table(c, Po_table)
+    }
+
+    static Ps_table : &'static [(char,char)] = &[
+        ('\x28', '\x28'), ('\x5b', '\x5b'),
+        ('\x7b', '\x7b'), ('\u0f3a', '\u0f3a'),
+        ('\u0f3c', '\u0f3c'), ('\u169b', '\u169b'),
+        ('\u201a', '\u201a'), ('\u201e', '\u201e'),
+        ('\u2045', '\u2045'), ('\u207d', '\u207d'),
+        ('\u208d', '\u208d'), ('\u2329', '\u2329'),
+        ('\u2768', '\u2768'), ('\u276a', '\u276a'),
+        ('\u276c', '\u276c'), ('\u276e', '\u276e'),
+        ('\u2770', '\u2770'), ('\u2772', '\u2772'),
+        ('\u2774', '\u2774'), ('\u27c5', '\u27c5'),
+        ('\u27e6', '\u27e6'), ('\u27e8', '\u27e8'),
+        ('\u27ea', '\u27ea'), ('\u27ec', '\u27ec'),
+        ('\u27ee', '\u27ee'), ('\u2983', '\u2983'),
+        ('\u2985', '\u2985'), ('\u2987', '\u2987'),
+        ('\u2989', '\u2989'), ('\u298b', '\u298b'),
+        ('\u298d', '\u298d'), ('\u298f', '\u298f'),
+        ('\u2991', '\u2991'), ('\u2993', '\u2993'),
+        ('\u2995', '\u2995'), ('\u2997', '\u2997'),
+        ('\u29d8', '\u29d8'), ('\u29da', '\u29da'),
+        ('\u29fc', '\u29fc'), ('\u2e22', '\u2e22'),
+        ('\u2e24', '\u2e24'), ('\u2e26', '\u2e26'),
+        ('\u2e28', '\u2e28'), ('\u3008', '\u3008'),
+        ('\u300a', '\u300a'), ('\u300c', '\u300c'),
+        ('\u300e', '\u300e'), ('\u3010', '\u3010'),
+        ('\u3014', '\u3014'), ('\u3016', '\u3016'),
+        ('\u3018', '\u3018'), ('\u301a', '\u301a'),
+        ('\u301d', '\u301d'), ('\ufd3e', '\ufd3e'),
+        ('\ufe17', '\ufe17'), ('\ufe35', '\ufe35'),
+        ('\ufe37', '\ufe37'), ('\ufe39', '\ufe39'),
+        ('\ufe3b', '\ufe3b'), ('\ufe3d', '\ufe3d'),
+        ('\ufe3f', '\ufe3f'), ('\ufe41', '\ufe41'),
+        ('\ufe43', '\ufe43'), ('\ufe47', '\ufe47'),
+        ('\ufe59', '\ufe59'), ('\ufe5b', '\ufe5b'),
+        ('\ufe5d', '\ufe5d'), ('\uff08', '\uff08'),
+        ('\uff3b', '\uff3b'), ('\uff5b', '\uff5b'),
+        ('\uff5f', '\uff5f'), ('\uff62', '\uff62')
+    ];
+
+    pub fn Ps(c: char) -> bool {
+        bsearch_range_table(c, Ps_table)
+    }
+
+    static Sc_table : &'static [(char,char)] = &[
+        ('\x24', '\x24'), ('\xa2', '\xa5'),
+        ('\u058f', '\u058f'), ('\u060b', '\u060b'),
+        ('\u09f2', '\u09f3'), ('\u09fb', '\u09fb'),
+        ('\u0af1', '\u0af1'), ('\u0bf9', '\u0bf9'),
+        ('\u0e3f', '\u0e3f'), ('\u17db', '\u17db'),
+        ('\u20a0', '\u20ba'), ('\ua838', '\ua838'),
+        ('\ufdfc', '\ufdfc'), ('\ufe69', '\ufe69'),
+        ('\uff04', '\uff04'), ('\uffe0', '\uffe1'),
+        ('\uffe5', '\uffe6')
+    ];
+
+    pub fn Sc(c: char) -> bool {
+        bsearch_range_table(c, Sc_table)
+    }
+
+    static Sk_table : &'static [(char,char)] = &[
+        ('\x5e', '\x5e'), ('\x60', '\x60'),
+        ('\xa8', '\xa8'), ('\xaf', '\xaf'),
+        ('\xb4', '\xb4'), ('\xb8', '\xb8'),
+        ('\u02c2', '\u02c5'), ('\u02d2', '\u02df'),
+        ('\u02e5', '\u02eb'), ('\u02ed', '\u02ed'),
+        ('\u02ef', '\u02ff'), ('\u0375', '\u0375'),
+        ('\u0384', '\u0385'), ('\u1fbd', '\u1fbd'),
+        ('\u1fbf', '\u1fc1'), ('\u1fcd', '\u1fcf'),
+        ('\u1fdd', '\u1fdf'), ('\u1fed', '\u1fef'),
+        ('\u1ffd', '\u1ffe'), ('\u309b', '\u309c'),
+        ('\ua700', '\ua716'), ('\ua720', '\ua721'),
+        ('\ua789', '\ua78a'), ('\ufbb2', '\ufbc1'),
+        ('\uff3e', '\uff3e'), ('\uff40', '\uff40'),
+        ('\uffe3', '\uffe3')
+    ];
+
+    pub fn Sk(c: char) -> bool {
+        bsearch_range_table(c, Sk_table)
+    }
+
+    static Sm_table : &'static [(char,char)] = &[
+        ('\x2b', '\x2b'), ('\x3c', '\x3e'),
+        ('\x7c', '\x7c'), ('\x7e', '\x7e'),
+        ('\xac', '\xac'), ('\xb1', '\xb1'),
+        ('\xd7', '\xd7'), ('\xf7', '\xf7'),
+        ('\u03f6', '\u03f6'), ('\u0606', '\u0608'),
+        ('\u2044', '\u2044'), ('\u2052', '\u2052'),
+        ('\u207a', '\u207c'), ('\u208a', '\u208c'),
+        ('\u2118', '\u2118'), ('\u2140', '\u2144'),
+        ('\u214b', '\u214b'), ('\u2190', '\u2194'),
+        ('\u219a', '\u219b'), ('\u21a0', '\u21a0'),
+        ('\u21a3', '\u21a3'), ('\u21a6', '\u21a6'),
+        ('\u21ae', '\u21ae'), ('\u21ce', '\u21cf'),
+        ('\u21d2', '\u21d2'), ('\u21d4', '\u21d4'),
+        ('\u21f4', '\u22ff'), ('\u2308', '\u230b'),
+        ('\u2320', '\u2321'), ('\u237c', '\u237c'),
+        ('\u239b', '\u23b3'), ('\u23dc', '\u23e1'),
+        ('\u25b7', '\u25b7'), ('\u25c1', '\u25c1'),
+        ('\u25f8', '\u25ff'), ('\u266f', '\u266f'),
+        ('\u27c0', '\u27c4'), ('\u27c7', '\u27e5'),
+        ('\u27f0', '\u27ff'), ('\u2900', '\u2982'),
+        ('\u2999', '\u29d7'), ('\u29dc', '\u29fb'),
+        ('\u29fe', '\u2aff'), ('\u2b30', '\u2b44'),
+        ('\u2b47', '\u2b4c'), ('\ufb29', '\ufb29'),
+        ('\ufe62', '\ufe62'), ('\ufe64', '\ufe66'),
+        ('\uff0b', '\uff0b'), ('\uff1c', '\uff1e'),
+        ('\uff5c', '\uff5c'), ('\uff5e', '\uff5e'),
+        ('\uffe2', '\uffe2'), ('\uffe9', '\uffec'),
+        ('\U0001d6c1', '\U0001d6c1'), ('\U0001d6db', '\U0001d6db'),
+        ('\U0001d6fb', '\U0001d6fb'), ('\U0001d715', '\U0001d715'),
+        ('\U0001d735', '\U0001d735'), ('\U0001d74f', '\U0001d74f'),
+        ('\U0001d76f', '\U0001d76f'), ('\U0001d789', '\U0001d789'),
+        ('\U0001d7a9', '\U0001d7a9'), ('\U0001d7c3', '\U0001d7c3'),
+        ('\U0001eef0', '\U0001eef1')
+    ];
+
+    pub fn Sm(c: char) -> bool {
+        bsearch_range_table(c, Sm_table)
+    }
+
+    static So_table : &'static [(char,char)] = &[
+        ('\xa6', '\xa6'), ('\xa9', '\xa9'),
+        ('\xae', '\xae'), ('\xb0', '\xb0'),
+        ('\u0482', '\u0482'), ('\u060e', '\u060f'),
+        ('\u06de', '\u06de'), ('\u06e9', '\u06e9'),
+        ('\u06fd', '\u06fe'), ('\u07f6', '\u07f6'),
+        ('\u09fa', '\u09fa'), ('\u0b70', '\u0b70'),
+        ('\u0bf3', '\u0bf8'), ('\u0bfa', '\u0bfa'),
+        ('\u0c7f', '\u0c7f'), ('\u0d79', '\u0d79'),
+        ('\u0f01', '\u0f03'), ('\u0f13', '\u0f13'),
+        ('\u0f15', '\u0f17'), ('\u0f1a', '\u0f1f'),
+        ('\u0f34', '\u0f34'), ('\u0f36', '\u0f36'),
+        ('\u0f38', '\u0f38'), ('\u0fbe', '\u0fc5'),
+        ('\u0fc7', '\u0fcf'), ('\u0fd5', '\u0fd8'),
+        ('\u109e', '\u109f'), ('\u1390', '\u1399'),
+        ('\u1940', '\u1940'), ('\u19de', '\u19ff'),
+        ('\u1b61', '\u1b6a'), ('\u1b74', '\u1b7c'),
+        ('\u2100', '\u2101'), ('\u2103', '\u2106'),
+        ('\u2108', '\u2109'), ('\u2114', '\u2114'),
+        ('\u2116', '\u2117'), ('\u211e', '\u2123'),
+        ('\u2125', '\u2125'), ('\u2127', '\u2127'),
+        ('\u2129', '\u2129'), ('\u212e', '\u212e'),
+        ('\u213a', '\u213b'), ('\u214a', '\u214a'),
+        ('\u214c', '\u214d'), ('\u214f', '\u214f'),
+        ('\u2195', '\u2199'), ('\u219c', '\u219f'),
+        ('\u21a1', '\u21a2'), ('\u21a4', '\u21a5'),
+        ('\u21a7', '\u21ad'), ('\u21af', '\u21cd'),
+        ('\u21d0', '\u21d1'), ('\u21d3', '\u21d3'),
+        ('\u21d5', '\u21f3'), ('\u2300', '\u2307'),
+        ('\u230c', '\u231f'), ('\u2322', '\u2328'),
+        ('\u232b', '\u237b'), ('\u237d', '\u239a'),
+        ('\u23b4', '\u23db'), ('\u23e2', '\u244a'),
+        ('\u249c', '\u24e9'), ('\u2500', '\u25b6'),
+        ('\u25b8', '\u25c0'), ('\u25c2', '\u25f7'),
+        ('\u2600', '\u266e'), ('\u2670', '\u2767'),
+        ('\u2794', '\u27bf'), ('\u2800', '\u28ff'),
+        ('\u2b00', '\u2b2f'), ('\u2b45', '\u2b46'),
+        ('\u2b50', '\u2b59'), ('\u2ce5', '\u2cea'),
+        ('\u2e80', '\u2ffb'), ('\u3004', '\u3004'),
+        ('\u3012', '\u3013'), ('\u3020', '\u3020'),
+        ('\u3036', '\u3037'), ('\u303e', '\u303f'),
+        ('\u3190', '\u3191'), ('\u3196', '\u319f'),
+        ('\u31c0', '\u31e3'), ('\u3200', '\u321e'),
+        ('\u322a', '\u3247'), ('\u3250', '\u3250'),
+        ('\u3260', '\u327f'), ('\u328a', '\u32b0'),
+        ('\u32c0', '\u33ff'), ('\u4dc0', '\u4dff'),
+        ('\ua490', '\ua4c6'), ('\ua828', '\ua82b'),
+        ('\ua836', '\ua837'), ('\ua839', '\ua839'),
+        ('\uaa77', '\uaa79'), ('\ufdfd', '\ufdfd'),
+        ('\uffe4', '\uffe4'), ('\uffe8', '\uffe8'),
+        ('\uffed', '\uffee'), ('\ufffc', '\ufffd'),
+        ('\U00010137', '\U0001013f'), ('\U00010179', '\U00010189'),
+        ('\U00010190', '\U000101fc'), ('\U0001d000', '\U0001d164'),
+        ('\U0001d16a', '\U0001d16c'), ('\U0001d183', '\U0001d184'),
+        ('\U0001d18c', '\U0001d1a9'), ('\U0001d1ae', '\U0001d241'),
+        ('\U0001d245', '\U0001d356'), ('\U0001f000', '\U0001f0df'),
+        ('\U0001f110', '\U0001f773')
+    ];
+
+    pub fn So(c: char) -> bool {
+        bsearch_range_table(c, So_table)
+    }
+
+    static Zl_table : &'static [(char,char)] = &[
+        ('\u2028', '\u2028')
+    ];
+
+    pub fn Zl(c: char) -> bool {
+        bsearch_range_table(c, Zl_table)
+    }
+
+    static Zp_table : &'static [(char,char)] = &[
+        ('\u2029', '\u2029')
+    ];
+
+    pub fn Zp(c: char) -> bool {
+        bsearch_range_table(c, Zp_table)
+    }
+
+    static Zs_table : &'static [(char,char)] = &[
+        ('\x20', '\x20'), ('\xa0', '\xa0'),
+        ('\u1680', '\u1680'), ('\u180e', '\u180e'),
+        ('\u2000', '\u200a'), ('\u202f', '\u202f'),
+        ('\u205f', '\u205f'), ('\u3000', '\u3000')
+    ];
+
+    pub fn Zs(c: char) -> bool {
+        bsearch_range_table(c, Zs_table)
+    }
 
-Returns true if a character is an uppercase letter.
-*/
-pub fn is_upper(c: char) -> bool {
-    return icu::libicu::u_isupper(c) == icu::TRUE;
 }
 
-#[cfg(test)]
-mod tests {
+pub mod derived_property {
 
-    #[test]
-    fn test_is_digit() {
-        assert!((unicode::icu::is_digit('0')));
-        assert!((!unicode::icu::is_digit('m')));
+
+    fn bsearch_range_table(c: char, r: &'static [(char,char)]) -> bool {
+        use cmp::{Equal, Less, Greater};
+        use vec::bsearch;
+        use option::None;
+        (do bsearch(r) |&(lo,hi)| {
+            if lo <= c && c <= hi { Equal }
+            else if hi < c { Less }
+            else { Greater }
+        }) != None
     }
 
-    #[test]
-    fn test_is_lower() {
-        assert!((unicode::icu::is_lower('m')));
-        assert!((!unicode::icu::is_lower('M')));
+
+    static Alphabetic_table : &'static [(char,char)] = &[
+        ('\x41', '\x5a'), ('\x61', '\x7a'),
+        ('\xaa', '\xaa'), ('\xb5', '\xb5'),
+        ('\xba', '\xba'), ('\xc0', '\xd6'),
+        ('\xd8', '\xf6'), ('\xf8', '\u01ba'),
+        ('\u01bb', '\u01bb'), ('\u01bc', '\u01bf'),
+        ('\u01c0', '\u01c3'), ('\u01c4', '\u0293'),
+        ('\u0294', '\u0294'), ('\u0295', '\u02af'),
+        ('\u02b0', '\u02c1'), ('\u02c6', '\u02d1'),
+        ('\u02e0', '\u02e4'), ('\u02ec', '\u02ec'),
+        ('\u02ee', '\u02ee'), ('\u0345', '\u0345'),
+        ('\u0370', '\u0373'), ('\u0374', '\u0374'),
+        ('\u0376', '\u0377'), ('\u037a', '\u037a'),
+        ('\u037b', '\u037d'), ('\u0386', '\u0386'),
+        ('\u0388', '\u038a'), ('\u038c', '\u038c'),
+        ('\u038e', '\u03a1'), ('\u03a3', '\u03f5'),
+        ('\u03f7', '\u0481'), ('\u048a', '\u0527'),
+        ('\u0531', '\u0556'), ('\u0559', '\u0559'),
+        ('\u0561', '\u0587'), ('\u05b0', '\u05bd'),
+        ('\u05bf', '\u05bf'), ('\u05c1', '\u05c2'),
+        ('\u05c4', '\u05c5'), ('\u05c7', '\u05c7'),
+        ('\u05d0', '\u05ea'), ('\u05f0', '\u05f2'),
+        ('\u0610', '\u061a'), ('\u0620', '\u063f'),
+        ('\u0640', '\u0640'), ('\u0641', '\u064a'),
+        ('\u064b', '\u0657'), ('\u0659', '\u065f'),
+        ('\u066e', '\u066f'), ('\u0670', '\u0670'),
+        ('\u0671', '\u06d3'), ('\u06d5', '\u06d5'),
+        ('\u06d6', '\u06dc'), ('\u06e1', '\u06e4'),
+        ('\u06e5', '\u06e6'), ('\u06e7', '\u06e8'),
+        ('\u06ed', '\u06ed'), ('\u06ee', '\u06ef'),
+        ('\u06fa', '\u06fc'), ('\u06ff', '\u06ff'),
+        ('\u0710', '\u0710'), ('\u0711', '\u0711'),
+        ('\u0712', '\u072f'), ('\u0730', '\u073f'),
+        ('\u074d', '\u07a5'), ('\u07a6', '\u07b0'),
+        ('\u07b1', '\u07b1'), ('\u07ca', '\u07ea'),
+        ('\u07f4', '\u07f5'), ('\u07fa', '\u07fa'),
+        ('\u0800', '\u0815'), ('\u0816', '\u0817'),
+        ('\u081a', '\u081a'), ('\u081b', '\u0823'),
+        ('\u0824', '\u0824'), ('\u0825', '\u0827'),
+        ('\u0828', '\u0828'), ('\u0829', '\u082c'),
+        ('\u0840', '\u0858'), ('\u08a0', '\u08a0'),
+        ('\u08a2', '\u08ac'), ('\u08e4', '\u08e9'),
+        ('\u08f0', '\u08fe'), ('\u0900', '\u0902'),
+        ('\u0903', '\u0903'), ('\u0904', '\u0939'),
+        ('\u093a', '\u093a'), ('\u093b', '\u093b'),
+        ('\u093d', '\u093d'), ('\u093e', '\u0940'),
+        ('\u0941', '\u0948'), ('\u0949', '\u094c'),
+        ('\u094e', '\u094f'), ('\u0950', '\u0950'),
+        ('\u0955', '\u0957'), ('\u0958', '\u0961'),
+        ('\u0962', '\u0963'), ('\u0971', '\u0971'),
+        ('\u0972', '\u0977'), ('\u0979', '\u097f'),
+        ('\u0981', '\u0981'), ('\u0982', '\u0983'),
+        ('\u0985', '\u098c'), ('\u098f', '\u0990'),
+        ('\u0993', '\u09a8'), ('\u09aa', '\u09b0'),
+        ('\u09b2', '\u09b2'), ('\u09b6', '\u09b9'),
+        ('\u09bd', '\u09bd'), ('\u09be', '\u09c0'),
+        ('\u09c1', '\u09c4'), ('\u09c7', '\u09c8'),
+        ('\u09cb', '\u09cc'), ('\u09ce', '\u09ce'),
+        ('\u09d7', '\u09d7'), ('\u09dc', '\u09dd'),
+        ('\u09df', '\u09e1'), ('\u09e2', '\u09e3'),
+        ('\u09f0', '\u09f1'), ('\u0a01', '\u0a02'),
+        ('\u0a03', '\u0a03'), ('\u0a05', '\u0a0a'),
+        ('\u0a0f', '\u0a10'), ('\u0a13', '\u0a28'),
+        ('\u0a2a', '\u0a30'), ('\u0a32', '\u0a33'),
+        ('\u0a35', '\u0a36'), ('\u0a38', '\u0a39'),
+        ('\u0a3e', '\u0a40'), ('\u0a41', '\u0a42'),
+        ('\u0a47', '\u0a48'), ('\u0a4b', '\u0a4c'),
+        ('\u0a51', '\u0a51'), ('\u0a59', '\u0a5c'),
+        ('\u0a5e', '\u0a5e'), ('\u0a70', '\u0a71'),
+        ('\u0a72', '\u0a74'), ('\u0a75', '\u0a75'),
+        ('\u0a81', '\u0a82'), ('\u0a83', '\u0a83'),
+        ('\u0a85', '\u0a8d'), ('\u0a8f', '\u0a91'),
+        ('\u0a93', '\u0aa8'), ('\u0aaa', '\u0ab0'),
+        ('\u0ab2', '\u0ab3'), ('\u0ab5', '\u0ab9'),
+        ('\u0abd', '\u0abd'), ('\u0abe', '\u0ac0'),
+        ('\u0ac1', '\u0ac5'), ('\u0ac7', '\u0ac8'),
+        ('\u0ac9', '\u0ac9'), ('\u0acb', '\u0acc'),
+        ('\u0ad0', '\u0ad0'), ('\u0ae0', '\u0ae1'),
+        ('\u0ae2', '\u0ae3'), ('\u0b01', '\u0b01'),
+        ('\u0b02', '\u0b03'), ('\u0b05', '\u0b0c'),
+        ('\u0b0f', '\u0b10'), ('\u0b13', '\u0b28'),
+        ('\u0b2a', '\u0b30'), ('\u0b32', '\u0b33'),
+        ('\u0b35', '\u0b39'), ('\u0b3d', '\u0b3d'),
+        ('\u0b3e', '\u0b3e'), ('\u0b3f', '\u0b3f'),
+        ('\u0b40', '\u0b40'), ('\u0b41', '\u0b44'),
+        ('\u0b47', '\u0b48'), ('\u0b4b', '\u0b4c'),
+        ('\u0b56', '\u0b56'), ('\u0b57', '\u0b57'),
+        ('\u0b5c', '\u0b5d'), ('\u0b5f', '\u0b61'),
+        ('\u0b62', '\u0b63'), ('\u0b71', '\u0b71'),
+        ('\u0b82', '\u0b82'), ('\u0b83', '\u0b83'),
+        ('\u0b85', '\u0b8a'), ('\u0b8e', '\u0b90'),
+        ('\u0b92', '\u0b95'), ('\u0b99', '\u0b9a'),
+        ('\u0b9c', '\u0b9c'), ('\u0b9e', '\u0b9f'),
+        ('\u0ba3', '\u0ba4'), ('\u0ba8', '\u0baa'),
+        ('\u0bae', '\u0bb9'), ('\u0bbe', '\u0bbf'),
+        ('\u0bc0', '\u0bc0'), ('\u0bc1', '\u0bc2'),
+        ('\u0bc6', '\u0bc8'), ('\u0bca', '\u0bcc'),
+        ('\u0bd0', '\u0bd0'), ('\u0bd7', '\u0bd7'),
+        ('\u0c01', '\u0c03'), ('\u0c05', '\u0c0c'),
+        ('\u0c0e', '\u0c10'), ('\u0c12', '\u0c28'),
+        ('\u0c2a', '\u0c33'), ('\u0c35', '\u0c39'),
+        ('\u0c3d', '\u0c3d'), ('\u0c3e', '\u0c40'),
+        ('\u0c41', '\u0c44'), ('\u0c46', '\u0c48'),
+        ('\u0c4a', '\u0c4c'), ('\u0c55', '\u0c56'),
+        ('\u0c58', '\u0c59'), ('\u0c60', '\u0c61'),
+        ('\u0c62', '\u0c63'), ('\u0c82', '\u0c83'),
+        ('\u0c85', '\u0c8c'), ('\u0c8e', '\u0c90'),
+        ('\u0c92', '\u0ca8'), ('\u0caa', '\u0cb3'),
+        ('\u0cb5', '\u0cb9'), ('\u0cbd', '\u0cbd'),
+        ('\u0cbe', '\u0cbe'), ('\u0cbf', '\u0cbf'),
+        ('\u0cc0', '\u0cc4'), ('\u0cc6', '\u0cc6'),
+        ('\u0cc7', '\u0cc8'), ('\u0cca', '\u0ccb'),
+        ('\u0ccc', '\u0ccc'), ('\u0cd5', '\u0cd6'),
+        ('\u0cde', '\u0cde'), ('\u0ce0', '\u0ce1'),
+        ('\u0ce2', '\u0ce3'), ('\u0cf1', '\u0cf2'),
+        ('\u0d02', '\u0d03'), ('\u0d05', '\u0d0c'),
+        ('\u0d0e', '\u0d10'), ('\u0d12', '\u0d3a'),
+        ('\u0d3d', '\u0d3d'), ('\u0d3e', '\u0d40'),
+        ('\u0d41', '\u0d44'), ('\u0d46', '\u0d48'),
+        ('\u0d4a', '\u0d4c'), ('\u0d4e', '\u0d4e'),
+        ('\u0d57', '\u0d57'), ('\u0d60', '\u0d61'),
+        ('\u0d62', '\u0d63'), ('\u0d7a', '\u0d7f'),
+        ('\u0d82', '\u0d83'), ('\u0d85', '\u0d96'),
+        ('\u0d9a', '\u0db1'), ('\u0db3', '\u0dbb'),
+        ('\u0dbd', '\u0dbd'), ('\u0dc0', '\u0dc6'),
+        ('\u0dcf', '\u0dd1'), ('\u0dd2', '\u0dd4'),
+        ('\u0dd6', '\u0dd6'), ('\u0dd8', '\u0ddf'),
+        ('\u0df2', '\u0df3'), ('\u0e01', '\u0e30'),
+        ('\u0e31', '\u0e31'), ('\u0e32', '\u0e33'),
+        ('\u0e34', '\u0e3a'), ('\u0e40', '\u0e45'),
+        ('\u0e46', '\u0e46'), ('\u0e4d', '\u0e4d'),
+        ('\u0e81', '\u0e82'), ('\u0e84', '\u0e84'),
+        ('\u0e87', '\u0e88'), ('\u0e8a', '\u0e8a'),
+        ('\u0e8d', '\u0e8d'), ('\u0e94', '\u0e97'),
+        ('\u0e99', '\u0e9f'), ('\u0ea1', '\u0ea3'),
+        ('\u0ea5', '\u0ea5'), ('\u0ea7', '\u0ea7'),
+        ('\u0eaa', '\u0eab'), ('\u0ead', '\u0eb0'),
+        ('\u0eb1', '\u0eb1'), ('\u0eb2', '\u0eb3'),
+        ('\u0eb4', '\u0eb9'), ('\u0ebb', '\u0ebc'),
+        ('\u0ebd', '\u0ebd'), ('\u0ec0', '\u0ec4'),
+        ('\u0ec6', '\u0ec6'), ('\u0ecd', '\u0ecd'),
+        ('\u0edc', '\u0edf'), ('\u0f00', '\u0f00'),
+        ('\u0f40', '\u0f47'), ('\u0f49', '\u0f6c'),
+        ('\u0f71', '\u0f7e'), ('\u0f7f', '\u0f7f'),
+        ('\u0f80', '\u0f81'), ('\u0f88', '\u0f8c'),
+        ('\u0f8d', '\u0f97'), ('\u0f99', '\u0fbc'),
+        ('\u1000', '\u102a'), ('\u102b', '\u102c'),
+        ('\u102d', '\u1030'), ('\u1031', '\u1031'),
+        ('\u1032', '\u1036'), ('\u1038', '\u1038'),
+        ('\u103b', '\u103c'), ('\u103d', '\u103e'),
+        ('\u103f', '\u103f'), ('\u1050', '\u1055'),
+        ('\u1056', '\u1057'), ('\u1058', '\u1059'),
+        ('\u105a', '\u105d'), ('\u105e', '\u1060'),
+        ('\u1061', '\u1061'), ('\u1062', '\u1062'),
+        ('\u1065', '\u1066'), ('\u1067', '\u1068'),
+        ('\u106e', '\u1070'), ('\u1071', '\u1074'),
+        ('\u1075', '\u1081'), ('\u1082', '\u1082'),
+        ('\u1083', '\u1084'), ('\u1085', '\u1086'),
+        ('\u108e', '\u108e'), ('\u109c', '\u109c'),
+        ('\u109d', '\u109d'), ('\u10a0', '\u10c5'),
+        ('\u10c7', '\u10c7'), ('\u10cd', '\u10cd'),
+        ('\u10d0', '\u10fa'), ('\u10fc', '\u10fc'),
+        ('\u10fd', '\u1248'), ('\u124a', '\u124d'),
+        ('\u1250', '\u1256'), ('\u1258', '\u1258'),
+        ('\u125a', '\u125d'), ('\u1260', '\u1288'),
+        ('\u128a', '\u128d'), ('\u1290', '\u12b0'),
+        ('\u12b2', '\u12b5'), ('\u12b8', '\u12be'),
+        ('\u12c0', '\u12c0'), ('\u12c2', '\u12c5'),
+        ('\u12c8', '\u12d6'), ('\u12d8', '\u1310'),
+        ('\u1312', '\u1315'), ('\u1318', '\u135a'),
+        ('\u135f', '\u135f'), ('\u1380', '\u138f'),
+        ('\u13a0', '\u13f4'), ('\u1401', '\u166c'),
+        ('\u166f', '\u167f'), ('\u1681', '\u169a'),
+        ('\u16a0', '\u16ea'), ('\u16ee', '\u16f0'),
+        ('\u1700', '\u170c'), ('\u170e', '\u1711'),
+        ('\u1712', '\u1713'), ('\u1720', '\u1731'),
+        ('\u1732', '\u1733'), ('\u1740', '\u1751'),
+        ('\u1752', '\u1753'), ('\u1760', '\u176c'),
+        ('\u176e', '\u1770'), ('\u1772', '\u1773'),
+        ('\u1780', '\u17b3'), ('\u17b6', '\u17b6'),
+        ('\u17b7', '\u17bd'), ('\u17be', '\u17c5'),
+        ('\u17c6', '\u17c6'), ('\u17c7', '\u17c8'),
+        ('\u17d7', '\u17d7'), ('\u17dc', '\u17dc'),
+        ('\u1820', '\u1842'), ('\u1843', '\u1843'),
+        ('\u1844', '\u1877'), ('\u1880', '\u18a8'),
+        ('\u18a9', '\u18a9'), ('\u18aa', '\u18aa'),
+        ('\u18b0', '\u18f5'), ('\u1900', '\u191c'),
+        ('\u1920', '\u1922'), ('\u1923', '\u1926'),
+        ('\u1927', '\u1928'), ('\u1929', '\u192b'),
+        ('\u1930', '\u1931'), ('\u1932', '\u1932'),
+        ('\u1933', '\u1938'), ('\u1950', '\u196d'),
+        ('\u1970', '\u1974'), ('\u1980', '\u19ab'),
+        ('\u19b0', '\u19c0'), ('\u19c1', '\u19c7'),
+        ('\u19c8', '\u19c9'), ('\u1a00', '\u1a16'),
+        ('\u1a17', '\u1a18'), ('\u1a19', '\u1a1b'),
+        ('\u1a20', '\u1a54'), ('\u1a55', '\u1a55'),
+        ('\u1a56', '\u1a56'), ('\u1a57', '\u1a57'),
+        ('\u1a58', '\u1a5e'), ('\u1a61', '\u1a61'),
+        ('\u1a62', '\u1a62'), ('\u1a63', '\u1a64'),
+        ('\u1a65', '\u1a6c'), ('\u1a6d', '\u1a72'),
+        ('\u1a73', '\u1a74'), ('\u1aa7', '\u1aa7'),
+        ('\u1b00', '\u1b03'), ('\u1b04', '\u1b04'),
+        ('\u1b05', '\u1b33'), ('\u1b35', '\u1b35'),
+        ('\u1b36', '\u1b3a'), ('\u1b3b', '\u1b3b'),
+        ('\u1b3c', '\u1b3c'), ('\u1b3d', '\u1b41'),
+        ('\u1b42', '\u1b42'), ('\u1b43', '\u1b43'),
+        ('\u1b45', '\u1b4b'), ('\u1b80', '\u1b81'),
+        ('\u1b82', '\u1b82'), ('\u1b83', '\u1ba0'),
+        ('\u1ba1', '\u1ba1'), ('\u1ba2', '\u1ba5'),
+        ('\u1ba6', '\u1ba7'), ('\u1ba8', '\u1ba9'),
+        ('\u1bac', '\u1bad'), ('\u1bae', '\u1baf'),
+        ('\u1bba', '\u1be5'), ('\u1be7', '\u1be7'),
+        ('\u1be8', '\u1be9'), ('\u1bea', '\u1bec'),
+        ('\u1bed', '\u1bed'), ('\u1bee', '\u1bee'),
+        ('\u1bef', '\u1bf1'), ('\u1c00', '\u1c23'),
+        ('\u1c24', '\u1c2b'), ('\u1c2c', '\u1c33'),
+        ('\u1c34', '\u1c35'), ('\u1c4d', '\u1c4f'),
+        ('\u1c5a', '\u1c77'), ('\u1c78', '\u1c7d'),
+        ('\u1ce9', '\u1cec'), ('\u1cee', '\u1cf1'),
+        ('\u1cf2', '\u1cf3'), ('\u1cf5', '\u1cf6'),
+        ('\u1d00', '\u1d2b'), ('\u1d2c', '\u1d6a'),
+        ('\u1d6b', '\u1d77'), ('\u1d78', '\u1d78'),
+        ('\u1d79', '\u1d9a'), ('\u1d9b', '\u1dbf'),
+        ('\u1e00', '\u1f15'), ('\u1f18', '\u1f1d'),
+        ('\u1f20', '\u1f45'), ('\u1f48', '\u1f4d'),
+        ('\u1f50', '\u1f57'), ('\u1f59', '\u1f59'),
+        ('\u1f5b', '\u1f5b'), ('\u1f5d', '\u1f5d'),
+        ('\u1f5f', '\u1f7d'), ('\u1f80', '\u1fb4'),
+        ('\u1fb6', '\u1fbc'), ('\u1fbe', '\u1fbe'),
+        ('\u1fc2', '\u1fc4'), ('\u1fc6', '\u1fcc'),
+        ('\u1fd0', '\u1fd3'), ('\u1fd6', '\u1fdb'),
+        ('\u1fe0', '\u1fec'), ('\u1ff2', '\u1ff4'),
+        ('\u1ff6', '\u1ffc'), ('\u2071', '\u2071'),
+        ('\u207f', '\u207f'), ('\u2090', '\u209c'),
+        ('\u2102', '\u2102'), ('\u2107', '\u2107'),
+        ('\u210a', '\u2113'), ('\u2115', '\u2115'),
+        ('\u2119', '\u211d'), ('\u2124', '\u2124'),
+        ('\u2126', '\u2126'), ('\u2128', '\u2128'),
+        ('\u212a', '\u212d'), ('\u212f', '\u2134'),
+        ('\u2135', '\u2138'), ('\u2139', '\u2139'),
+        ('\u213c', '\u213f'), ('\u2145', '\u2149'),
+        ('\u214e', '\u214e'), ('\u2160', '\u2182'),
+        ('\u2183', '\u2184'), ('\u2185', '\u2188'),
+        ('\u24b6', '\u24e9'), ('\u2c00', '\u2c2e'),
+        ('\u2c30', '\u2c5e'), ('\u2c60', '\u2c7b'),
+        ('\u2c7c', '\u2c7d'), ('\u2c7e', '\u2ce4'),
+        ('\u2ceb', '\u2cee'), ('\u2cf2', '\u2cf3'),
+        ('\u2d00', '\u2d25'), ('\u2d27', '\u2d27'),
+        ('\u2d2d', '\u2d2d'), ('\u2d30', '\u2d67'),
+        ('\u2d6f', '\u2d6f'), ('\u2d80', '\u2d96'),
+        ('\u2da0', '\u2da6'), ('\u2da8', '\u2dae'),
+        ('\u2db0', '\u2db6'), ('\u2db8', '\u2dbe'),
+        ('\u2dc0', '\u2dc6'), ('\u2dc8', '\u2dce'),
+        ('\u2dd0', '\u2dd6'), ('\u2dd8', '\u2dde'),
+        ('\u2de0', '\u2dff'), ('\u2e2f', '\u2e2f'),
+        ('\u3005', '\u3005'), ('\u3006', '\u3006'),
+        ('\u3007', '\u3007'), ('\u3021', '\u3029'),
+        ('\u3031', '\u3035'), ('\u3038', '\u303a'),
+        ('\u303b', '\u303b'), ('\u303c', '\u303c'),
+        ('\u3041', '\u3096'), ('\u309d', '\u309e'),
+        ('\u309f', '\u309f'), ('\u30a1', '\u30fa'),
+        ('\u30fc', '\u30fe'), ('\u30ff', '\u30ff'),
+        ('\u3105', '\u312d'), ('\u3131', '\u318e'),
+        ('\u31a0', '\u31ba'), ('\u31f0', '\u31ff'),
+        ('\u3400', '\u4db5'), ('\u4e00', '\u9fcc'),
+        ('\ua000', '\ua014'), ('\ua015', '\ua015'),
+        ('\ua016', '\ua48c'), ('\ua4d0', '\ua4f7'),
+        ('\ua4f8', '\ua4fd'), ('\ua500', '\ua60b'),
+        ('\ua60c', '\ua60c'), ('\ua610', '\ua61f'),
+        ('\ua62a', '\ua62b'), ('\ua640', '\ua66d'),
+        ('\ua66e', '\ua66e'), ('\ua674', '\ua67b'),
+        ('\ua67f', '\ua67f'), ('\ua680', '\ua697'),
+        ('\ua69f', '\ua69f'), ('\ua6a0', '\ua6e5'),
+        ('\ua6e6', '\ua6ef'), ('\ua717', '\ua71f'),
+        ('\ua722', '\ua76f'), ('\ua770', '\ua770'),
+        ('\ua771', '\ua787'), ('\ua788', '\ua788'),
+        ('\ua78b', '\ua78e'), ('\ua790', '\ua793'),
+        ('\ua7a0', '\ua7aa'), ('\ua7f8', '\ua7f9'),
+        ('\ua7fa', '\ua7fa'), ('\ua7fb', '\ua801'),
+        ('\ua803', '\ua805'), ('\ua807', '\ua80a'),
+        ('\ua80c', '\ua822'), ('\ua823', '\ua824'),
+        ('\ua825', '\ua826'), ('\ua827', '\ua827'),
+        ('\ua840', '\ua873'), ('\ua880', '\ua881'),
+        ('\ua882', '\ua8b3'), ('\ua8b4', '\ua8c3'),
+        ('\ua8f2', '\ua8f7'), ('\ua8fb', '\ua8fb'),
+        ('\ua90a', '\ua925'), ('\ua926', '\ua92a'),
+        ('\ua930', '\ua946'), ('\ua947', '\ua951'),
+        ('\ua952', '\ua952'), ('\ua960', '\ua97c'),
+        ('\ua980', '\ua982'), ('\ua983', '\ua983'),
+        ('\ua984', '\ua9b2'), ('\ua9b4', '\ua9b5'),
+        ('\ua9b6', '\ua9b9'), ('\ua9ba', '\ua9bb'),
+        ('\ua9bc', '\ua9bc'), ('\ua9bd', '\ua9bf'),
+        ('\ua9cf', '\ua9cf'), ('\uaa00', '\uaa28'),
+        ('\uaa29', '\uaa2e'), ('\uaa2f', '\uaa30'),
+        ('\uaa31', '\uaa32'), ('\uaa33', '\uaa34'),
+        ('\uaa35', '\uaa36'), ('\uaa40', '\uaa42'),
+        ('\uaa43', '\uaa43'), ('\uaa44', '\uaa4b'),
+        ('\uaa4c', '\uaa4c'), ('\uaa4d', '\uaa4d'),
+        ('\uaa60', '\uaa6f'), ('\uaa70', '\uaa70'),
+        ('\uaa71', '\uaa76'), ('\uaa7a', '\uaa7a'),
+        ('\uaa80', '\uaaaf'), ('\uaab0', '\uaab0'),
+        ('\uaab1', '\uaab1'), ('\uaab2', '\uaab4'),
+        ('\uaab5', '\uaab6'), ('\uaab7', '\uaab8'),
+        ('\uaab9', '\uaabd'), ('\uaabe', '\uaabe'),
+        ('\uaac0', '\uaac0'), ('\uaac2', '\uaac2'),
+        ('\uaadb', '\uaadc'), ('\uaadd', '\uaadd'),
+        ('\uaae0', '\uaaea'), ('\uaaeb', '\uaaeb'),
+        ('\uaaec', '\uaaed'), ('\uaaee', '\uaaef'),
+        ('\uaaf2', '\uaaf2'), ('\uaaf3', '\uaaf4'),
+        ('\uaaf5', '\uaaf5'), ('\uab01', '\uab06'),
+        ('\uab09', '\uab0e'), ('\uab11', '\uab16'),
+        ('\uab20', '\uab26'), ('\uab28', '\uab2e'),
+        ('\uabc0', '\uabe2'), ('\uabe3', '\uabe4'),
+        ('\uabe5', '\uabe5'), ('\uabe6', '\uabe7'),
+        ('\uabe8', '\uabe8'), ('\uabe9', '\uabea'),
+        ('\uac00', '\ud7a3'), ('\ud7b0', '\ud7c6'),
+        ('\ud7cb', '\ud7fb'), ('\uf900', '\ufa6d'),
+        ('\ufa70', '\ufad9'), ('\ufb00', '\ufb06'),
+        ('\ufb13', '\ufb17'), ('\ufb1d', '\ufb1d'),
+        ('\ufb1e', '\ufb1e'), ('\ufb1f', '\ufb28'),
+        ('\ufb2a', '\ufb36'), ('\ufb38', '\ufb3c'),
+        ('\ufb3e', '\ufb3e'), ('\ufb40', '\ufb41'),
+        ('\ufb43', '\ufb44'), ('\ufb46', '\ufbb1'),
+        ('\ufbd3', '\ufd3d'), ('\ufd50', '\ufd8f'),
+        ('\ufd92', '\ufdc7'), ('\ufdf0', '\ufdfb'),
+        ('\ufe70', '\ufe74'), ('\ufe76', '\ufefc'),
+        ('\uff21', '\uff3a'), ('\uff41', '\uff5a'),
+        ('\uff66', '\uff6f'), ('\uff70', '\uff70'),
+        ('\uff71', '\uff9d'), ('\uff9e', '\uff9f'),
+        ('\uffa0', '\uffbe'), ('\uffc2', '\uffc7'),
+        ('\uffca', '\uffcf'), ('\uffd2', '\uffd7'),
+        ('\uffda', '\uffdc'), ('\U00010000', '\U0001000b'),
+        ('\U0001000d', '\U00010026'), ('\U00010028', '\U0001003a'),
+        ('\U0001003c', '\U0001003d'), ('\U0001003f', '\U0001004d'),
+        ('\U00010050', '\U0001005d'), ('\U00010080', '\U000100fa'),
+        ('\U00010140', '\U00010174'), ('\U00010280', '\U0001029c'),
+        ('\U000102a0', '\U000102d0'), ('\U00010300', '\U0001031e'),
+        ('\U00010330', '\U00010340'), ('\U00010341', '\U00010341'),
+        ('\U00010342', '\U00010349'), ('\U0001034a', '\U0001034a'),
+        ('\U00010380', '\U0001039d'), ('\U000103a0', '\U000103c3'),
+        ('\U000103c8', '\U000103cf'), ('\U000103d1', '\U000103d5'),
+        ('\U00010400', '\U0001044f'), ('\U00010450', '\U0001049d'),
+        ('\U00010800', '\U00010805'), ('\U00010808', '\U00010808'),
+        ('\U0001080a', '\U00010835'), ('\U00010837', '\U00010838'),
+        ('\U0001083c', '\U0001083c'), ('\U0001083f', '\U00010855'),
+        ('\U00010900', '\U00010915'), ('\U00010920', '\U00010939'),
+        ('\U00010980', '\U000109b7'), ('\U000109be', '\U000109bf'),
+        ('\U00010a00', '\U00010a00'), ('\U00010a01', '\U00010a03'),
+        ('\U00010a05', '\U00010a06'), ('\U00010a0c', '\U00010a0f'),
+        ('\U00010a10', '\U00010a13'), ('\U00010a15', '\U00010a17'),
+        ('\U00010a19', '\U00010a33'), ('\U00010a60', '\U00010a7c'),
+        ('\U00010b00', '\U00010b35'), ('\U00010b40', '\U00010b55'),
+        ('\U00010b60', '\U00010b72'), ('\U00010c00', '\U00010c48'),
+        ('\U00011000', '\U00011000'), ('\U00011001', '\U00011001'),
+        ('\U00011002', '\U00011002'), ('\U00011003', '\U00011037'),
+        ('\U00011038', '\U00011045'), ('\U00011082', '\U00011082'),
+        ('\U00011083', '\U000110af'), ('\U000110b0', '\U000110b2'),
+        ('\U000110b3', '\U000110b6'), ('\U000110b7', '\U000110b8'),
+        ('\U000110d0', '\U000110e8'), ('\U00011100', '\U00011102'),
+        ('\U00011103', '\U00011126'), ('\U00011127', '\U0001112b'),
+        ('\U0001112c', '\U0001112c'), ('\U0001112d', '\U00011132'),
+        ('\U00011180', '\U00011181'), ('\U00011182', '\U00011182'),
+        ('\U00011183', '\U000111b2'), ('\U000111b3', '\U000111b5'),
+        ('\U000111b6', '\U000111be'), ('\U000111bf', '\U000111bf'),
+        ('\U000111c1', '\U000111c4'), ('\U00011680', '\U000116aa'),
+        ('\U000116ab', '\U000116ab'), ('\U000116ac', '\U000116ac'),
+        ('\U000116ad', '\U000116ad'), ('\U000116ae', '\U000116af'),
+        ('\U000116b0', '\U000116b5'), ('\U00012000', '\U0001236e'),
+        ('\U00012400', '\U00012462'), ('\U00013000', '\U0001342e'),
+        ('\U00016800', '\U00016a38'), ('\U00016f00', '\U00016f44'),
+        ('\U00016f50', '\U00016f50'), ('\U00016f51', '\U00016f7e'),
+        ('\U00016f93', '\U00016f9f'), ('\U0001b000', '\U0001b001'),
+        ('\U0001d400', '\U0001d454'), ('\U0001d456', '\U0001d49c'),
+        ('\U0001d49e', '\U0001d49f'), ('\U0001d4a2', '\U0001d4a2'),
+        ('\U0001d4a5', '\U0001d4a6'), ('\U0001d4a9', '\U0001d4ac'),
+        ('\U0001d4ae', '\U0001d4b9'), ('\U0001d4bb', '\U0001d4bb'),
+        ('\U0001d4bd', '\U0001d4c3'), ('\U0001d4c5', '\U0001d505'),
+        ('\U0001d507', '\U0001d50a'), ('\U0001d50d', '\U0001d514'),
+        ('\U0001d516', '\U0001d51c'), ('\U0001d51e', '\U0001d539'),
+        ('\U0001d53b', '\U0001d53e'), ('\U0001d540', '\U0001d544'),
+        ('\U0001d546', '\U0001d546'), ('\U0001d54a', '\U0001d550'),
+        ('\U0001d552', '\U0001d6a5'), ('\U0001d6a8', '\U0001d6c0'),
+        ('\U0001d6c2', '\U0001d6da'), ('\U0001d6dc', '\U0001d6fa'),
+        ('\U0001d6fc', '\U0001d714'), ('\U0001d716', '\U0001d734'),
+        ('\U0001d736', '\U0001d74e'), ('\U0001d750', '\U0001d76e'),
+        ('\U0001d770', '\U0001d788'), ('\U0001d78a', '\U0001d7a8'),
+        ('\U0001d7aa', '\U0001d7c2'), ('\U0001d7c4', '\U0001d7cb'),
+        ('\U0001ee00', '\U0001ee03'), ('\U0001ee05', '\U0001ee1f'),
+        ('\U0001ee21', '\U0001ee22'), ('\U0001ee24', '\U0001ee24'),
+        ('\U0001ee27', '\U0001ee27'), ('\U0001ee29', '\U0001ee32'),
+        ('\U0001ee34', '\U0001ee37'), ('\U0001ee39', '\U0001ee39'),
+        ('\U0001ee3b', '\U0001ee3b'), ('\U0001ee42', '\U0001ee42'),
+        ('\U0001ee47', '\U0001ee47'), ('\U0001ee49', '\U0001ee49'),
+        ('\U0001ee4b', '\U0001ee4b'), ('\U0001ee4d', '\U0001ee4f'),
+        ('\U0001ee51', '\U0001ee52'), ('\U0001ee54', '\U0001ee54'),
+        ('\U0001ee57', '\U0001ee57'), ('\U0001ee59', '\U0001ee59'),
+        ('\U0001ee5b', '\U0001ee5b'), ('\U0001ee5d', '\U0001ee5d'),
+        ('\U0001ee5f', '\U0001ee5f'), ('\U0001ee61', '\U0001ee62'),
+        ('\U0001ee64', '\U0001ee64'), ('\U0001ee67', '\U0001ee6a'),
+        ('\U0001ee6c', '\U0001ee72'), ('\U0001ee74', '\U0001ee77'),
+        ('\U0001ee79', '\U0001ee7c'), ('\U0001ee7e', '\U0001ee7e'),
+        ('\U0001ee80', '\U0001ee89'), ('\U0001ee8b', '\U0001ee9b'),
+        ('\U0001eea1', '\U0001eea3'), ('\U0001eea5', '\U0001eea9'),
+        ('\U0001eeab', '\U0001eebb'), ('\U00020000', '\U0002a6d6'),
+        ('\U0002a700', '\U0002b734'), ('\U0002b740', '\U0002b81d'),
+        ('\U0002f800', '\U0002fa1d')
+    ];
+
+    pub fn Alphabetic(c: char) -> bool {
+        bsearch_range_table(c, Alphabetic_table)
     }
 
-    #[test]
-    fn test_is_space() {
-        assert!((unicode::icu::is_space(' ')));
-        assert!((!unicode::icu::is_space('m')));
+    static XID_Continue_table : &'static [(char,char)] = &[
+        ('\x30', '\x39'), ('\x41', '\x5a'),
+        ('\x5f', '\x5f'), ('\x61', '\x7a'),
+        ('\xaa', '\xaa'), ('\xb5', '\xb5'),
+        ('\xb7', '\xb7'), ('\xba', '\xba'),
+        ('\xc0', '\xd6'), ('\xd8', '\xf6'),
+        ('\xf8', '\u01ba'), ('\u01bb', '\u01bb'),
+        ('\u01bc', '\u01bf'), ('\u01c0', '\u01c3'),
+        ('\u01c4', '\u0293'), ('\u0294', '\u0294'),
+        ('\u0295', '\u02af'), ('\u02b0', '\u02c1'),
+        ('\u02c6', '\u02d1'), ('\u02e0', '\u02e4'),
+        ('\u02ec', '\u02ec'), ('\u02ee', '\u02ee'),
+        ('\u0300', '\u036f'), ('\u0370', '\u0373'),
+        ('\u0374', '\u0374'), ('\u0376', '\u0377'),
+        ('\u037b', '\u037d'), ('\u0386', '\u0386'),
+        ('\u0387', '\u0387'), ('\u0388', '\u038a'),
+        ('\u038c', '\u038c'), ('\u038e', '\u03a1'),
+        ('\u03a3', '\u03f5'), ('\u03f7', '\u0481'),
+        ('\u0483', '\u0487'), ('\u048a', '\u0527'),
+        ('\u0531', '\u0556'), ('\u0559', '\u0559'),
+        ('\u0561', '\u0587'), ('\u0591', '\u05bd'),
+        ('\u05bf', '\u05bf'), ('\u05c1', '\u05c2'),
+        ('\u05c4', '\u05c5'), ('\u05c7', '\u05c7'),
+        ('\u05d0', '\u05ea'), ('\u05f0', '\u05f2'),
+        ('\u0610', '\u061a'), ('\u0620', '\u063f'),
+        ('\u0640', '\u0640'), ('\u0641', '\u064a'),
+        ('\u064b', '\u065f'), ('\u0660', '\u0669'),
+        ('\u066e', '\u066f'), ('\u0670', '\u0670'),
+        ('\u0671', '\u06d3'), ('\u06d5', '\u06d5'),
+        ('\u06d6', '\u06dc'), ('\u06df', '\u06e4'),
+        ('\u06e5', '\u06e6'), ('\u06e7', '\u06e8'),
+        ('\u06ea', '\u06ed'), ('\u06ee', '\u06ef'),
+        ('\u06f0', '\u06f9'), ('\u06fa', '\u06fc'),
+        ('\u06ff', '\u06ff'), ('\u0710', '\u0710'),
+        ('\u0711', '\u0711'), ('\u0712', '\u072f'),
+        ('\u0730', '\u074a'), ('\u074d', '\u07a5'),
+        ('\u07a6', '\u07b0'), ('\u07b1', '\u07b1'),
+        ('\u07c0', '\u07c9'), ('\u07ca', '\u07ea'),
+        ('\u07eb', '\u07f3'), ('\u07f4', '\u07f5'),
+        ('\u07fa', '\u07fa'), ('\u0800', '\u0815'),
+        ('\u0816', '\u0819'), ('\u081a', '\u081a'),
+        ('\u081b', '\u0823'), ('\u0824', '\u0824'),
+        ('\u0825', '\u0827'), ('\u0828', '\u0828'),
+        ('\u0829', '\u082d'), ('\u0840', '\u0858'),
+        ('\u0859', '\u085b'), ('\u08a0', '\u08a0'),
+        ('\u08a2', '\u08ac'), ('\u08e4', '\u08fe'),
+        ('\u0900', '\u0902'), ('\u0903', '\u0903'),
+        ('\u0904', '\u0939'), ('\u093a', '\u093a'),
+        ('\u093b', '\u093b'), ('\u093c', '\u093c'),
+        ('\u093d', '\u093d'), ('\u093e', '\u0940'),
+        ('\u0941', '\u0948'), ('\u0949', '\u094c'),
+        ('\u094d', '\u094d'), ('\u094e', '\u094f'),
+        ('\u0950', '\u0950'), ('\u0951', '\u0957'),
+        ('\u0958', '\u0961'), ('\u0962', '\u0963'),
+        ('\u0966', '\u096f'), ('\u0971', '\u0971'),
+        ('\u0972', '\u0977'), ('\u0979', '\u097f'),
+        ('\u0981', '\u0981'), ('\u0982', '\u0983'),
+        ('\u0985', '\u098c'), ('\u098f', '\u0990'),
+        ('\u0993', '\u09a8'), ('\u09aa', '\u09b0'),
+        ('\u09b2', '\u09b2'), ('\u09b6', '\u09b9'),
+        ('\u09bc', '\u09bc'), ('\u09bd', '\u09bd'),
+        ('\u09be', '\u09c0'), ('\u09c1', '\u09c4'),
+        ('\u09c7', '\u09c8'), ('\u09cb', '\u09cc'),
+        ('\u09cd', '\u09cd'), ('\u09ce', '\u09ce'),
+        ('\u09d7', '\u09d7'), ('\u09dc', '\u09dd'),
+        ('\u09df', '\u09e1'), ('\u09e2', '\u09e3'),
+        ('\u09e6', '\u09ef'), ('\u09f0', '\u09f1'),
+        ('\u0a01', '\u0a02'), ('\u0a03', '\u0a03'),
+        ('\u0a05', '\u0a0a'), ('\u0a0f', '\u0a10'),
+        ('\u0a13', '\u0a28'), ('\u0a2a', '\u0a30'),
+        ('\u0a32', '\u0a33'), ('\u0a35', '\u0a36'),
+        ('\u0a38', '\u0a39'), ('\u0a3c', '\u0a3c'),
+        ('\u0a3e', '\u0a40'), ('\u0a41', '\u0a42'),
+        ('\u0a47', '\u0a48'), ('\u0a4b', '\u0a4d'),
+        ('\u0a51', '\u0a51'), ('\u0a59', '\u0a5c'),
+        ('\u0a5e', '\u0a5e'), ('\u0a66', '\u0a6f'),
+        ('\u0a70', '\u0a71'), ('\u0a72', '\u0a74'),
+        ('\u0a75', '\u0a75'), ('\u0a81', '\u0a82'),
+        ('\u0a83', '\u0a83'), ('\u0a85', '\u0a8d'),
+        ('\u0a8f', '\u0a91'), ('\u0a93', '\u0aa8'),
+        ('\u0aaa', '\u0ab0'), ('\u0ab2', '\u0ab3'),
+        ('\u0ab5', '\u0ab9'), ('\u0abc', '\u0abc'),
+        ('\u0abd', '\u0abd'), ('\u0abe', '\u0ac0'),
+        ('\u0ac1', '\u0ac5'), ('\u0ac7', '\u0ac8'),
+        ('\u0ac9', '\u0ac9'), ('\u0acb', '\u0acc'),
+        ('\u0acd', '\u0acd'), ('\u0ad0', '\u0ad0'),
+        ('\u0ae0', '\u0ae1'), ('\u0ae2', '\u0ae3'),
+        ('\u0ae6', '\u0aef'), ('\u0b01', '\u0b01'),
+        ('\u0b02', '\u0b03'), ('\u0b05', '\u0b0c'),
+        ('\u0b0f', '\u0b10'), ('\u0b13', '\u0b28'),
+        ('\u0b2a', '\u0b30'), ('\u0b32', '\u0b33'),
+        ('\u0b35', '\u0b39'), ('\u0b3c', '\u0b3c'),
+        ('\u0b3d', '\u0b3d'), ('\u0b3e', '\u0b3e'),
+        ('\u0b3f', '\u0b3f'), ('\u0b40', '\u0b40'),
+        ('\u0b41', '\u0b44'), ('\u0b47', '\u0b48'),
+        ('\u0b4b', '\u0b4c'), ('\u0b4d', '\u0b4d'),
+        ('\u0b56', '\u0b56'), ('\u0b57', '\u0b57'),
+        ('\u0b5c', '\u0b5d'), ('\u0b5f', '\u0b61'),
+        ('\u0b62', '\u0b63'), ('\u0b66', '\u0b6f'),
+        ('\u0b71', '\u0b71'), ('\u0b82', '\u0b82'),
+        ('\u0b83', '\u0b83'), ('\u0b85', '\u0b8a'),
+        ('\u0b8e', '\u0b90'), ('\u0b92', '\u0b95'),
+        ('\u0b99', '\u0b9a'), ('\u0b9c', '\u0b9c'),
+        ('\u0b9e', '\u0b9f'), ('\u0ba3', '\u0ba4'),
+        ('\u0ba8', '\u0baa'), ('\u0bae', '\u0bb9'),
+        ('\u0bbe', '\u0bbf'), ('\u0bc0', '\u0bc0'),
+        ('\u0bc1', '\u0bc2'), ('\u0bc6', '\u0bc8'),
+        ('\u0bca', '\u0bcc'), ('\u0bcd', '\u0bcd'),
+        ('\u0bd0', '\u0bd0'), ('\u0bd7', '\u0bd7'),
+        ('\u0be6', '\u0bef'), ('\u0c01', '\u0c03'),
+        ('\u0c05', '\u0c0c'), ('\u0c0e', '\u0c10'),
+        ('\u0c12', '\u0c28'), ('\u0c2a', '\u0c33'),
+        ('\u0c35', '\u0c39'), ('\u0c3d', '\u0c3d'),
+        ('\u0c3e', '\u0c40'), ('\u0c41', '\u0c44'),
+        ('\u0c46', '\u0c48'), ('\u0c4a', '\u0c4d'),
+        ('\u0c55', '\u0c56'), ('\u0c58', '\u0c59'),
+        ('\u0c60', '\u0c61'), ('\u0c62', '\u0c63'),
+        ('\u0c66', '\u0c6f'), ('\u0c82', '\u0c83'),
+        ('\u0c85', '\u0c8c'), ('\u0c8e', '\u0c90'),
+        ('\u0c92', '\u0ca8'), ('\u0caa', '\u0cb3'),
+        ('\u0cb5', '\u0cb9'), ('\u0cbc', '\u0cbc'),
+        ('\u0cbd', '\u0cbd'), ('\u0cbe', '\u0cbe'),
+        ('\u0cbf', '\u0cbf'), ('\u0cc0', '\u0cc4'),
+        ('\u0cc6', '\u0cc6'), ('\u0cc7', '\u0cc8'),
+        ('\u0cca', '\u0ccb'), ('\u0ccc', '\u0ccd'),
+        ('\u0cd5', '\u0cd6'), ('\u0cde', '\u0cde'),
+        ('\u0ce0', '\u0ce1'), ('\u0ce2', '\u0ce3'),
+        ('\u0ce6', '\u0cef'), ('\u0cf1', '\u0cf2'),
+        ('\u0d02', '\u0d03'), ('\u0d05', '\u0d0c'),
+        ('\u0d0e', '\u0d10'), ('\u0d12', '\u0d3a'),
+        ('\u0d3d', '\u0d3d'), ('\u0d3e', '\u0d40'),
+        ('\u0d41', '\u0d44'), ('\u0d46', '\u0d48'),
+        ('\u0d4a', '\u0d4c'), ('\u0d4d', '\u0d4d'),
+        ('\u0d4e', '\u0d4e'), ('\u0d57', '\u0d57'),
+        ('\u0d60', '\u0d61'), ('\u0d62', '\u0d63'),
+        ('\u0d66', '\u0d6f'), ('\u0d7a', '\u0d7f'),
+        ('\u0d82', '\u0d83'), ('\u0d85', '\u0d96'),
+        ('\u0d9a', '\u0db1'), ('\u0db3', '\u0dbb'),
+        ('\u0dbd', '\u0dbd'), ('\u0dc0', '\u0dc6'),
+        ('\u0dca', '\u0dca'), ('\u0dcf', '\u0dd1'),
+        ('\u0dd2', '\u0dd4'), ('\u0dd6', '\u0dd6'),
+        ('\u0dd8', '\u0ddf'), ('\u0df2', '\u0df3'),
+        ('\u0e01', '\u0e30'), ('\u0e31', '\u0e31'),
+        ('\u0e32', '\u0e33'), ('\u0e34', '\u0e3a'),
+        ('\u0e40', '\u0e45'), ('\u0e46', '\u0e46'),
+        ('\u0e47', '\u0e4e'), ('\u0e50', '\u0e59'),
+        ('\u0e81', '\u0e82'), ('\u0e84', '\u0e84'),
+        ('\u0e87', '\u0e88'), ('\u0e8a', '\u0e8a'),
+        ('\u0e8d', '\u0e8d'), ('\u0e94', '\u0e97'),
+        ('\u0e99', '\u0e9f'), ('\u0ea1', '\u0ea3'),
+        ('\u0ea5', '\u0ea5'), ('\u0ea7', '\u0ea7'),
+        ('\u0eaa', '\u0eab'), ('\u0ead', '\u0eb0'),
+        ('\u0eb1', '\u0eb1'), ('\u0eb2', '\u0eb3'),
+        ('\u0eb4', '\u0eb9'), ('\u0ebb', '\u0ebc'),
+        ('\u0ebd', '\u0ebd'), ('\u0ec0', '\u0ec4'),
+        ('\u0ec6', '\u0ec6'), ('\u0ec8', '\u0ecd'),
+        ('\u0ed0', '\u0ed9'), ('\u0edc', '\u0edf'),
+        ('\u0f00', '\u0f00'), ('\u0f18', '\u0f19'),
+        ('\u0f20', '\u0f29'), ('\u0f35', '\u0f35'),
+        ('\u0f37', '\u0f37'), ('\u0f39', '\u0f39'),
+        ('\u0f3e', '\u0f3f'), ('\u0f40', '\u0f47'),
+        ('\u0f49', '\u0f6c'), ('\u0f71', '\u0f7e'),
+        ('\u0f7f', '\u0f7f'), ('\u0f80', '\u0f84'),
+        ('\u0f86', '\u0f87'), ('\u0f88', '\u0f8c'),
+        ('\u0f8d', '\u0f97'), ('\u0f99', '\u0fbc'),
+        ('\u0fc6', '\u0fc6'), ('\u1000', '\u102a'),
+        ('\u102b', '\u102c'), ('\u102d', '\u1030'),
+        ('\u1031', '\u1031'), ('\u1032', '\u1037'),
+        ('\u1038', '\u1038'), ('\u1039', '\u103a'),
+        ('\u103b', '\u103c'), ('\u103d', '\u103e'),
+        ('\u103f', '\u103f'), ('\u1040', '\u1049'),
+        ('\u1050', '\u1055'), ('\u1056', '\u1057'),
+        ('\u1058', '\u1059'), ('\u105a', '\u105d'),
+        ('\u105e', '\u1060'), ('\u1061', '\u1061'),
+        ('\u1062', '\u1064'), ('\u1065', '\u1066'),
+        ('\u1067', '\u106d'), ('\u106e', '\u1070'),
+        ('\u1071', '\u1074'), ('\u1075', '\u1081'),
+        ('\u1082', '\u1082'), ('\u1083', '\u1084'),
+        ('\u1085', '\u1086'), ('\u1087', '\u108c'),
+        ('\u108d', '\u108d'), ('\u108e', '\u108e'),
+        ('\u108f', '\u108f'), ('\u1090', '\u1099'),
+        ('\u109a', '\u109c'), ('\u109d', '\u109d'),
+        ('\u10a0', '\u10c5'), ('\u10c7', '\u10c7'),
+        ('\u10cd', '\u10cd'), ('\u10d0', '\u10fa'),
+        ('\u10fc', '\u10fc'), ('\u10fd', '\u1248'),
+        ('\u124a', '\u124d'), ('\u1250', '\u1256'),
+        ('\u1258', '\u1258'), ('\u125a', '\u125d'),
+        ('\u1260', '\u1288'), ('\u128a', '\u128d'),
+        ('\u1290', '\u12b0'), ('\u12b2', '\u12b5'),
+        ('\u12b8', '\u12be'), ('\u12c0', '\u12c0'),
+        ('\u12c2', '\u12c5'), ('\u12c8', '\u12d6'),
+        ('\u12d8', '\u1310'), ('\u1312', '\u1315'),
+        ('\u1318', '\u135a'), ('\u135d', '\u135f'),
+        ('\u1369', '\u1371'), ('\u1380', '\u138f'),
+        ('\u13a0', '\u13f4'), ('\u1401', '\u166c'),
+        ('\u166f', '\u167f'), ('\u1681', '\u169a'),
+        ('\u16a0', '\u16ea'), ('\u16ee', '\u16f0'),
+        ('\u1700', '\u170c'), ('\u170e', '\u1711'),
+        ('\u1712', '\u1714'), ('\u1720', '\u1731'),
+        ('\u1732', '\u1734'), ('\u1740', '\u1751'),
+        ('\u1752', '\u1753'), ('\u1760', '\u176c'),
+        ('\u176e', '\u1770'), ('\u1772', '\u1773'),
+        ('\u1780', '\u17b3'), ('\u17b4', '\u17b5'),
+        ('\u17b6', '\u17b6'), ('\u17b7', '\u17bd'),
+        ('\u17be', '\u17c5'), ('\u17c6', '\u17c6'),
+        ('\u17c7', '\u17c8'), ('\u17c9', '\u17d3'),
+        ('\u17d7', '\u17d7'), ('\u17dc', '\u17dc'),
+        ('\u17dd', '\u17dd'), ('\u17e0', '\u17e9'),
+        ('\u180b', '\u180d'), ('\u1810', '\u1819'),
+        ('\u1820', '\u1842'), ('\u1843', '\u1843'),
+        ('\u1844', '\u1877'), ('\u1880', '\u18a8'),
+        ('\u18a9', '\u18a9'), ('\u18aa', '\u18aa'),
+        ('\u18b0', '\u18f5'), ('\u1900', '\u191c'),
+        ('\u1920', '\u1922'), ('\u1923', '\u1926'),
+        ('\u1927', '\u1928'), ('\u1929', '\u192b'),
+        ('\u1930', '\u1931'), ('\u1932', '\u1932'),
+        ('\u1933', '\u1938'), ('\u1939', '\u193b'),
+        ('\u1946', '\u194f'), ('\u1950', '\u196d'),
+        ('\u1970', '\u1974'), ('\u1980', '\u19ab'),
+        ('\u19b0', '\u19c0'), ('\u19c1', '\u19c7'),
+        ('\u19c8', '\u19c9'), ('\u19d0', '\u19d9'),
+        ('\u19da', '\u19da'), ('\u1a00', '\u1a16'),
+        ('\u1a17', '\u1a18'), ('\u1a19', '\u1a1b'),
+        ('\u1a20', '\u1a54'), ('\u1a55', '\u1a55'),
+        ('\u1a56', '\u1a56'), ('\u1a57', '\u1a57'),
+        ('\u1a58', '\u1a5e'), ('\u1a60', '\u1a60'),
+        ('\u1a61', '\u1a61'), ('\u1a62', '\u1a62'),
+        ('\u1a63', '\u1a64'), ('\u1a65', '\u1a6c'),
+        ('\u1a6d', '\u1a72'), ('\u1a73', '\u1a7c'),
+        ('\u1a7f', '\u1a7f'), ('\u1a80', '\u1a89'),
+        ('\u1a90', '\u1a99'), ('\u1aa7', '\u1aa7'),
+        ('\u1b00', '\u1b03'), ('\u1b04', '\u1b04'),
+        ('\u1b05', '\u1b33'), ('\u1b34', '\u1b34'),
+        ('\u1b35', '\u1b35'), ('\u1b36', '\u1b3a'),
+        ('\u1b3b', '\u1b3b'), ('\u1b3c', '\u1b3c'),
+        ('\u1b3d', '\u1b41'), ('\u1b42', '\u1b42'),
+        ('\u1b43', '\u1b44'), ('\u1b45', '\u1b4b'),
+        ('\u1b50', '\u1b59'), ('\u1b6b', '\u1b73'),
+        ('\u1b80', '\u1b81'), ('\u1b82', '\u1b82'),
+        ('\u1b83', '\u1ba0'), ('\u1ba1', '\u1ba1'),
+        ('\u1ba2', '\u1ba5'), ('\u1ba6', '\u1ba7'),
+        ('\u1ba8', '\u1ba9'), ('\u1baa', '\u1baa'),
+        ('\u1bab', '\u1bab'), ('\u1bac', '\u1bad'),
+        ('\u1bae', '\u1baf'), ('\u1bb0', '\u1bb9'),
+        ('\u1bba', '\u1be5'), ('\u1be6', '\u1be6'),
+        ('\u1be7', '\u1be7'), ('\u1be8', '\u1be9'),
+        ('\u1bea', '\u1bec'), ('\u1bed', '\u1bed'),
+        ('\u1bee', '\u1bee'), ('\u1bef', '\u1bf1'),
+        ('\u1bf2', '\u1bf3'), ('\u1c00', '\u1c23'),
+        ('\u1c24', '\u1c2b'), ('\u1c2c', '\u1c33'),
+        ('\u1c34', '\u1c35'), ('\u1c36', '\u1c37'),
+        ('\u1c40', '\u1c49'), ('\u1c4d', '\u1c4f'),
+        ('\u1c50', '\u1c59'), ('\u1c5a', '\u1c77'),
+        ('\u1c78', '\u1c7d'), ('\u1cd0', '\u1cd2'),
+        ('\u1cd4', '\u1ce0'), ('\u1ce1', '\u1ce1'),
+        ('\u1ce2', '\u1ce8'), ('\u1ce9', '\u1cec'),
+        ('\u1ced', '\u1ced'), ('\u1cee', '\u1cf1'),
+        ('\u1cf2', '\u1cf3'), ('\u1cf4', '\u1cf4'),
+        ('\u1cf5', '\u1cf6'), ('\u1d00', '\u1d2b'),
+        ('\u1d2c', '\u1d6a'), ('\u1d6b', '\u1d77'),
+        ('\u1d78', '\u1d78'), ('\u1d79', '\u1d9a'),
+        ('\u1d9b', '\u1dbf'), ('\u1dc0', '\u1de6'),
+        ('\u1dfc', '\u1dff'), ('\u1e00', '\u1f15'),
+        ('\u1f18', '\u1f1d'), ('\u1f20', '\u1f45'),
+        ('\u1f48', '\u1f4d'), ('\u1f50', '\u1f57'),
+        ('\u1f59', '\u1f59'), ('\u1f5b', '\u1f5b'),
+        ('\u1f5d', '\u1f5d'), ('\u1f5f', '\u1f7d'),
+        ('\u1f80', '\u1fb4'), ('\u1fb6', '\u1fbc'),
+        ('\u1fbe', '\u1fbe'), ('\u1fc2', '\u1fc4'),
+        ('\u1fc6', '\u1fcc'), ('\u1fd0', '\u1fd3'),
+        ('\u1fd6', '\u1fdb'), ('\u1fe0', '\u1fec'),
+        ('\u1ff2', '\u1ff4'), ('\u1ff6', '\u1ffc'),
+        ('\u203f', '\u2040'), ('\u2054', '\u2054'),
+        ('\u2071', '\u2071'), ('\u207f', '\u207f'),
+        ('\u2090', '\u209c'), ('\u20d0', '\u20dc'),
+        ('\u20e1', '\u20e1'), ('\u20e5', '\u20f0'),
+        ('\u2102', '\u2102'), ('\u2107', '\u2107'),
+        ('\u210a', '\u2113'), ('\u2115', '\u2115'),
+        ('\u2118', '\u2118'), ('\u2119', '\u211d'),
+        ('\u2124', '\u2124'), ('\u2126', '\u2126'),
+        ('\u2128', '\u2128'), ('\u212a', '\u212d'),
+        ('\u212e', '\u212e'), ('\u212f', '\u2134'),
+        ('\u2135', '\u2138'), ('\u2139', '\u2139'),
+        ('\u213c', '\u213f'), ('\u2145', '\u2149'),
+        ('\u214e', '\u214e'), ('\u2160', '\u2182'),
+        ('\u2183', '\u2184'), ('\u2185', '\u2188'),
+        ('\u2c00', '\u2c2e'), ('\u2c30', '\u2c5e'),
+        ('\u2c60', '\u2c7b'), ('\u2c7c', '\u2c7d'),
+        ('\u2c7e', '\u2ce4'), ('\u2ceb', '\u2cee'),
+        ('\u2cef', '\u2cf1'), ('\u2cf2', '\u2cf3'),
+        ('\u2d00', '\u2d25'), ('\u2d27', '\u2d27'),
+        ('\u2d2d', '\u2d2d'), ('\u2d30', '\u2d67'),
+        ('\u2d6f', '\u2d6f'), ('\u2d7f', '\u2d7f'),
+        ('\u2d80', '\u2d96'), ('\u2da0', '\u2da6'),
+        ('\u2da8', '\u2dae'), ('\u2db0', '\u2db6'),
+        ('\u2db8', '\u2dbe'), ('\u2dc0', '\u2dc6'),
+        ('\u2dc8', '\u2dce'), ('\u2dd0', '\u2dd6'),
+        ('\u2dd8', '\u2dde'), ('\u2de0', '\u2dff'),
+        ('\u3005', '\u3005'), ('\u3006', '\u3006'),
+        ('\u3007', '\u3007'), ('\u3021', '\u3029'),
+        ('\u302a', '\u302d'), ('\u302e', '\u302f'),
+        ('\u3031', '\u3035'), ('\u3038', '\u303a'),
+        ('\u303b', '\u303b'), ('\u303c', '\u303c'),
+        ('\u3041', '\u3096'), ('\u3099', '\u309a'),
+        ('\u309d', '\u309e'), ('\u309f', '\u309f'),
+        ('\u30a1', '\u30fa'), ('\u30fc', '\u30fe'),
+        ('\u30ff', '\u30ff'), ('\u3105', '\u312d'),
+        ('\u3131', '\u318e'), ('\u31a0', '\u31ba'),
+        ('\u31f0', '\u31ff'), ('\u3400', '\u4db5'),
+        ('\u4e00', '\u9fcc'), ('\ua000', '\ua014'),
+        ('\ua015', '\ua015'), ('\ua016', '\ua48c'),
+        ('\ua4d0', '\ua4f7'), ('\ua4f8', '\ua4fd'),
+        ('\ua500', '\ua60b'), ('\ua60c', '\ua60c'),
+        ('\ua610', '\ua61f'), ('\ua620', '\ua629'),
+        ('\ua62a', '\ua62b'), ('\ua640', '\ua66d'),
+        ('\ua66e', '\ua66e'), ('\ua66f', '\ua66f'),
+        ('\ua674', '\ua67d'), ('\ua67f', '\ua67f'),
+        ('\ua680', '\ua697'), ('\ua69f', '\ua69f'),
+        ('\ua6a0', '\ua6e5'), ('\ua6e6', '\ua6ef'),
+        ('\ua6f0', '\ua6f1'), ('\ua717', '\ua71f'),
+        ('\ua722', '\ua76f'), ('\ua770', '\ua770'),
+        ('\ua771', '\ua787'), ('\ua788', '\ua788'),
+        ('\ua78b', '\ua78e'), ('\ua790', '\ua793'),
+        ('\ua7a0', '\ua7aa'), ('\ua7f8', '\ua7f9'),
+        ('\ua7fa', '\ua7fa'), ('\ua7fb', '\ua801'),
+        ('\ua802', '\ua802'), ('\ua803', '\ua805'),
+        ('\ua806', '\ua806'), ('\ua807', '\ua80a'),
+        ('\ua80b', '\ua80b'), ('\ua80c', '\ua822'),
+        ('\ua823', '\ua824'), ('\ua825', '\ua826'),
+        ('\ua827', '\ua827'), ('\ua840', '\ua873'),
+        ('\ua880', '\ua881'), ('\ua882', '\ua8b3'),
+        ('\ua8b4', '\ua8c3'), ('\ua8c4', '\ua8c4'),
+        ('\ua8d0', '\ua8d9'), ('\ua8e0', '\ua8f1'),
+        ('\ua8f2', '\ua8f7'), ('\ua8fb', '\ua8fb'),
+        ('\ua900', '\ua909'), ('\ua90a', '\ua925'),
+        ('\ua926', '\ua92d'), ('\ua930', '\ua946'),
+        ('\ua947', '\ua951'), ('\ua952', '\ua953'),
+        ('\ua960', '\ua97c'), ('\ua980', '\ua982'),
+        ('\ua983', '\ua983'), ('\ua984', '\ua9b2'),
+        ('\ua9b3', '\ua9b3'), ('\ua9b4', '\ua9b5'),
+        ('\ua9b6', '\ua9b9'), ('\ua9ba', '\ua9bb'),
+        ('\ua9bc', '\ua9bc'), ('\ua9bd', '\ua9c0'),
+        ('\ua9cf', '\ua9cf'), ('\ua9d0', '\ua9d9'),
+        ('\uaa00', '\uaa28'), ('\uaa29', '\uaa2e'),
+        ('\uaa2f', '\uaa30'), ('\uaa31', '\uaa32'),
+        ('\uaa33', '\uaa34'), ('\uaa35', '\uaa36'),
+        ('\uaa40', '\uaa42'), ('\uaa43', '\uaa43'),
+        ('\uaa44', '\uaa4b'), ('\uaa4c', '\uaa4c'),
+        ('\uaa4d', '\uaa4d'), ('\uaa50', '\uaa59'),
+        ('\uaa60', '\uaa6f'), ('\uaa70', '\uaa70'),
+        ('\uaa71', '\uaa76'), ('\uaa7a', '\uaa7a'),
+        ('\uaa7b', '\uaa7b'), ('\uaa80', '\uaaaf'),
+        ('\uaab0', '\uaab0'), ('\uaab1', '\uaab1'),
+        ('\uaab2', '\uaab4'), ('\uaab5', '\uaab6'),
+        ('\uaab7', '\uaab8'), ('\uaab9', '\uaabd'),
+        ('\uaabe', '\uaabf'), ('\uaac0', '\uaac0'),
+        ('\uaac1', '\uaac1'), ('\uaac2', '\uaac2'),
+        ('\uaadb', '\uaadc'), ('\uaadd', '\uaadd'),
+        ('\uaae0', '\uaaea'), ('\uaaeb', '\uaaeb'),
+        ('\uaaec', '\uaaed'), ('\uaaee', '\uaaef'),
+        ('\uaaf2', '\uaaf2'), ('\uaaf3', '\uaaf4'),
+        ('\uaaf5', '\uaaf5'), ('\uaaf6', '\uaaf6'),
+        ('\uab01', '\uab06'), ('\uab09', '\uab0e'),
+        ('\uab11', '\uab16'), ('\uab20', '\uab26'),
+        ('\uab28', '\uab2e'), ('\uabc0', '\uabe2'),
+        ('\uabe3', '\uabe4'), ('\uabe5', '\uabe5'),
+        ('\uabe6', '\uabe7'), ('\uabe8', '\uabe8'),
+        ('\uabe9', '\uabea'), ('\uabec', '\uabec'),
+        ('\uabed', '\uabed'), ('\uabf0', '\uabf9'),
+        ('\uac00', '\ud7a3'), ('\ud7b0', '\ud7c6'),
+        ('\ud7cb', '\ud7fb'), ('\uf900', '\ufa6d'),
+        ('\ufa70', '\ufad9'), ('\ufb00', '\ufb06'),
+        ('\ufb13', '\ufb17'), ('\ufb1d', '\ufb1d'),
+        ('\ufb1e', '\ufb1e'), ('\ufb1f', '\ufb28'),
+        ('\ufb2a', '\ufb36'), ('\ufb38', '\ufb3c'),
+        ('\ufb3e', '\ufb3e'), ('\ufb40', '\ufb41'),
+        ('\ufb43', '\ufb44'), ('\ufb46', '\ufbb1'),
+        ('\ufbd3', '\ufc5d'), ('\ufc64', '\ufd3d'),
+        ('\ufd50', '\ufd8f'), ('\ufd92', '\ufdc7'),
+        ('\ufdf0', '\ufdf9'), ('\ufe00', '\ufe0f'),
+        ('\ufe20', '\ufe26'), ('\ufe33', '\ufe34'),
+        ('\ufe4d', '\ufe4f'), ('\ufe71', '\ufe71'),
+        ('\ufe73', '\ufe73'), ('\ufe77', '\ufe77'),
+        ('\ufe79', '\ufe79'), ('\ufe7b', '\ufe7b'),
+        ('\ufe7d', '\ufe7d'), ('\ufe7f', '\ufefc'),
+        ('\uff10', '\uff19'), ('\uff21', '\uff3a'),
+        ('\uff3f', '\uff3f'), ('\uff41', '\uff5a'),
+        ('\uff66', '\uff6f'), ('\uff70', '\uff70'),
+        ('\uff71', '\uff9d'), ('\uff9e', '\uff9f'),
+        ('\uffa0', '\uffbe'), ('\uffc2', '\uffc7'),
+        ('\uffca', '\uffcf'), ('\uffd2', '\uffd7'),
+        ('\uffda', '\uffdc'), ('\U00010000', '\U0001000b'),
+        ('\U0001000d', '\U00010026'), ('\U00010028', '\U0001003a'),
+        ('\U0001003c', '\U0001003d'), ('\U0001003f', '\U0001004d'),
+        ('\U00010050', '\U0001005d'), ('\U00010080', '\U000100fa'),
+        ('\U00010140', '\U00010174'), ('\U000101fd', '\U000101fd'),
+        ('\U00010280', '\U0001029c'), ('\U000102a0', '\U000102d0'),
+        ('\U00010300', '\U0001031e'), ('\U00010330', '\U00010340'),
+        ('\U00010341', '\U00010341'), ('\U00010342', '\U00010349'),
+        ('\U0001034a', '\U0001034a'), ('\U00010380', '\U0001039d'),
+        ('\U000103a0', '\U000103c3'), ('\U000103c8', '\U000103cf'),
+        ('\U000103d1', '\U000103d5'), ('\U00010400', '\U0001044f'),
+        ('\U00010450', '\U0001049d'), ('\U000104a0', '\U000104a9'),
+        ('\U00010800', '\U00010805'), ('\U00010808', '\U00010808'),
+        ('\U0001080a', '\U00010835'), ('\U00010837', '\U00010838'),
+        ('\U0001083c', '\U0001083c'), ('\U0001083f', '\U00010855'),
+        ('\U00010900', '\U00010915'), ('\U00010920', '\U00010939'),
+        ('\U00010980', '\U000109b7'), ('\U000109be', '\U000109bf'),
+        ('\U00010a00', '\U00010a00'), ('\U00010a01', '\U00010a03'),
+        ('\U00010a05', '\U00010a06'), ('\U00010a0c', '\U00010a0f'),
+        ('\U00010a10', '\U00010a13'), ('\U00010a15', '\U00010a17'),
+        ('\U00010a19', '\U00010a33'), ('\U00010a38', '\U00010a3a'),
+        ('\U00010a3f', '\U00010a3f'), ('\U00010a60', '\U00010a7c'),
+        ('\U00010b00', '\U00010b35'), ('\U00010b40', '\U00010b55'),
+        ('\U00010b60', '\U00010b72'), ('\U00010c00', '\U00010c48'),
+        ('\U00011000', '\U00011000'), ('\U00011001', '\U00011001'),
+        ('\U00011002', '\U00011002'), ('\U00011003', '\U00011037'),
+        ('\U00011038', '\U00011046'), ('\U00011066', '\U0001106f'),
+        ('\U00011080', '\U00011081'), ('\U00011082', '\U00011082'),
+        ('\U00011083', '\U000110af'), ('\U000110b0', '\U000110b2'),
+        ('\U000110b3', '\U000110b6'), ('\U000110b7', '\U000110b8'),
+        ('\U000110b9', '\U000110ba'), ('\U000110d0', '\U000110e8'),
+        ('\U000110f0', '\U000110f9'), ('\U00011100', '\U00011102'),
+        ('\U00011103', '\U00011126'), ('\U00011127', '\U0001112b'),
+        ('\U0001112c', '\U0001112c'), ('\U0001112d', '\U00011134'),
+        ('\U00011136', '\U0001113f'), ('\U00011180', '\U00011181'),
+        ('\U00011182', '\U00011182'), ('\U00011183', '\U000111b2'),
+        ('\U000111b3', '\U000111b5'), ('\U000111b6', '\U000111be'),
+        ('\U000111bf', '\U000111c0'), ('\U000111c1', '\U000111c4'),
+        ('\U000111d0', '\U000111d9'), ('\U00011680', '\U000116aa'),
+        ('\U000116ab', '\U000116ab'), ('\U000116ac', '\U000116ac'),
+        ('\U000116ad', '\U000116ad'), ('\U000116ae', '\U000116af'),
+        ('\U000116b0', '\U000116b5'), ('\U000116b6', '\U000116b6'),
+        ('\U000116b7', '\U000116b7'), ('\U000116c0', '\U000116c9'),
+        ('\U00012000', '\U0001236e'), ('\U00012400', '\U00012462'),
+        ('\U00013000', '\U0001342e'), ('\U00016800', '\U00016a38'),
+        ('\U00016f00', '\U00016f44'), ('\U00016f50', '\U00016f50'),
+        ('\U00016f51', '\U00016f7e'), ('\U00016f8f', '\U00016f92'),
+        ('\U00016f93', '\U00016f9f'), ('\U0001b000', '\U0001b001'),
+        ('\U0001d165', '\U0001d166'), ('\U0001d167', '\U0001d169'),
+        ('\U0001d16d', '\U0001d172'), ('\U0001d17b', '\U0001d182'),
+        ('\U0001d185', '\U0001d18b'), ('\U0001d1aa', '\U0001d1ad'),
+        ('\U0001d242', '\U0001d244'), ('\U0001d400', '\U0001d454'),
+        ('\U0001d456', '\U0001d49c'), ('\U0001d49e', '\U0001d49f'),
+        ('\U0001d4a2', '\U0001d4a2'), ('\U0001d4a5', '\U0001d4a6'),
+        ('\U0001d4a9', '\U0001d4ac'), ('\U0001d4ae', '\U0001d4b9'),
+        ('\U0001d4bb', '\U0001d4bb'), ('\U0001d4bd', '\U0001d4c3'),
+        ('\U0001d4c5', '\U0001d505'), ('\U0001d507', '\U0001d50a'),
+        ('\U0001d50d', '\U0001d514'), ('\U0001d516', '\U0001d51c'),
+        ('\U0001d51e', '\U0001d539'), ('\U0001d53b', '\U0001d53e'),
+        ('\U0001d540', '\U0001d544'), ('\U0001d546', '\U0001d546'),
+        ('\U0001d54a', '\U0001d550'), ('\U0001d552', '\U0001d6a5'),
+        ('\U0001d6a8', '\U0001d6c0'), ('\U0001d6c2', '\U0001d6da'),
+        ('\U0001d6dc', '\U0001d6fa'), ('\U0001d6fc', '\U0001d714'),
+        ('\U0001d716', '\U0001d734'), ('\U0001d736', '\U0001d74e'),
+        ('\U0001d750', '\U0001d76e'), ('\U0001d770', '\U0001d788'),
+        ('\U0001d78a', '\U0001d7a8'), ('\U0001d7aa', '\U0001d7c2'),
+        ('\U0001d7c4', '\U0001d7cb'), ('\U0001d7ce', '\U0001d7ff'),
+        ('\U0001ee00', '\U0001ee03'), ('\U0001ee05', '\U0001ee1f'),
+        ('\U0001ee21', '\U0001ee22'), ('\U0001ee24', '\U0001ee24'),
+        ('\U0001ee27', '\U0001ee27'), ('\U0001ee29', '\U0001ee32'),
+        ('\U0001ee34', '\U0001ee37'), ('\U0001ee39', '\U0001ee39'),
+        ('\U0001ee3b', '\U0001ee3b'), ('\U0001ee42', '\U0001ee42'),
+        ('\U0001ee47', '\U0001ee47'), ('\U0001ee49', '\U0001ee49'),
+        ('\U0001ee4b', '\U0001ee4b'), ('\U0001ee4d', '\U0001ee4f'),
+        ('\U0001ee51', '\U0001ee52'), ('\U0001ee54', '\U0001ee54'),
+        ('\U0001ee57', '\U0001ee57'), ('\U0001ee59', '\U0001ee59'),
+        ('\U0001ee5b', '\U0001ee5b'), ('\U0001ee5d', '\U0001ee5d'),
+        ('\U0001ee5f', '\U0001ee5f'), ('\U0001ee61', '\U0001ee62'),
+        ('\U0001ee64', '\U0001ee64'), ('\U0001ee67', '\U0001ee6a'),
+        ('\U0001ee6c', '\U0001ee72'), ('\U0001ee74', '\U0001ee77'),
+        ('\U0001ee79', '\U0001ee7c'), ('\U0001ee7e', '\U0001ee7e'),
+        ('\U0001ee80', '\U0001ee89'), ('\U0001ee8b', '\U0001ee9b'),
+        ('\U0001eea1', '\U0001eea3'), ('\U0001eea5', '\U0001eea9'),
+        ('\U0001eeab', '\U0001eebb'), ('\U00020000', '\U0002a6d6'),
+        ('\U0002a700', '\U0002b734'), ('\U0002b740', '\U0002b81d'),
+        ('\U0002f800', '\U0002fa1d'), ('\U000e0100', '\U000e01ef')
+    ];
+
+    pub fn XID_Continue(c: char) -> bool {
+        bsearch_range_table(c, XID_Continue_table)
     }
 
-    #[test]
-    fn test_is_upper() {
-        assert!((unicode::icu::is_upper('M')));
-        assert!((!unicode::icu::is_upper('m')));
+    static XID_Start_table : &'static [(char,char)] = &[
+        ('\x41', '\x5a'), ('\x61', '\x7a'),
+        ('\xaa', '\xaa'), ('\xb5', '\xb5'),
+        ('\xba', '\xba'), ('\xc0', '\xd6'),
+        ('\xd8', '\xf6'), ('\xf8', '\u01ba'),
+        ('\u01bb', '\u01bb'), ('\u01bc', '\u01bf'),
+        ('\u01c0', '\u01c3'), ('\u01c4', '\u0293'),
+        ('\u0294', '\u0294'), ('\u0295', '\u02af'),
+        ('\u02b0', '\u02c1'), ('\u02c6', '\u02d1'),
+        ('\u02e0', '\u02e4'), ('\u02ec', '\u02ec'),
+        ('\u02ee', '\u02ee'), ('\u0370', '\u0373'),
+        ('\u0374', '\u0374'), ('\u0376', '\u0377'),
+        ('\u037b', '\u037d'), ('\u0386', '\u0386'),
+        ('\u0388', '\u038a'), ('\u038c', '\u038c'),
+        ('\u038e', '\u03a1'), ('\u03a3', '\u03f5'),
+        ('\u03f7', '\u0481'), ('\u048a', '\u0527'),
+        ('\u0531', '\u0556'), ('\u0559', '\u0559'),
+        ('\u0561', '\u0587'), ('\u05d0', '\u05ea'),
+        ('\u05f0', '\u05f2'), ('\u0620', '\u063f'),
+        ('\u0640', '\u0640'), ('\u0641', '\u064a'),
+        ('\u066e', '\u066f'), ('\u0671', '\u06d3'),
+        ('\u06d5', '\u06d5'), ('\u06e5', '\u06e6'),
+        ('\u06ee', '\u06ef'), ('\u06fa', '\u06fc'),
+        ('\u06ff', '\u06ff'), ('\u0710', '\u0710'),
+        ('\u0712', '\u072f'), ('\u074d', '\u07a5'),
+        ('\u07b1', '\u07b1'), ('\u07ca', '\u07ea'),
+        ('\u07f4', '\u07f5'), ('\u07fa', '\u07fa'),
+        ('\u0800', '\u0815'), ('\u081a', '\u081a'),
+        ('\u0824', '\u0824'), ('\u0828', '\u0828'),
+        ('\u0840', '\u0858'), ('\u08a0', '\u08a0'),
+        ('\u08a2', '\u08ac'), ('\u0904', '\u0939'),
+        ('\u093d', '\u093d'), ('\u0950', '\u0950'),
+        ('\u0958', '\u0961'), ('\u0971', '\u0971'),
+        ('\u0972', '\u0977'), ('\u0979', '\u097f'),
+        ('\u0985', '\u098c'), ('\u098f', '\u0990'),
+        ('\u0993', '\u09a8'), ('\u09aa', '\u09b0'),
+        ('\u09b2', '\u09b2'), ('\u09b6', '\u09b9'),
+        ('\u09bd', '\u09bd'), ('\u09ce', '\u09ce'),
+        ('\u09dc', '\u09dd'), ('\u09df', '\u09e1'),
+        ('\u09f0', '\u09f1'), ('\u0a05', '\u0a0a'),
+        ('\u0a0f', '\u0a10'), ('\u0a13', '\u0a28'),
+        ('\u0a2a', '\u0a30'), ('\u0a32', '\u0a33'),
+        ('\u0a35', '\u0a36'), ('\u0a38', '\u0a39'),
+        ('\u0a59', '\u0a5c'), ('\u0a5e', '\u0a5e'),
+        ('\u0a72', '\u0a74'), ('\u0a85', '\u0a8d'),
+        ('\u0a8f', '\u0a91'), ('\u0a93', '\u0aa8'),
+        ('\u0aaa', '\u0ab0'), ('\u0ab2', '\u0ab3'),
+        ('\u0ab5', '\u0ab9'), ('\u0abd', '\u0abd'),
+        ('\u0ad0', '\u0ad0'), ('\u0ae0', '\u0ae1'),
+        ('\u0b05', '\u0b0c'), ('\u0b0f', '\u0b10'),
+        ('\u0b13', '\u0b28'), ('\u0b2a', '\u0b30'),
+        ('\u0b32', '\u0b33'), ('\u0b35', '\u0b39'),
+        ('\u0b3d', '\u0b3d'), ('\u0b5c', '\u0b5d'),
+        ('\u0b5f', '\u0b61'), ('\u0b71', '\u0b71'),
+        ('\u0b83', '\u0b83'), ('\u0b85', '\u0b8a'),
+        ('\u0b8e', '\u0b90'), ('\u0b92', '\u0b95'),
+        ('\u0b99', '\u0b9a'), ('\u0b9c', '\u0b9c'),
+        ('\u0b9e', '\u0b9f'), ('\u0ba3', '\u0ba4'),
+        ('\u0ba8', '\u0baa'), ('\u0bae', '\u0bb9'),
+        ('\u0bd0', '\u0bd0'), ('\u0c05', '\u0c0c'),
+        ('\u0c0e', '\u0c10'), ('\u0c12', '\u0c28'),
+        ('\u0c2a', '\u0c33'), ('\u0c35', '\u0c39'),
+        ('\u0c3d', '\u0c3d'), ('\u0c58', '\u0c59'),
+        ('\u0c60', '\u0c61'), ('\u0c85', '\u0c8c'),
+        ('\u0c8e', '\u0c90'), ('\u0c92', '\u0ca8'),
+        ('\u0caa', '\u0cb3'), ('\u0cb5', '\u0cb9'),
+        ('\u0cbd', '\u0cbd'), ('\u0cde', '\u0cde'),
+        ('\u0ce0', '\u0ce1'), ('\u0cf1', '\u0cf2'),
+        ('\u0d05', '\u0d0c'), ('\u0d0e', '\u0d10'),
+        ('\u0d12', '\u0d3a'), ('\u0d3d', '\u0d3d'),
+        ('\u0d4e', '\u0d4e'), ('\u0d60', '\u0d61'),
+        ('\u0d7a', '\u0d7f'), ('\u0d85', '\u0d96'),
+        ('\u0d9a', '\u0db1'), ('\u0db3', '\u0dbb'),
+        ('\u0dbd', '\u0dbd'), ('\u0dc0', '\u0dc6'),
+        ('\u0e01', '\u0e30'), ('\u0e32', '\u0e32'),
+        ('\u0e40', '\u0e45'), ('\u0e46', '\u0e46'),
+        ('\u0e81', '\u0e82'), ('\u0e84', '\u0e84'),
+        ('\u0e87', '\u0e88'), ('\u0e8a', '\u0e8a'),
+        ('\u0e8d', '\u0e8d'), ('\u0e94', '\u0e97'),
+        ('\u0e99', '\u0e9f'), ('\u0ea1', '\u0ea3'),
+        ('\u0ea5', '\u0ea5'), ('\u0ea7', '\u0ea7'),
+        ('\u0eaa', '\u0eab'), ('\u0ead', '\u0eb0'),
+        ('\u0eb2', '\u0eb2'), ('\u0ebd', '\u0ebd'),
+        ('\u0ec0', '\u0ec4'), ('\u0ec6', '\u0ec6'),
+        ('\u0edc', '\u0edf'), ('\u0f00', '\u0f00'),
+        ('\u0f40', '\u0f47'), ('\u0f49', '\u0f6c'),
+        ('\u0f88', '\u0f8c'), ('\u1000', '\u102a'),
+        ('\u103f', '\u103f'), ('\u1050', '\u1055'),
+        ('\u105a', '\u105d'), ('\u1061', '\u1061'),
+        ('\u1065', '\u1066'), ('\u106e', '\u1070'),
+        ('\u1075', '\u1081'), ('\u108e', '\u108e'),
+        ('\u10a0', '\u10c5'), ('\u10c7', '\u10c7'),
+        ('\u10cd', '\u10cd'), ('\u10d0', '\u10fa'),
+        ('\u10fc', '\u10fc'), ('\u10fd', '\u1248'),
+        ('\u124a', '\u124d'), ('\u1250', '\u1256'),
+        ('\u1258', '\u1258'), ('\u125a', '\u125d'),
+        ('\u1260', '\u1288'), ('\u128a', '\u128d'),
+        ('\u1290', '\u12b0'), ('\u12b2', '\u12b5'),
+        ('\u12b8', '\u12be'), ('\u12c0', '\u12c0'),
+        ('\u12c2', '\u12c5'), ('\u12c8', '\u12d6'),
+        ('\u12d8', '\u1310'), ('\u1312', '\u1315'),
+        ('\u1318', '\u135a'), ('\u1380', '\u138f'),
+        ('\u13a0', '\u13f4'), ('\u1401', '\u166c'),
+        ('\u166f', '\u167f'), ('\u1681', '\u169a'),
+        ('\u16a0', '\u16ea'), ('\u16ee', '\u16f0'),
+        ('\u1700', '\u170c'), ('\u170e', '\u1711'),
+        ('\u1720', '\u1731'), ('\u1740', '\u1751'),
+        ('\u1760', '\u176c'), ('\u176e', '\u1770'),
+        ('\u1780', '\u17b3'), ('\u17d7', '\u17d7'),
+        ('\u17dc', '\u17dc'), ('\u1820', '\u1842'),
+        ('\u1843', '\u1843'), ('\u1844', '\u1877'),
+        ('\u1880', '\u18a8'), ('\u18aa', '\u18aa'),
+        ('\u18b0', '\u18f5'), ('\u1900', '\u191c'),
+        ('\u1950', '\u196d'), ('\u1970', '\u1974'),
+        ('\u1980', '\u19ab'), ('\u19c1', '\u19c7'),
+        ('\u1a00', '\u1a16'), ('\u1a20', '\u1a54'),
+        ('\u1aa7', '\u1aa7'), ('\u1b05', '\u1b33'),
+        ('\u1b45', '\u1b4b'), ('\u1b83', '\u1ba0'),
+        ('\u1bae', '\u1baf'), ('\u1bba', '\u1be5'),
+        ('\u1c00', '\u1c23'), ('\u1c4d', '\u1c4f'),
+        ('\u1c5a', '\u1c77'), ('\u1c78', '\u1c7d'),
+        ('\u1ce9', '\u1cec'), ('\u1cee', '\u1cf1'),
+        ('\u1cf5', '\u1cf6'), ('\u1d00', '\u1d2b'),
+        ('\u1d2c', '\u1d6a'), ('\u1d6b', '\u1d77'),
+        ('\u1d78', '\u1d78'), ('\u1d79', '\u1d9a'),
+        ('\u1d9b', '\u1dbf'), ('\u1e00', '\u1f15'),
+        ('\u1f18', '\u1f1d'), ('\u1f20', '\u1f45'),
+        ('\u1f48', '\u1f4d'), ('\u1f50', '\u1f57'),
+        ('\u1f59', '\u1f59'), ('\u1f5b', '\u1f5b'),
+        ('\u1f5d', '\u1f5d'), ('\u1f5f', '\u1f7d'),
+        ('\u1f80', '\u1fb4'), ('\u1fb6', '\u1fbc'),
+        ('\u1fbe', '\u1fbe'), ('\u1fc2', '\u1fc4'),
+        ('\u1fc6', '\u1fcc'), ('\u1fd0', '\u1fd3'),
+        ('\u1fd6', '\u1fdb'), ('\u1fe0', '\u1fec'),
+        ('\u1ff2', '\u1ff4'), ('\u1ff6', '\u1ffc'),
+        ('\u2071', '\u2071'), ('\u207f', '\u207f'),
+        ('\u2090', '\u209c'), ('\u2102', '\u2102'),
+        ('\u2107', '\u2107'), ('\u210a', '\u2113'),
+        ('\u2115', '\u2115'), ('\u2118', '\u2118'),
+        ('\u2119', '\u211d'), ('\u2124', '\u2124'),
+        ('\u2126', '\u2126'), ('\u2128', '\u2128'),
+        ('\u212a', '\u212d'), ('\u212e', '\u212e'),
+        ('\u212f', '\u2134'), ('\u2135', '\u2138'),
+        ('\u2139', '\u2139'), ('\u213c', '\u213f'),
+        ('\u2145', '\u2149'), ('\u214e', '\u214e'),
+        ('\u2160', '\u2182'), ('\u2183', '\u2184'),
+        ('\u2185', '\u2188'), ('\u2c00', '\u2c2e'),
+        ('\u2c30', '\u2c5e'), ('\u2c60', '\u2c7b'),
+        ('\u2c7c', '\u2c7d'), ('\u2c7e', '\u2ce4'),
+        ('\u2ceb', '\u2cee'), ('\u2cf2', '\u2cf3'),
+        ('\u2d00', '\u2d25'), ('\u2d27', '\u2d27'),
+        ('\u2d2d', '\u2d2d'), ('\u2d30', '\u2d67'),
+        ('\u2d6f', '\u2d6f'), ('\u2d80', '\u2d96'),
+        ('\u2da0', '\u2da6'), ('\u2da8', '\u2dae'),
+        ('\u2db0', '\u2db6'), ('\u2db8', '\u2dbe'),
+        ('\u2dc0', '\u2dc6'), ('\u2dc8', '\u2dce'),
+        ('\u2dd0', '\u2dd6'), ('\u2dd8', '\u2dde'),
+        ('\u3005', '\u3005'), ('\u3006', '\u3006'),
+        ('\u3007', '\u3007'), ('\u3021', '\u3029'),
+        ('\u3031', '\u3035'), ('\u3038', '\u303a'),
+        ('\u303b', '\u303b'), ('\u303c', '\u303c'),
+        ('\u3041', '\u3096'), ('\u309d', '\u309e'),
+        ('\u309f', '\u309f'), ('\u30a1', '\u30fa'),
+        ('\u30fc', '\u30fe'), ('\u30ff', '\u30ff'),
+        ('\u3105', '\u312d'), ('\u3131', '\u318e'),
+        ('\u31a0', '\u31ba'), ('\u31f0', '\u31ff'),
+        ('\u3400', '\u4db5'), ('\u4e00', '\u9fcc'),
+        ('\ua000', '\ua014'), ('\ua015', '\ua015'),
+        ('\ua016', '\ua48c'), ('\ua4d0', '\ua4f7'),
+        ('\ua4f8', '\ua4fd'), ('\ua500', '\ua60b'),
+        ('\ua60c', '\ua60c'), ('\ua610', '\ua61f'),
+        ('\ua62a', '\ua62b'), ('\ua640', '\ua66d'),
+        ('\ua66e', '\ua66e'), ('\ua67f', '\ua67f'),
+        ('\ua680', '\ua697'), ('\ua6a0', '\ua6e5'),
+        ('\ua6e6', '\ua6ef'), ('\ua717', '\ua71f'),
+        ('\ua722', '\ua76f'), ('\ua770', '\ua770'),
+        ('\ua771', '\ua787'), ('\ua788', '\ua788'),
+        ('\ua78b', '\ua78e'), ('\ua790', '\ua793'),
+        ('\ua7a0', '\ua7aa'), ('\ua7f8', '\ua7f9'),
+        ('\ua7fa', '\ua7fa'), ('\ua7fb', '\ua801'),
+        ('\ua803', '\ua805'), ('\ua807', '\ua80a'),
+        ('\ua80c', '\ua822'), ('\ua840', '\ua873'),
+        ('\ua882', '\ua8b3'), ('\ua8f2', '\ua8f7'),
+        ('\ua8fb', '\ua8fb'), ('\ua90a', '\ua925'),
+        ('\ua930', '\ua946'), ('\ua960', '\ua97c'),
+        ('\ua984', '\ua9b2'), ('\ua9cf', '\ua9cf'),
+        ('\uaa00', '\uaa28'), ('\uaa40', '\uaa42'),
+        ('\uaa44', '\uaa4b'), ('\uaa60', '\uaa6f'),
+        ('\uaa70', '\uaa70'), ('\uaa71', '\uaa76'),
+        ('\uaa7a', '\uaa7a'), ('\uaa80', '\uaaaf'),
+        ('\uaab1', '\uaab1'), ('\uaab5', '\uaab6'),
+        ('\uaab9', '\uaabd'), ('\uaac0', '\uaac0'),
+        ('\uaac2', '\uaac2'), ('\uaadb', '\uaadc'),
+        ('\uaadd', '\uaadd'), ('\uaae0', '\uaaea'),
+        ('\uaaf2', '\uaaf2'), ('\uaaf3', '\uaaf4'),
+        ('\uab01', '\uab06'), ('\uab09', '\uab0e'),
+        ('\uab11', '\uab16'), ('\uab20', '\uab26'),
+        ('\uab28', '\uab2e'), ('\uabc0', '\uabe2'),
+        ('\uac00', '\ud7a3'), ('\ud7b0', '\ud7c6'),
+        ('\ud7cb', '\ud7fb'), ('\uf900', '\ufa6d'),
+        ('\ufa70', '\ufad9'), ('\ufb00', '\ufb06'),
+        ('\ufb13', '\ufb17'), ('\ufb1d', '\ufb1d'),
+        ('\ufb1f', '\ufb28'), ('\ufb2a', '\ufb36'),
+        ('\ufb38', '\ufb3c'), ('\ufb3e', '\ufb3e'),
+        ('\ufb40', '\ufb41'), ('\ufb43', '\ufb44'),
+        ('\ufb46', '\ufbb1'), ('\ufbd3', '\ufc5d'),
+        ('\ufc64', '\ufd3d'), ('\ufd50', '\ufd8f'),
+        ('\ufd92', '\ufdc7'), ('\ufdf0', '\ufdf9'),
+        ('\ufe71', '\ufe71'), ('\ufe73', '\ufe73'),
+        ('\ufe77', '\ufe77'), ('\ufe79', '\ufe79'),
+        ('\ufe7b', '\ufe7b'), ('\ufe7d', '\ufe7d'),
+        ('\ufe7f', '\ufefc'), ('\uff21', '\uff3a'),
+        ('\uff41', '\uff5a'), ('\uff66', '\uff6f'),
+        ('\uff70', '\uff70'), ('\uff71', '\uff9d'),
+        ('\uffa0', '\uffbe'), ('\uffc2', '\uffc7'),
+        ('\uffca', '\uffcf'), ('\uffd2', '\uffd7'),
+        ('\uffda', '\uffdc'), ('\U00010000', '\U0001000b'),
+        ('\U0001000d', '\U00010026'), ('\U00010028', '\U0001003a'),
+        ('\U0001003c', '\U0001003d'), ('\U0001003f', '\U0001004d'),
+        ('\U00010050', '\U0001005d'), ('\U00010080', '\U000100fa'),
+        ('\U00010140', '\U00010174'), ('\U00010280', '\U0001029c'),
+        ('\U000102a0', '\U000102d0'), ('\U00010300', '\U0001031e'),
+        ('\U00010330', '\U00010340'), ('\U00010341', '\U00010341'),
+        ('\U00010342', '\U00010349'), ('\U0001034a', '\U0001034a'),
+        ('\U00010380', '\U0001039d'), ('\U000103a0', '\U000103c3'),
+        ('\U000103c8', '\U000103cf'), ('\U000103d1', '\U000103d5'),
+        ('\U00010400', '\U0001044f'), ('\U00010450', '\U0001049d'),
+        ('\U00010800', '\U00010805'), ('\U00010808', '\U00010808'),
+        ('\U0001080a', '\U00010835'), ('\U00010837', '\U00010838'),
+        ('\U0001083c', '\U0001083c'), ('\U0001083f', '\U00010855'),
+        ('\U00010900', '\U00010915'), ('\U00010920', '\U00010939'),
+        ('\U00010980', '\U000109b7'), ('\U000109be', '\U000109bf'),
+        ('\U00010a00', '\U00010a00'), ('\U00010a10', '\U00010a13'),
+        ('\U00010a15', '\U00010a17'), ('\U00010a19', '\U00010a33'),
+        ('\U00010a60', '\U00010a7c'), ('\U00010b00', '\U00010b35'),
+        ('\U00010b40', '\U00010b55'), ('\U00010b60', '\U00010b72'),
+        ('\U00010c00', '\U00010c48'), ('\U00011003', '\U00011037'),
+        ('\U00011083', '\U000110af'), ('\U000110d0', '\U000110e8'),
+        ('\U00011103', '\U00011126'), ('\U00011183', '\U000111b2'),
+        ('\U000111c1', '\U000111c4'), ('\U00011680', '\U000116aa'),
+        ('\U00012000', '\U0001236e'), ('\U00012400', '\U00012462'),
+        ('\U00013000', '\U0001342e'), ('\U00016800', '\U00016a38'),
+        ('\U00016f00', '\U00016f44'), ('\U00016f50', '\U00016f50'),
+        ('\U00016f93', '\U00016f9f'), ('\U0001b000', '\U0001b001'),
+        ('\U0001d400', '\U0001d454'), ('\U0001d456', '\U0001d49c'),
+        ('\U0001d49e', '\U0001d49f'), ('\U0001d4a2', '\U0001d4a2'),
+        ('\U0001d4a5', '\U0001d4a6'), ('\U0001d4a9', '\U0001d4ac'),
+        ('\U0001d4ae', '\U0001d4b9'), ('\U0001d4bb', '\U0001d4bb'),
+        ('\U0001d4bd', '\U0001d4c3'), ('\U0001d4c5', '\U0001d505'),
+        ('\U0001d507', '\U0001d50a'), ('\U0001d50d', '\U0001d514'),
+        ('\U0001d516', '\U0001d51c'), ('\U0001d51e', '\U0001d539'),
+        ('\U0001d53b', '\U0001d53e'), ('\U0001d540', '\U0001d544'),
+        ('\U0001d546', '\U0001d546'), ('\U0001d54a', '\U0001d550'),
+        ('\U0001d552', '\U0001d6a5'), ('\U0001d6a8', '\U0001d6c0'),
+        ('\U0001d6c2', '\U0001d6da'), ('\U0001d6dc', '\U0001d6fa'),
+        ('\U0001d6fc', '\U0001d714'), ('\U0001d716', '\U0001d734'),
+        ('\U0001d736', '\U0001d74e'), ('\U0001d750', '\U0001d76e'),
+        ('\U0001d770', '\U0001d788'), ('\U0001d78a', '\U0001d7a8'),
+        ('\U0001d7aa', '\U0001d7c2'), ('\U0001d7c4', '\U0001d7cb'),
+        ('\U0001ee00', '\U0001ee03'), ('\U0001ee05', '\U0001ee1f'),
+        ('\U0001ee21', '\U0001ee22'), ('\U0001ee24', '\U0001ee24'),
+        ('\U0001ee27', '\U0001ee27'), ('\U0001ee29', '\U0001ee32'),
+        ('\U0001ee34', '\U0001ee37'), ('\U0001ee39', '\U0001ee39'),
+        ('\U0001ee3b', '\U0001ee3b'), ('\U0001ee42', '\U0001ee42'),
+        ('\U0001ee47', '\U0001ee47'), ('\U0001ee49', '\U0001ee49'),
+        ('\U0001ee4b', '\U0001ee4b'), ('\U0001ee4d', '\U0001ee4f'),
+        ('\U0001ee51', '\U0001ee52'), ('\U0001ee54', '\U0001ee54'),
+        ('\U0001ee57', '\U0001ee57'), ('\U0001ee59', '\U0001ee59'),
+        ('\U0001ee5b', '\U0001ee5b'), ('\U0001ee5d', '\U0001ee5d'),
+        ('\U0001ee5f', '\U0001ee5f'), ('\U0001ee61', '\U0001ee62'),
+        ('\U0001ee64', '\U0001ee64'), ('\U0001ee67', '\U0001ee6a'),
+        ('\U0001ee6c', '\U0001ee72'), ('\U0001ee74', '\U0001ee77'),
+        ('\U0001ee79', '\U0001ee7c'), ('\U0001ee7e', '\U0001ee7e'),
+        ('\U0001ee80', '\U0001ee89'), ('\U0001ee8b', '\U0001ee9b'),
+        ('\U0001eea1', '\U0001eea3'), ('\U0001eea5', '\U0001eea9'),
+        ('\U0001eeab', '\U0001eebb'), ('\U00020000', '\U0002a6d6'),
+        ('\U0002a700', '\U0002b734'), ('\U0002b740', '\U0002b81d'),
+        ('\U0002f800', '\U0002fa1d')
+    ];
+
+    pub fn XID_Start(c: char) -> bool {
+        bsearch_range_table(c, XID_Start_table)
     }
 }
diff --git a/src/libstd/unstable/at_exit.rs b/src/libstd/unstable/at_exit.rs
new file mode 100644
index 00000000000..d214b509dfb
--- /dev/null
+++ b/src/libstd/unstable/at_exit.rs
@@ -0,0 +1,100 @@
+// 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 cast;
+use libc::size_t;
+use rand::RngUtil;
+use rand;
+use sys;
+use task;
+use vec;
+
+#[cfg(test)] use uint;
+
+/**
+Register a function to be run during runtime shutdown.
+
+After all non-weak tasks have exited, registered exit functions will
+execute, in random order, on the primary scheduler. Each function runs
+in its own unsupervised task.
+*/
+pub fn at_exit(f: ~fn()) {
+    unsafe {
+        let runner: &fn(*ExitFunctions) = exit_runner;
+        let runner_pair: sys::Closure = cast::transmute(runner);
+        let runner_ptr = runner_pair.code;
+        let runner_ptr = cast::transmute(runner_ptr);
+        rustrt::rust_register_exit_function(runner_ptr, ~f);
+    }
+}
+
+// NB: The double pointer indirection here is because ~fn() is a fat
+// pointer and due to FFI problems I am more comfortable making the
+// interface use a normal pointer
+mod rustrt {
+    use libc::c_void;
+
+    pub extern {
+        fn rust_register_exit_function(runner: *c_void, f: ~~fn());
+    }
+}
+
+struct ExitFunctions {
+    // The number of exit functions
+    count: size_t,
+    // The buffer of exit functions
+    start: *~~fn()
+}
+
+fn exit_runner(exit_fns: *ExitFunctions) {
+    let exit_fns = unsafe { &*exit_fns };
+    let count = (*exit_fns).count;
+    let start = (*exit_fns).start;
+
+    // NB: from_buf memcpys from the source, which will
+    // give us ownership of the array of functions
+    let mut exit_fns_vec = unsafe { vec::from_buf(start, count as uint) };
+    // Let's not make any promises about execution order
+    let mut rng = rand::rng();
+    rng.shuffle_mut(exit_fns_vec);
+
+    debug!("running %u exit functions", exit_fns_vec.len());
+
+    while !exit_fns_vec.is_empty() {
+        match exit_fns_vec.pop() {
+            ~f => {
+                let mut task = task::task();
+                task.supervised();
+                task.spawn(f);
+            }
+        }
+    }
+}
+
+#[test]
+fn test_at_exit() {
+    let i = 10;
+    do at_exit {
+        debug!("at_exit1");
+        assert_eq!(i, 10);
+    }
+}
+
+#[test]
+fn test_at_exit_many() {
+    let i = 10;
+    for uint::range(20, 100) |j| {
+        do at_exit {
+            debug!("at_exit2");
+            assert_eq!(i, 10);
+            assert!(j > i);
+        }
+    }
+}
diff --git a/src/libstd/unstable/exchange_alloc.rs b/src/libstd/unstable/exchange_alloc.rs
new file mode 100644
index 00000000000..3b35c2fb804
--- /dev/null
+++ b/src/libstd/unstable/exchange_alloc.rs
@@ -0,0 +1,83 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use sys::{TypeDesc, size_of};
+use libc::{c_void, size_t};
+use c_malloc = libc::malloc;
+use c_free = libc::free;
+use managed::raw::{BoxHeaderRepr, BoxRepr};
+use cast::transmute;
+use unstable::intrinsics::{atomic_xadd,atomic_xsub};
+use ptr::null;
+use intrinsic::TyDesc;
+
+pub unsafe fn malloc(td: *TypeDesc, size: uint) -> *c_void {
+    assert!(td.is_not_null());
+
+    let total_size = get_box_size(size, (*td).align);
+    let p = c_malloc(total_size as size_t);
+    assert!(p.is_not_null());
+
+    // FIXME #3475: Converting between our two different tydesc types
+    let td: *TyDesc = transmute(td);
+
+    let box: &mut BoxRepr = transmute(p);
+    box.header.ref_count = -1; // Exchange values not ref counted
+    box.header.type_desc = td;
+    box.header.prev = null();
+    box.header.next = null();
+
+    let exchange_count = &mut *rust_get_exchange_count_ptr();
+    atomic_xadd(exchange_count, 1);
+
+    return transmute(box);
+}
+/**
+Thin wrapper around libc::malloc, none of the box header
+stuff in exchange_alloc::malloc
+*/
+pub unsafe fn malloc_raw(size: uint) -> *c_void {
+    let p = c_malloc(size as size_t);
+    if p.is_null() {
+        fail!("Failure in malloc_raw: result ptr is null");
+    }
+    p
+}
+
+pub unsafe fn free(ptr: *c_void) {
+    let exchange_count = &mut *rust_get_exchange_count_ptr();
+    atomic_xsub(exchange_count, 1);
+
+    assert!(ptr.is_not_null());
+    c_free(ptr);
+}
+///Thin wrapper around libc::free, as with exchange_alloc::malloc_raw
+pub unsafe fn free_raw(ptr: *c_void) {
+    c_free(ptr);
+}
+
+fn get_box_size(body_size: uint, body_align: uint) -> uint {
+    let header_size = size_of::<BoxHeaderRepr>();
+    // FIXME (#2699): This alignment calculation is suspicious. Is it right?
+    let total_size = align_to(header_size, body_align) + body_size;
+    return total_size;
+}
+
+// Rounds |size| to the nearest |alignment|. Invariant: |alignment| is a power
+// of two.
+fn align_to(size: uint, align: uint) -> uint {
+    assert!(align != 0);
+    (size + align - 1) & !(align - 1)
+}
+
+extern {
+    #[rust_stack]
+    fn rust_get_exchange_count_ptr() -> *mut int;
+}
diff --git a/src/libstd/unstable/extfmt.rs b/src/libstd/unstable/extfmt.rs
new file mode 100644
index 00000000000..8da378fdc97
--- /dev/null
+++ b/src/libstd/unstable/extfmt.rs
@@ -0,0 +1,690 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Support for fmt! expressions.
+//!
+//! The syntax is close to that of Posix format strings:
+//!
+//! ~~~~~~
+//! Format := '%' Parameter? Flag* Width? Precision? Type
+//! Parameter := [0-9]+ '$'
+//! Flag := [ 0#+-]
+//! Width := Parameter | [0-9]+
+//! Precision := '.' [0-9]+
+//! Type := [bcdfiostuxX?]
+//! ~~~~~~
+//!
+//! * Parameter is the 1-based argument to apply the format to. Currently not
+//! implemented.
+//! * Flag 0 causes leading zeros to be used for padding when converting
+//! numbers.
+//! * Flag # causes the conversion to be done in an *alternative* manner.
+//! Currently not implemented.
+//! * Flag + causes signed numbers to always be prepended with a sign
+//! character.
+//! * Flag - left justifies the result
+//! * Width specifies the minimum field width of the result. By default
+//! leading spaces are added.
+//! * Precision specifies the minimum number of digits for integral types
+//! and the minimum number
+//! of decimal places for float.
+//!
+//! The types currently supported are:
+//!
+//! * b - bool
+//! * c - char
+//! * d - int
+//! * f - float
+//! * i - int (same as d)
+//! * o - uint as octal
+//! * t - uint as binary
+//! * u - uint
+//! * x - uint as lower-case hexadecimal
+//! * X - uint as upper-case hexadecimal
+//! * s - str (any flavor)
+//! * ? - arbitrary type (does not use the to_str trait)
+
+/*
+Syntax Extension: fmt
+
+Format a string
+
+The 'fmt' extension is modeled on the posix printf system.
+
+A posix conversion ostensibly looks like this
+
+> %~[parameter]~[flags]~[width]~[.precision]~[length]type
+
+Given the different numeric type bestiary we have, we omit the 'length'
+parameter and support slightly different conversions for 'type'
+
+> %~[parameter]~[flags]~[width]~[.precision]type
+
+we also only support translating-to-rust a tiny subset of the possible
+combinations at the moment.
+
+Example:
+
+debug!("hello, %s!", "world");
+
+*/
+
+use cmp::Eq;
+use prelude::*;
+
+/*
+ * We have a 'ct' (compile-time) module that parses format strings into a
+ * sequence of conversions. From those conversions AST fragments are built
+ * that call into properly-typed functions in the 'rt' (run-time) module.
+ * Each of those run-time conversion functions accepts another conversion
+ * description that specifies how to format its output.
+ *
+ * The building of the AST is currently done in a module inside the compiler,
+ * but should migrate over here as the plugin interface is defined.
+ */
+
+// Functions used by the fmt extension at compile time
+#[doc(hidden)]
+pub mod ct {
+    use char;
+    use prelude::*;
+    use str;
+
+    #[deriving(Eq)]
+    pub enum Signedness { Signed, Unsigned, }
+
+    #[deriving(Eq)]
+    pub enum Caseness { CaseUpper, CaseLower, }
+
+    #[deriving(Eq)]
+    pub enum Ty {
+        TyBool,
+        TyStr,
+        TyChar,
+        TyInt(Signedness),
+        TyBits,
+        TyHex(Caseness),
+        TyOctal,
+        TyFloat,
+        TyPoly,
+    }
+
+    #[deriving(Eq)]
+    pub enum Flag {
+        FlagLeftJustify,
+        FlagLeftZeroPad,
+        FlagSpaceForSign,
+        FlagSignAlways,
+        FlagAlternate,
+    }
+
+    #[deriving(Eq)]
+    pub enum Count {
+        CountIs(uint),
+        CountIsParam(uint),
+        CountIsNextParam,
+        CountImplied,
+    }
+
+    #[deriving(Eq)]
+    struct Parsed<T> {
+        val: T,
+        next: uint
+    }
+
+    pub impl<T> Parsed<T> {
+        fn new(val: T, next: uint) -> Parsed<T> {
+            Parsed {val: val, next: next}
+        }
+    }
+
+    // A formatted conversion from an expression to a string
+    #[deriving(Eq)]
+    pub struct Conv {
+        param: Option<uint>,
+        flags: ~[Flag],
+        width: Count,
+        precision: Count,
+        ty: Ty
+    }
+
+    // A fragment of the output sequence
+    #[deriving(Eq)]
+    pub enum Piece { PieceString(~str), PieceConv(Conv), }
+
+    pub type ErrorFn = @fn(&str) -> !;
+
+    pub fn parse_fmt_string(s: &str, err: ErrorFn) -> ~[Piece] {
+        fn push_slice(ps: &mut ~[Piece], s: &str, from: uint, to: uint) {
+            if to > from {
+                ps.push(PieceString(s.slice(from, to).to_owned()));
+            }
+        }
+
+        let lim = s.len();
+        let mut h = 0;
+        let mut i = 0;
+        let mut pieces = ~[];
+
+        while i < lim {
+            if s[i] == '%' as u8 {
+                i += 1;
+
+                if i >= lim {
+                    err("unterminated conversion at end of string");
+                } else if s[i] == '%' as u8 {
+                    push_slice(&mut pieces, s, h, i);
+                    i += 1;
+                } else {
+                    push_slice(&mut pieces, s, h, i - 1);
+                    let Parsed {val, next} = parse_conversion(s, i, lim, err);
+                    pieces.push(val);
+                    i = next;
+                }
+
+                h = i;
+            } else {
+                i += str::utf8_char_width(s[i]);
+            }
+        }
+
+        push_slice(&mut pieces, s, h, i);
+        pieces
+    }
+
+    pub fn peek_num(s: &str, i: uint, lim: uint) -> Option<Parsed<uint>> {
+        let mut i = i;
+        let mut accum = 0;
+        let mut found = false;
+
+        while i < lim {
+            match char::to_digit(s[i] as char, 10) {
+                Some(x) => {
+                    found = true;
+                    accum *= 10;
+                    accum += x;
+                    i += 1;
+                }
+                None => break
+            }
+        }
+
+        if found {
+            Some(Parsed::new(accum, i))
+        } else {
+            None
+        }
+    }
+
+    pub fn parse_conversion(s: &str, i: uint, lim: uint, err: ErrorFn) ->
+        Parsed<Piece> {
+        let param = parse_parameter(s, i, lim);
+        // avoid copying ~[Flag] by destructuring
+        let Parsed {val: flags_val, next: flags_next} = parse_flags(s,
+            param.next, lim);
+        let width = parse_count(s, flags_next, lim);
+        let prec = parse_precision(s, width.next, lim);
+        let ty = parse_type(s, prec.next, lim, err);
+
+        Parsed::new(PieceConv(Conv {
+            param: param.val,
+            flags: flags_val,
+            width: width.val,
+            precision: prec.val,
+            ty: ty.val}), ty.next)
+    }
+
+    pub fn parse_parameter(s: &str, i: uint, lim: uint) ->
+        Parsed<Option<uint>> {
+        if i >= lim { return Parsed::new(None, i); }
+
+        match peek_num(s, i, lim) {
+            Some(num) if num.next < lim && s[num.next] == '$' as u8 =>
+                Parsed::new(Some(num.val), num.next + 1),
+            _ => Parsed::new(None, i)
+        }
+    }
+
+    pub fn parse_flags(s: &str, i: uint, lim: uint) -> Parsed<~[Flag]> {
+        let mut i = i;
+        let mut flags = ~[];
+
+        while i < lim {
+            let f = match s[i] as char {
+                '-' => FlagLeftJustify,
+                '0' => FlagLeftZeroPad,
+                ' ' => FlagSpaceForSign,
+                '+' => FlagSignAlways,
+                '#' => FlagAlternate,
+                _ => break
+            };
+
+            flags.push(f);
+            i += 1;
+        }
+
+        Parsed::new(flags, i)
+    }
+
+    pub fn parse_count(s: &str, i: uint, lim: uint) -> Parsed<Count> {
+        if i >= lim {
+            Parsed::new(CountImplied, i)
+        } else if s[i] == '*' as u8 {
+            let param = parse_parameter(s, i + 1, lim);
+            let j = param.next;
+
+            match param.val {
+                None => Parsed::new(CountIsNextParam, j),
+                Some(n) => Parsed::new(CountIsParam(n), j)
+            }
+        } else {
+            match peek_num(s, i, lim) {
+                None => Parsed::new(CountImplied, i),
+                Some(num) => Parsed::new(CountIs(num.val), num.next)
+            }
+        }
+    }
+
+    pub fn parse_precision(s: &str, i: uint, lim: uint) -> Parsed<Count> {
+        if i < lim && s[i] == '.' as u8 {
+            let count = parse_count(s, i + 1, lim);
+
+            // If there were no digits specified, i.e. the precision
+            // was ".", then the precision is 0
+            match count.val {
+                CountImplied => Parsed::new(CountIs(0), count.next),
+                _ => count
+            }
+        } else {
+            Parsed::new(CountImplied, i)
+        }
+    }
+
+    pub fn parse_type(s: &str, i: uint, lim: uint, err: ErrorFn) ->
+        Parsed<Ty> {
+        if i >= lim { err("missing type in conversion"); }
+
+        // FIXME (#2249): Do we really want two signed types here?
+        // How important is it to be printf compatible?
+        let t = match s[i] as char {
+            'b' => TyBool,
+            's' => TyStr,
+            'c' => TyChar,
+            'd' | 'i' => TyInt(Signed),
+            'u' => TyInt(Unsigned),
+            'x' => TyHex(CaseLower),
+            'X' => TyHex(CaseUpper),
+            't' => TyBits,
+            'o' => TyOctal,
+            'f' => TyFloat,
+            '?' => TyPoly,
+            _ => err(~"unknown type in conversion: " + s.substr(i, 1))
+        };
+
+        Parsed::new(t, i + 1)
+    }
+
+    #[cfg(test)]
+    fn die(s: &str) -> ! { fail!(s.to_owned()) }
+
+    #[test]
+    fn test_parse_count() {
+        fn test(s: &str, count: Count, next: uint) -> bool {
+            parse_count(s, 0, s.len()) == Parsed::new(count, next)
+        }
+
+        assert!(test("", CountImplied, 0));
+        assert!(test("*", CountIsNextParam, 1));
+        assert!(test("*1", CountIsNextParam, 1));
+        assert!(test("*1$", CountIsParam(1), 3));
+        assert!(test("123", CountIs(123), 3));
+    }
+
+    #[test]
+    fn test_parse_flags() {
+        fn pack(fs: &[Flag]) -> uint {
+            fs.foldl(0, |&p, &f| p | (1 << f as uint))
+        }
+
+        fn test(s: &str, flags: &[Flag], next: uint) {
+            let f = parse_flags(s, 0, s.len());
+            assert_eq!(pack(f.val), pack(flags));
+            assert_eq!(f.next, next);
+        }
+
+        test("", [], 0);
+        test("!#-+ 0", [], 0);
+        test("#-+", [FlagAlternate, FlagLeftJustify, FlagSignAlways], 3);
+        test(" 0", [FlagSpaceForSign, FlagLeftZeroPad], 2);
+    }
+
+    #[test]
+    fn test_parse_fmt_string() {
+        assert!(parse_fmt_string("foo %s bar", die) == ~[
+            PieceString(~"foo "),
+            PieceConv(Conv {
+                param: None,
+                flags: ~[],
+                width: CountImplied,
+                precision: CountImplied,
+                ty: TyStr,
+            }),
+            PieceString(~" bar")]);
+
+        assert!(parse_fmt_string("%s", die) == ~[
+            PieceConv(Conv {
+                param: None,
+                flags: ~[],
+                width: CountImplied,
+                precision: CountImplied,
+                ty: TyStr,
+            })]);
+
+        assert!(parse_fmt_string("%%%%", die) == ~[
+            PieceString(~"%"), PieceString(~"%")]);
+    }
+
+    #[test]
+    fn test_parse_parameter() {
+        fn test(s: &str, param: Option<uint>, next: uint) -> bool {
+            parse_parameter(s, 0, s.len()) == Parsed::new(param, next)
+        }
+
+        assert!(test("", None, 0));
+        assert!(test("foo", None, 0));
+        assert!(test("123", None, 0));
+        assert!(test("123$", Some(123), 4));
+    }
+
+    #[test]
+    fn test_parse_precision() {
+        fn test(s: &str, count: Count, next: uint) -> bool {
+            parse_precision(s, 0, s.len()) == Parsed::new(count, next)
+        }
+
+        assert!(test("", CountImplied, 0));
+        assert!(test(".", CountIs(0), 1));
+        assert!(test(".*", CountIsNextParam, 2));
+        assert!(test(".*1", CountIsNextParam, 2));
+        assert!(test(".*1$", CountIsParam(1), 4));
+        assert!(test(".123", CountIs(123), 4));
+    }
+
+    #[test]
+    fn test_parse_type() {
+        fn test(s: &str, ty: Ty) -> bool {
+            parse_type(s, 0, s.len(), die) == Parsed::new(ty, 1)
+        }
+
+        assert!(test("b", TyBool));
+        assert!(test("c", TyChar));
+        assert!(test("d", TyInt(Signed)));
+        assert!(test("f", TyFloat));
+        assert!(test("i", TyInt(Signed)));
+        assert!(test("o", TyOctal));
+        assert!(test("s", TyStr));
+        assert!(test("t", TyBits));
+        assert!(test("x", TyHex(CaseLower)));
+        assert!(test("X", TyHex(CaseUpper)));
+        assert!(test("?", TyPoly));
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_parse_type_missing() {
+        parse_type("", 0, 0, die);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_parse_type_unknown() {
+        parse_type("!", 0, 1, die);
+    }
+
+    #[test]
+    fn test_peek_num() {
+        let s1 = "";
+        assert!(peek_num(s1, 0, s1.len()).is_none());
+
+        let s2 = "foo";
+        assert!(peek_num(s2, 0, s2.len()).is_none());
+
+        let s3 = "123";
+        assert_eq!(peek_num(s3, 0, s3.len()), Some(Parsed::new(123, 3)));
+
+        let s4 = "123foo";
+        assert_eq!(peek_num(s4, 0, s4.len()), Some(Parsed::new(123, 3)));
+    }
+}
+
+// Functions used by the fmt extension at runtime. For now there are a lot of
+// decisions made a runtime. If it proves worthwhile then some of these
+// conditions can be evaluated at compile-time. For now though it's cleaner to
+// implement it this way, I think.
+#[doc(hidden)]
+pub mod rt {
+    use float;
+    use str;
+    use sys;
+    use int;
+    use uint;
+    use vec;
+    use option::{Some, None, Option};
+
+    pub static flag_none : u32 = 0u32;
+    pub static flag_left_justify   : u32 = 0b00000000000001u32;
+    pub static flag_left_zero_pad  : u32 = 0b00000000000010u32;
+    pub static flag_space_for_sign : u32 = 0b00000000000100u32;
+    pub static flag_sign_always    : u32 = 0b00000000001000u32;
+    pub static flag_alternate      : u32 = 0b00000000010000u32;
+
+    pub enum Count { CountIs(uint), CountImplied, }
+
+    pub enum Ty { TyDefault, TyBits, TyHexUpper, TyHexLower, TyOctal, }
+
+    pub struct Conv {
+        flags: u32,
+        width: Count,
+        precision: Count,
+        ty: Ty,
+    }
+
+    pub fn conv_int(cv: Conv, i: int, buf: &mut ~str) {
+        let radix = 10;
+        let prec = get_int_precision(cv);
+        let s : ~str = uint_to_str_prec(int::abs(i) as uint, radix, prec);
+
+        let head = if i >= 0 {
+            if have_flag(cv.flags, flag_sign_always) {
+                Some('+')
+            } else if have_flag(cv.flags, flag_space_for_sign) {
+                Some(' ')
+            } else {
+                None
+            }
+        } else { Some('-') };
+        pad(cv, s, head, PadSigned, buf);
+    }
+    pub fn conv_uint(cv: Conv, u: uint, buf: &mut ~str) {
+        let prec = get_int_precision(cv);
+        let rs =
+            match cv.ty {
+              TyDefault => uint_to_str_prec(u, 10, prec),
+              TyHexLower => uint_to_str_prec(u, 16, prec),
+
+              // FIXME: #4318 Instead of to_ascii and to_str_ascii, could use
+              // to_ascii_consume and to_str_consume to not do a unnecessary copy.
+              TyHexUpper => {
+                let s = uint_to_str_prec(u, 16, prec);
+                s.to_ascii().to_upper().to_str_ascii()
+              }
+              TyBits => uint_to_str_prec(u, 2, prec),
+              TyOctal => uint_to_str_prec(u, 8, prec)
+            };
+        pad(cv, rs, None, PadUnsigned, buf);
+    }
+    pub fn conv_bool(cv: Conv, b: bool, buf: &mut ~str) {
+        let s = if b { "true" } else { "false" };
+        // run the boolean conversion through the string conversion logic,
+        // giving it the same rules for precision, etc.
+        conv_str(cv, s, buf);
+    }
+    pub fn conv_char(cv: Conv, c: char, buf: &mut ~str) {
+        pad(cv, "", Some(c), PadNozero, buf);
+    }
+    pub fn conv_str(cv: Conv, s: &str, buf: &mut ~str) {
+        // For strings, precision is the maximum characters
+        // displayed
+        let unpadded = match cv.precision {
+          CountImplied => s,
+          CountIs(max) => if (max as uint) < str::char_len(s) {
+            str::slice(s, 0, max as uint)
+          } else {
+            s
+          }
+        };
+        pad(cv, unpadded, None, PadNozero, buf);
+    }
+    pub fn conv_float(cv: Conv, f: float, buf: &mut ~str) {
+        let (to_str, digits) = match cv.precision {
+              CountIs(c) => (float::to_str_exact, c as uint),
+              CountImplied => (float::to_str_digits, 6u)
+        };
+        let s = to_str(f, digits);
+        let head = if 0.0 <= f {
+            if have_flag(cv.flags, flag_sign_always) {
+                Some('+')
+            } else if have_flag(cv.flags, flag_space_for_sign) {
+                Some(' ')
+            } else {
+                None
+            }
+        } else { None };
+        pad(cv, s, head, PadFloat, buf);
+    }
+    pub fn conv_poly<T>(cv: Conv, v: &T, buf: &mut ~str) {
+        let s = sys::log_str(v);
+        conv_str(cv, s, buf);
+    }
+
+    // Convert a uint to string with a minimum number of digits.  If precision
+    // is 0 and num is 0 then the result is the empty string. Could move this
+    // to uint: but it doesn't seem all that useful.
+    pub fn uint_to_str_prec(num: uint, radix: uint, prec: uint) -> ~str {
+        return if prec == 0u && num == 0u {
+                ~""
+            } else {
+                let s = uint::to_str_radix(num, radix);
+                let len = str::char_len(s);
+                if len < prec {
+                    let diff = prec - len;
+                    let pad = str::from_chars(vec::from_elem(diff, '0'));
+                    pad + s
+                } else { s }
+            };
+    }
+    pub fn get_int_precision(cv: Conv) -> uint {
+        return match cv.precision {
+              CountIs(c) => c as uint,
+              CountImplied => 1u
+            };
+    }
+
+    #[deriving(Eq)]
+    pub enum PadMode { PadSigned, PadUnsigned, PadNozero, PadFloat }
+
+    pub fn pad(cv: Conv, s: &str, head: Option<char>, mode: PadMode,
+               buf: &mut ~str) {
+        let headsize = match head { Some(_) => 1, _ => 0 };
+        let uwidth : uint = match cv.width {
+            CountImplied => {
+                for head.each |&c| {
+                    buf.push_char(c);
+                }
+                return buf.push_str(s);
+            }
+            CountIs(width) => { width as uint }
+        };
+        let strlen = str::char_len(s) + headsize;
+        if uwidth <= strlen {
+            for head.each |&c| {
+                buf.push_char(c);
+            }
+            return buf.push_str(s);
+        }
+        let mut padchar = ' ';
+        let diff = uwidth - strlen;
+        if have_flag(cv.flags, flag_left_justify) {
+            for head.each |&c| {
+                buf.push_char(c);
+            }
+            buf.push_str(s);
+            for diff.times {
+                buf.push_char(padchar);
+            }
+            return;
+        }
+        let (might_zero_pad, signed) = match mode {
+          PadNozero   => (false, true),
+          PadSigned   => (true, true),
+          PadFloat    => (true, true),
+          PadUnsigned => (true, false)
+        };
+        fn have_precision(cv: Conv) -> bool {
+            return match cv.precision { CountImplied => false, _ => true };
+        }
+        let zero_padding = {
+            if might_zero_pad && have_flag(cv.flags, flag_left_zero_pad) &&
+                (!have_precision(cv) || mode == PadFloat) {
+                padchar = '0';
+                true
+            } else {
+                false
+            }
+        };
+        let padstr = str::from_chars(vec::from_elem(diff, padchar));
+        // This is completely heinous. If we have a signed value then
+        // potentially rip apart the intermediate result and insert some
+        // zeros. It may make sense to convert zero padding to a precision
+        // instead.
+
+        if signed && zero_padding {
+            for head.each |&head| {
+                if head == '+' || head == '-' || head == ' ' {
+                    buf.push_char(head);
+                    buf.push_str(padstr);
+                    buf.push_str(s);
+                    return;
+                }
+            }
+        }
+        buf.push_str(padstr);
+        for head.each |&c| {
+            buf.push_char(c);
+        }
+        buf.push_str(s);
+    }
+    #[inline(always)]
+    pub fn have_flag(flags: u32, f: u32) -> bool {
+        flags & f != 0
+    }
+}
+
+// Bulk of the tests are in src/test/run-pass/syntax-extension-fmt.rs
+#[cfg(test)]
+mod test {
+    #[test]
+    fn fmt_slice() {
+        let s = "abc";
+        let _s = fmt!("%s", s);
+    }
+}
diff --git a/src/libstd/unstable/finally.rs b/src/libstd/unstable/finally.rs
new file mode 100644
index 00000000000..5001fb421cd
--- /dev/null
+++ b/src/libstd/unstable/finally.rs
@@ -0,0 +1,139 @@
+// 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.
+
+/*!
+The Finally trait provides a method, `finally` on
+stack closures that emulates Java-style try/finally blocks.
+
+# Example
+
+~~~
+do || {
+    ...
+}.finally {
+    alway_run_this();
+}
+~~~
+*/
+
+use ops::Drop;
+
+#[cfg(test)] use task::{failing, spawn};
+
+pub trait Finally<T> {
+    fn finally(&self, dtor: &fn()) -> T;
+}
+
+impl<'self,T> Finally<T> for &'self fn() -> T {
+    fn finally(&self, dtor: &fn()) -> T {
+        let _d = Finallyalizer {
+            dtor: dtor
+        };
+
+        (*self)()
+    }
+}
+
+impl<T> Finally<T> for ~fn() -> T {
+    fn finally(&self, dtor: &fn()) -> T {
+        let _d = Finallyalizer {
+            dtor: dtor
+        };
+
+        (*self)()
+    }
+}
+
+impl<T> Finally<T> for @fn() -> T {
+    fn finally(&self, dtor: &fn()) -> T {
+        let _d = Finallyalizer {
+            dtor: dtor
+        };
+
+        (*self)()
+    }
+}
+
+struct Finallyalizer<'self> {
+    dtor: &'self fn()
+}
+
+#[unsafe_destructor]
+impl<'self> Drop for Finallyalizer<'self> {
+    fn finalize(&self) {
+        (self.dtor)();
+    }
+}
+
+#[test]
+fn test_success() {
+    let mut i = 0;
+    do (|| {
+        i = 10;
+    }).finally {
+        assert!(!failing());
+        assert_eq!(i, 10);
+        i = 20;
+    }
+    assert_eq!(i, 20);
+}
+
+#[test]
+#[ignore(cfg(windows))]
+#[should_fail]
+fn test_fail() {
+    let mut i = 0;
+    do (|| {
+        i = 10;
+        fail!();
+    }).finally {
+        assert!(failing());
+        assert_eq!(i, 10);
+    }
+}
+
+#[test]
+fn test_retval() {
+    let closure: &fn() -> int = || 10;
+    let i = do closure.finally { };
+    assert_eq!(i, 10);
+}
+
+#[test]
+fn test_compact() {
+    // FIXME #4727: Should be able to use a fn item instead
+    // of a closure for do_some_fallible_work,
+    // but it's a type error.
+    let do_some_fallible_work: &fn() = || { };
+    fn but_always_run_this_function() { }
+    do_some_fallible_work.finally(
+        but_always_run_this_function);
+}
+
+#[test]
+fn test_owned() {
+    fn spawn_with_finalizer(f: ~fn()) {
+        do spawn { do f.finally { } }
+    }
+    let owned: ~fn() = || { };
+    spawn_with_finalizer(owned);
+}
+
+#[test]
+fn test_managed() {
+    let i = @mut 10;
+    let managed: @fn() -> int = || {
+        let r = *i;
+        *i += 10;
+        r
+    };
+    assert_eq!(do managed.finally {}, 10);
+    assert_eq!(*i, 20);
+}
\ No newline at end of file
diff --git a/src/libstd/unstable/global.rs b/src/libstd/unstable/global.rs
new file mode 100644
index 00000000000..96549a83a8c
--- /dev/null
+++ b/src/libstd/unstable/global.rs
@@ -0,0 +1,281 @@
+// 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.
+
+/*!
+Global data
+
+An interface for creating and retrieving values with global
+(per-runtime) scope.
+
+Global values are stored in a map and protected by a single global
+mutex. Operations are provided for accessing and cloning the value
+under the mutex.
+
+Because all globals go through a single mutex, they should be used
+sparingly.  The interface is intended to be used with clonable,
+atomically reference counted synchronization types, like ARCs, in
+which case the value should be cached locally whenever possible to
+avoid hitting the mutex.
+*/
+
+use cast::{transmute};
+use clone::Clone;
+use kinds::Owned;
+use libc::{c_void};
+use option::{Option, Some, None};
+use ops::Drop;
+use unstable::sync::{Exclusive, exclusive};
+use unstable::at_exit::at_exit;
+use unstable::intrinsics::atomic_cxchg;
+use hashmap::HashMap;
+use sys::Closure;
+
+#[cfg(test)] use unstable::sync::{UnsafeAtomicRcBox};
+#[cfg(test)] use task::spawn;
+#[cfg(test)] use uint;
+
+pub type GlobalDataKey<'self,T> = &'self fn(v: T);
+
+pub unsafe fn global_data_clone_create<T:Owned + Clone>(
+    key: GlobalDataKey<T>, create: &fn() -> ~T) -> T {
+    /*!
+     * Clone a global value or, if it has not been created,
+     * first construct the value then return a clone.
+     *
+     * # Safety note
+     *
+     * Both the clone operation and the constructor are
+     * called while the global lock is held. Recursive
+     * use of the global interface in either of these
+     * operations will result in deadlock.
+     */
+    global_data_clone_create_(key_ptr(key), create)
+}
+
+unsafe fn global_data_clone_create_<T:Owned + Clone>(
+    key: uint, create: &fn() -> ~T) -> T {
+
+    let mut clone_value: Option<T> = None;
+    do global_data_modify_(key) |value: Option<~T>| {
+        match value {
+            None => {
+                let value = create();
+                clone_value = Some((*value).clone());
+                Some(value)
+            }
+            Some(value) => {
+                clone_value = Some((*value).clone());
+                Some(value)
+            }
+        }
+    }
+    return clone_value.unwrap();
+}
+
+unsafe fn global_data_modify<T:Owned>(
+    key: GlobalDataKey<T>, op: &fn(Option<~T>) -> Option<~T>) {
+
+    global_data_modify_(key_ptr(key), op)
+}
+
+unsafe fn global_data_modify_<T:Owned>(
+    key: uint, op: &fn(Option<~T>) -> Option<~T>) {
+
+    let mut old_dtor = None;
+    do get_global_state().with |gs| {
+        let (maybe_new_value, maybe_dtor) = match gs.map.pop(&key) {
+            Some((ptr, dtor)) => {
+                let value: ~T = transmute(ptr);
+                (op(Some(value)), Some(dtor))
+            }
+            None => {
+                (op(None), None)
+            }
+        };
+        match maybe_new_value {
+            Some(value) => {
+                let data: *c_void = transmute(value);
+                let dtor: ~fn() = match maybe_dtor {
+                    Some(dtor) => dtor,
+                    None => {
+                        let dtor: ~fn() = || unsafe {
+                            let _destroy_value: ~T = transmute(data);
+                        };
+                        dtor
+                    }
+                };
+                let value = (data, dtor);
+                gs.map.insert(key, value);
+            }
+            None => {
+                match maybe_dtor {
+                    Some(dtor) => old_dtor = Some(dtor),
+                    None => ()
+                }
+            }
+        }
+    }
+}
+
+pub unsafe fn global_data_clone<T:Owned + Clone>(
+    key: GlobalDataKey<T>) -> Option<T> {
+    let mut maybe_clone: Option<T> = None;
+    do global_data_modify(key) |current| {
+        match &current {
+            &Some(~ref value) => {
+                maybe_clone = Some(value.clone());
+            }
+            &None => ()
+        }
+        current
+    }
+    return maybe_clone;
+}
+
+// GlobalState is a map from keys to unique pointers and a
+// destructor. Keys are pointers derived from the type of the
+// global value.  There is a single GlobalState instance per runtime.
+struct GlobalState {
+    map: HashMap<uint, (*c_void, ~fn())>
+}
+
+impl Drop for GlobalState {
+    fn finalize(&self) {
+        for self.map.each_value |v| {
+            match v {
+                &(_, ref dtor) => (*dtor)()
+            }
+        }
+    }
+}
+
+fn get_global_state() -> Exclusive<GlobalState> {
+
+    static POISON: int = -1;
+
+    // FIXME #4728: Doing atomic_cxchg to initialize the global state
+    // lazily, which wouldn't be necessary with a runtime written
+    // in Rust
+    let global_ptr = unsafe { rust_get_global_data_ptr() };
+
+    if unsafe { *global_ptr } == 0 {
+        // Global state doesn't exist yet, probably
+
+        // The global state object
+        let state = GlobalState {
+            map: HashMap::new()
+        };
+
+        // It's under a reference-counted mutex
+        let state = ~exclusive(state);
+
+        // Convert it to an integer
+        let state_i: int = unsafe {
+            let state_ptr: &Exclusive<GlobalState> = state;
+            transmute(state_ptr)
+        };
+
+        // Swap our structure into the global pointer
+        let prev_i = unsafe { atomic_cxchg(&mut *global_ptr, 0, state_i) };
+
+        // Sanity check that we're not trying to reinitialize after shutdown
+        assert!(prev_i != POISON);
+
+        if prev_i == 0 {
+            // Successfully installed the global pointer
+
+            // Take a handle to return
+            let clone = (*state).clone();
+
+            // Install a runtime exit function to destroy the global object
+            do at_exit {
+                // Poison the global pointer
+                let prev_i = unsafe {
+                    atomic_cxchg(&mut *global_ptr, state_i, POISON)
+                };
+                assert_eq!(prev_i, state_i);
+
+                // Capture the global state object in the at_exit closure
+                // so that it is destroyed at the right time
+                let _capture_global_state = &state;
+            };
+            return clone;
+        } else {
+            // Somebody else initialized the globals first
+            let state: &Exclusive<GlobalState> = unsafe { transmute(prev_i) };
+            return state.clone();
+        }
+    } else {
+        let state: &Exclusive<GlobalState> = unsafe {
+            transmute(*global_ptr)
+        };
+        return state.clone();
+    }
+}
+
+fn key_ptr<T:Owned>(key: GlobalDataKey<T>) -> uint {
+    unsafe {
+        let closure: Closure = transmute(key);
+        return transmute(closure.code);
+    }
+}
+
+extern {
+    fn rust_get_global_data_ptr() -> *mut int;
+}
+
+#[test]
+fn test_clone_rc() {
+    fn key(_v: UnsafeAtomicRcBox<int>) { }
+
+    for uint::range(0, 100) |_| {
+        do spawn {
+            unsafe {
+                let val = do global_data_clone_create(key) {
+                    ~UnsafeAtomicRcBox::new(10)
+                };
+
+                assert!(val.get() == &10);
+            }
+        }
+    }
+}
+
+#[test]
+fn test_modify() {
+    fn key(_v: UnsafeAtomicRcBox<int>) { }
+
+    unsafe {
+        do global_data_modify(key) |v| {
+            match v {
+                None => { Some(~UnsafeAtomicRcBox::new(10)) }
+                _ => fail!()
+            }
+        }
+
+        do global_data_modify(key) |v| {
+            match v {
+                Some(sms) => {
+                    let v = sms.get();
+                    assert!(*v == 10);
+                    None
+                },
+                _ => fail!()
+            }
+        }
+
+        do global_data_modify(key) |v| {
+            match v {
+                None => { Some(~UnsafeAtomicRcBox::new(10)) }
+                _ => fail!()
+            }
+        }
+    }
+}
diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs
new file mode 100644
index 00000000000..d476822819e
--- /dev/null
+++ b/src/libstd/unstable/intrinsics.rs
@@ -0,0 +1,211 @@
+// 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.
+
+/*! rustc compiler intrinsics.
+
+The corresponding definitions are in librustc/middle/trans/foreign.rs.
+
+# Atomics
+
+The atomic intrinsics provide common atomic operations on machine
+words, with multiple possible memory orderings. They obey the same
+semantics as C++0x. See the LLVM documentation on [[atomics]].
+
+[atomics]: http://llvm.org/docs/Atomics.html
+
+A quick refresher on memory ordering:
+
+* Acquire - a barrier for aquiring a lock. Subsequent reads and writes
+  take place after the barrier.
+* Release - a barrier for releasing a lock. Preceding reads and writes
+  take place before the barrier.
+* Sequentially consistent - sequentially consistent operations are
+  guaranteed to happen in order. This is the standard mode for working
+  with atomic types and is equivalent to Java's `volatile`.
+
+*/
+
+#[abi = "rust-intrinsic"]
+pub extern "rust-intrinsic" {
+
+    /// Atomic compare and exchange, sequentially consistent.
+    pub fn atomic_cxchg(dst: &mut int, old: int, src: int) -> int;
+    /// Atomic compare and exchange, acquire ordering.
+    pub fn atomic_cxchg_acq(dst: &mut int, old: int, src: int) -> int;
+    /// Atomic compare and exchange, release ordering.
+    pub fn atomic_cxchg_rel(dst: &mut int, old: int, src: int) -> int;
+
+    /// Atomic load, sequentially consistent.
+    pub fn atomic_load(src: &int) -> int;
+    /// Atomic load, acquire ordering.
+    pub fn atomic_load_acq(src: &int) -> int;
+
+    /// Atomic store, sequentially consistent.
+    pub fn atomic_store(dst: &mut int, val: int);
+    /// Atomic store, release ordering.
+    pub fn atomic_store_rel(dst: &mut int, val: int);
+
+    /// Atomic exchange, sequentially consistent.
+    pub fn atomic_xchg(dst: &mut int, src: int) -> int;
+    /// Atomic exchange, acquire ordering.
+    pub fn atomic_xchg_acq(dst: &mut int, src: int) -> int;
+    /// Atomic exchange, release ordering.
+    pub fn atomic_xchg_rel(dst: &mut int, src: int) -> int;
+
+    /// Atomic addition, sequentially consistent.
+    pub fn atomic_xadd(dst: &mut int, src: int) -> int;
+    /// Atomic addition, acquire ordering.
+    pub fn atomic_xadd_acq(dst: &mut int, src: int) -> int;
+    /// Atomic addition, release ordering.
+    pub fn atomic_xadd_rel(dst: &mut int, src: int) -> int;
+
+    /// Atomic subtraction, sequentially consistent.
+    pub fn atomic_xsub(dst: &mut int, src: int) -> int;
+    /// Atomic subtraction, acquire ordering.
+    pub fn atomic_xsub_acq(dst: &mut int, src: int) -> int;
+    /// Atomic subtraction, release ordering.
+    pub fn atomic_xsub_rel(dst: &mut int, src: int) -> int;
+
+    /// The size of a type in bytes.
+    ///
+    /// This is the exact number of bytes in memory taken up by a
+    /// value of the given type. In other words, a memset of this size
+    /// would *exactly* overwrite a value. When laid out in vectors
+    /// and structures there may be additional padding between
+    /// elements.
+    pub fn size_of<T>() -> uint;
+
+    /// Move a value to a memory location containing a value.
+    ///
+    /// Drop glue is run on the destination, which must contain a
+    /// valid Rust value.
+    pub fn move_val<T>(dst: &mut T, src: T);
+
+    /// Move a value to an uninitialized memory location.
+    ///
+    /// Drop glue is not run on the destination.
+    pub fn move_val_init<T>(dst: &mut T, src: T);
+
+    pub fn min_align_of<T>() -> uint;
+    pub fn pref_align_of<T>() -> uint;
+
+    /// Get a static pointer to a type descriptor.
+    pub fn get_tydesc<T>() -> *();
+
+    /// Create a value initialized to zero.
+    ///
+    /// `init` is unsafe because it returns a zeroed-out datum,
+    /// which is unsafe unless T is POD. We don't have a POD
+    /// kind yet. (See #4074).
+    pub unsafe fn init<T>() -> T;
+
+    /// Create an uninitialized value.
+    pub unsafe fn uninit<T>() -> T;
+
+    /// Move a value out of scope without running drop glue.
+    ///
+    /// `forget` is unsafe because the caller is responsible for
+    /// ensuring the argument is deallocated already.
+    pub unsafe fn forget<T>(_: T) -> ();
+    pub fn transmute<T,U>(e: T) -> U;
+
+    /// Returns `true` if a type requires drop glue.
+    pub fn needs_drop<T>() -> bool;
+
+    // XXX: intrinsic uses legacy modes and has reference to TyDesc
+    // and TyVisitor which are in librustc
+    //fn visit_tydesc(++td: *TyDesc, &&tv: TyVisitor) -> ();
+
+    pub fn frame_address(f: &once fn(*u8));
+
+    /// Get the address of the `__morestack` stack growth function.
+    pub fn morestack_addr() -> *();
+
+    /// Equivalent to the `llvm.memmove.p0i8.0i8.i32` intrinsic.
+    pub fn memmove32(dst: *mut u8, src: *u8, size: u32);
+    /// Equivalent to the `llvm.memmove.p0i8.0i8.i64` intrinsic.
+    pub fn memmove64(dst: *mut u8, src: *u8, size: u64);
+
+    pub fn sqrtf32(x: f32) -> f32;
+    pub fn sqrtf64(x: f64) -> f64;
+
+    pub fn powif32(a: f32, x: i32) -> f32;
+    pub fn powif64(a: f64, x: i32) -> f64;
+
+    // the following kill the stack canary without
+    // `fixed_stack_segment`. This possibly only affects the f64
+    // variants, but it's hard to be sure since it seems to only
+    // occur with fairly specific arguments.
+    #[fixed_stack_segment]
+    pub fn sinf32(x: f32) -> f32;
+    #[fixed_stack_segment]
+    pub fn sinf64(x: f64) -> f64;
+
+    #[fixed_stack_segment]
+    pub fn cosf32(x: f32) -> f32;
+    #[fixed_stack_segment]
+    pub fn cosf64(x: f64) -> f64;
+
+    #[fixed_stack_segment]
+    pub fn powf32(a: f32, x: f32) -> f32;
+    #[fixed_stack_segment]
+    pub fn powf64(a: f64, x: f64) -> f64;
+
+    #[fixed_stack_segment]
+    pub fn expf32(x: f32) -> f32;
+    #[fixed_stack_segment]
+    pub fn expf64(x: f64) -> f64;
+
+    pub fn exp2f32(x: f32) -> f32;
+    pub fn exp2f64(x: f64) -> f64;
+
+    pub fn logf32(x: f32) -> f32;
+    pub fn logf64(x: f64) -> f64;
+
+    pub fn log10f32(x: f32) -> f32;
+    pub fn log10f64(x: f64) -> f64;
+
+    pub fn log2f32(x: f32) -> f32;
+    pub fn log2f64(x: f64) -> f64;
+
+    pub fn fmaf32(a: f32, b: f32, c: f32) -> f32;
+    pub fn fmaf64(a: f64, b: f64, c: f64) -> f64;
+
+    pub fn fabsf32(x: f32) -> f32;
+    pub fn fabsf64(x: f64) -> f64;
+
+    pub fn floorf32(x: f32) -> f32;
+    pub fn floorf64(x: f64) -> f64;
+
+    pub fn ceilf32(x: f32) -> f32;
+    pub fn ceilf64(x: f64) -> f64;
+
+    pub fn truncf32(x: f32) -> f32;
+    pub fn truncf64(x: f64) -> f64;
+
+    pub fn ctpop8(x: i8) -> i8;
+    pub fn ctpop16(x: i16) -> i16;
+    pub fn ctpop32(x: i32) -> i32;
+    pub fn ctpop64(x: i64) -> i64;
+
+    pub fn ctlz8(x: i8) -> i8;
+    pub fn ctlz16(x: i16) -> i16;
+    pub fn ctlz32(x: i32) -> i32;
+    pub fn ctlz64(x: i64) -> i64;
+
+    pub fn cttz8(x: i8) -> i8;
+    pub fn cttz16(x: i16) -> i16;
+    pub fn cttz32(x: i32) -> i32;
+    pub fn cttz64(x: i64) -> i64;
+
+    pub fn bswap16(x: i16) -> i16;
+    pub fn bswap32(x: i32) -> i32;
+    pub fn bswap64(x: i64) -> i64;
+}
diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs
new file mode 100644
index 00000000000..350b18d4541
--- /dev/null
+++ b/src/libstd/unstable/lang.rs
@@ -0,0 +1,420 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Runtime calls emitted by the compiler.
+
+use uint;
+use cast::transmute;
+use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int, STDERR_FILENO};
+use managed::raw::BoxRepr;
+use str;
+use sys;
+use rt::{context, OldTaskContext};
+use rt::task::Task;
+use rt::local::Local;
+use option::{Option, Some, None};
+use io;
+use rt::global_heap;
+
+#[allow(non_camel_case_types)]
+pub type rust_task = c_void;
+
+pub static FROZEN_BIT: uint = 1 << (uint::bits - 1);
+pub static MUT_BIT: uint = 1 << (uint::bits - 2);
+static ALL_BITS: uint = FROZEN_BIT | MUT_BIT;
+
+pub mod rustrt {
+    use unstable::lang::rust_task;
+    use libc::{c_void, c_char, uintptr_t};
+
+    pub extern {
+        #[rust_stack]
+        unsafe fn rust_upcall_malloc(td: *c_char, size: uintptr_t) -> *c_char;
+
+        #[rust_stack]
+        unsafe fn rust_upcall_free(ptr: *c_char);
+
+        #[fast_ffi]
+        unsafe fn rust_upcall_malloc_noswitch(td: *c_char,
+                                              size: uintptr_t)
+                                           -> *c_char;
+
+        #[fast_ffi]
+        unsafe fn rust_upcall_free_noswitch(ptr: *c_char);
+
+        #[rust_stack]
+        fn rust_take_task_borrow_list(task: *rust_task) -> *c_void;
+
+        #[rust_stack]
+        fn rust_set_task_borrow_list(task: *rust_task, map: *c_void);
+
+        #[rust_stack]
+        fn rust_try_get_task() -> *rust_task;
+
+        fn rust_dbg_breakpoint();
+    }
+}
+
+#[lang="fail_"]
+pub fn fail_(expr: *c_char, file: *c_char, line: size_t) -> ! {
+    sys::begin_unwind_(expr, file, line);
+}
+
+#[lang="fail_bounds_check"]
+pub fn fail_bounds_check(file: *c_char, line: size_t,
+                         index: size_t, len: size_t) {
+    let msg = fmt!("index out of bounds: the len is %d but the index is %d",
+                    len as int, index as int);
+    do str::as_buf(msg) |p, _len| {
+        fail_(p as *c_char, file, line);
+    }
+}
+
+#[deriving(Eq)]
+struct BorrowRecord {
+    box: *mut BoxRepr,
+    file: *c_char,
+    line: size_t
+}
+
+fn try_take_task_borrow_list() -> Option<~[BorrowRecord]> {
+    unsafe {
+        let cur_task: *rust_task = rustrt::rust_try_get_task();
+        if cur_task.is_not_null() {
+            let ptr = rustrt::rust_take_task_borrow_list(cur_task);
+            if ptr.is_null() {
+                None
+            } else {
+                let v: ~[BorrowRecord] = transmute(ptr);
+                Some(v)
+            }
+        } else {
+            None
+        }
+    }
+}
+
+fn swap_task_borrow_list(f: &fn(~[BorrowRecord]) -> ~[BorrowRecord]) {
+    unsafe {
+        let cur_task: *rust_task = rustrt::rust_try_get_task();
+        if cur_task.is_not_null() {
+            let mut borrow_list: ~[BorrowRecord] = {
+                let ptr = rustrt::rust_take_task_borrow_list(cur_task);
+                if ptr.is_null() { ~[] } else { transmute(ptr) }
+            };
+            borrow_list = f(borrow_list);
+            rustrt::rust_set_task_borrow_list(cur_task, transmute(borrow_list));
+        }
+    }
+}
+
+pub unsafe fn clear_task_borrow_list() {
+    // pub because it is used by the box annihilator.
+    let _ = try_take_task_borrow_list();
+}
+
+unsafe fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) {
+    debug_borrow("fail_borrowed: ", box, 0, 0, file, line);
+
+    match try_take_task_borrow_list() {
+        None => { // not recording borrows
+            let msg = "borrowed";
+            do str::as_buf(msg) |msg_p, _| {
+                fail_(msg_p as *c_char, file, line);
+            }
+        }
+        Some(borrow_list) => { // recording borrows
+            let mut msg = ~"borrowed";
+            let mut sep = " at ";
+            for borrow_list.each_reverse |entry| {
+                if entry.box == box {
+                    str::push_str(&mut msg, sep);
+                    let filename = str::raw::from_c_str(entry.file);
+                    str::push_str(&mut msg, filename);
+                    str::push_str(&mut msg, fmt!(":%u", entry.line as uint));
+                    sep = " and at ";
+                }
+            }
+            do str::as_buf(msg) |msg_p, _| {
+                fail_(msg_p as *c_char, file, line)
+            }
+        }
+    }
+}
+
+// FIXME #4942: Make these signatures agree with exchange_alloc's signatures
+#[lang="exchange_malloc"]
+#[inline(always)]
+pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
+    transmute(global_heap::malloc(transmute(td), transmute(size)))
+}
+
+/// Because this code is so perf. sensitive, use a static constant so that
+/// debug printouts are compiled out most of the time.
+static ENABLE_DEBUG: bool = false;
+
+#[inline]
+unsafe fn debug_borrow<T>(tag: &'static str,
+                          p: *const T,
+                          old_bits: uint,
+                          new_bits: uint,
+                          filename: *c_char,
+                          line: size_t) {
+    //! A useful debugging function that prints a pointer + tag + newline
+    //! without allocating memory.
+
+    if ENABLE_DEBUG && ::rt::env::get().debug_borrow {
+        debug_borrow_slow(tag, p, old_bits, new_bits, filename, line);
+    }
+
+    unsafe fn debug_borrow_slow<T>(tag: &'static str,
+                                   p: *const T,
+                                   old_bits: uint,
+                                   new_bits: uint,
+                                   filename: *c_char,
+                                   line: size_t) {
+        let dbg = STDERR_FILENO as io::fd_t;
+        dbg.write_str(tag);
+        dbg.write_hex(p as uint);
+        dbg.write_str(" ");
+        dbg.write_hex(old_bits);
+        dbg.write_str(" ");
+        dbg.write_hex(new_bits);
+        dbg.write_str(" ");
+        dbg.write_cstr(filename);
+        dbg.write_str(":");
+        dbg.write_hex(line as uint);
+        dbg.write_str("\n");
+    }
+}
+
+trait DebugPrints {
+    fn write_hex(&self, val: uint);
+    unsafe fn write_cstr(&self, str: *c_char);
+}
+
+impl DebugPrints for io::fd_t {
+    fn write_hex(&self, mut i: uint) {
+        let letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8',
+                       '9', 'a', 'b', 'c', 'd', 'e', 'f'];
+        static uint_nibbles: uint = ::uint::bytes << 1;
+        let mut buffer = [0_u8, ..uint_nibbles+1];
+        let mut c = uint_nibbles;
+        while c > 0 {
+            c -= 1;
+            buffer[c] = letters[i & 0xF] as u8;
+            i >>= 4;
+        }
+        self.write(buffer.slice(0, uint_nibbles));
+    }
+
+    unsafe fn write_cstr(&self, p: *c_char) {
+        use libc::strlen;
+        use vec;
+
+        let len = strlen(p);
+        let p: *u8 = transmute(p);
+        do vec::raw::buf_as_slice(p, len as uint) |s| {
+            self.write(s);
+        }
+    }
+}
+
+// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
+// inside a landing pad may corrupt the state of the exception handler. If a
+// problem occurs, call exit instead.
+#[lang="exchange_free"]
+#[inline(always)]
+pub unsafe fn exchange_free(ptr: *c_char) {
+    global_heap::free(transmute(ptr))
+}
+
+#[lang="malloc"]
+pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
+    match context() {
+        OldTaskContext => {
+            return rustrt::rust_upcall_malloc_noswitch(td, size);
+        }
+        _ => {
+            let mut alloc = ::ptr::null();
+            do Local::borrow::<Task> |task| {
+                alloc = task.heap.alloc(td as *c_void, size as uint) as *c_char;
+            }
+            return alloc;
+        }
+    }
+}
+
+// NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
+// inside a landing pad may corrupt the state of the exception handler. If a
+// problem occurs, call exit instead.
+#[lang="free"]
+pub unsafe fn local_free(ptr: *c_char) {
+    match context() {
+        OldTaskContext => {
+            rustrt::rust_upcall_free_noswitch(ptr);
+        }
+        _ => {
+            do Local::borrow::<Task> |task| {
+                task.heap.free(ptr as *c_void);
+            }
+        }
+    }
+}
+
+#[lang="borrow_as_imm"]
+#[inline(always)]
+pub unsafe fn borrow_as_imm(a: *u8, file: *c_char, line: size_t) -> uint {
+    let a: *mut BoxRepr = transmute(a);
+    let old_ref_count = (*a).header.ref_count;
+    let new_ref_count = old_ref_count | FROZEN_BIT;
+
+    debug_borrow("borrow_as_imm:", a, old_ref_count, new_ref_count, file, line);
+
+    if (old_ref_count & MUT_BIT) != 0 {
+        fail_borrowed(a, file, line);
+    }
+
+    (*a).header.ref_count = new_ref_count;
+
+    old_ref_count
+}
+
+#[lang="borrow_as_mut"]
+#[inline(always)]
+pub unsafe fn borrow_as_mut(a: *u8, file: *c_char, line: size_t) -> uint {
+    let a: *mut BoxRepr = transmute(a);
+    let old_ref_count = (*a).header.ref_count;
+    let new_ref_count = old_ref_count | MUT_BIT | FROZEN_BIT;
+
+    debug_borrow("borrow_as_mut:", a, old_ref_count, new_ref_count, file, line);
+
+    if (old_ref_count & (MUT_BIT|FROZEN_BIT)) != 0 {
+        fail_borrowed(a, file, line);
+    }
+
+    (*a).header.ref_count = new_ref_count;
+
+    old_ref_count
+}
+
+
+#[lang="record_borrow"]
+pub unsafe fn record_borrow(a: *u8, old_ref_count: uint,
+                            file: *c_char, line: size_t) {
+    if (old_ref_count & ALL_BITS) == 0 {
+        // was not borrowed before
+        let a: *mut BoxRepr = transmute(a);
+        debug_borrow("record_borrow:", a, old_ref_count, 0, file, line);
+        do swap_task_borrow_list |borrow_list| {
+            let mut borrow_list = borrow_list;
+            borrow_list.push(BorrowRecord {box: a, file: file, line: line});
+            borrow_list
+        }
+    }
+}
+
+#[lang="unrecord_borrow"]
+pub unsafe fn unrecord_borrow(a: *u8, old_ref_count: uint,
+                              file: *c_char, line: size_t) {
+    if (old_ref_count & ALL_BITS) == 0 {
+        // was not borrowed before, so we should find the record at
+        // the end of the list
+        let a: *mut BoxRepr = transmute(a);
+        debug_borrow("unrecord_borrow:", a, old_ref_count, 0, file, line);
+        do swap_task_borrow_list |borrow_list| {
+            let mut borrow_list = borrow_list;
+            assert!(!borrow_list.is_empty());
+            let br = borrow_list.pop();
+            if br.box != a || br.file != file || br.line != line {
+                let err = fmt!("wrong borrow found, br=%?", br);
+                do str::as_buf(err) |msg_p, _| {
+                    fail_(msg_p as *c_char, file, line)
+                }
+            }
+            borrow_list
+        }
+    }
+}
+
+#[lang="return_to_mut"]
+#[inline(always)]
+pub unsafe fn return_to_mut(a: *u8, orig_ref_count: uint,
+                            file: *c_char, line: size_t) {
+    // Sometimes the box is null, if it is conditionally frozen.
+    // See e.g. #4904.
+    if !a.is_null() {
+        let a: *mut BoxRepr = transmute(a);
+        let old_ref_count = (*a).header.ref_count;
+        let new_ref_count =
+            (old_ref_count & !ALL_BITS) | (orig_ref_count & ALL_BITS);
+
+        debug_borrow("return_to_mut:",
+                     a, old_ref_count, new_ref_count, file, line);
+
+        (*a).header.ref_count = new_ref_count;
+    }
+}
+
+#[lang="check_not_borrowed"]
+#[inline(always)]
+pub unsafe fn check_not_borrowed(a: *u8,
+                                 file: *c_char,
+                                 line: size_t) {
+    let a: *mut BoxRepr = transmute(a);
+    let ref_count = (*a).header.ref_count;
+    debug_borrow("check_not_borrowed:", a, ref_count, 0, file, line);
+    if (ref_count & FROZEN_BIT) != 0 {
+        fail_borrowed(a, file, line);
+    }
+}
+
+#[lang="strdup_uniq"]
+#[inline(always)]
+pub unsafe fn strdup_uniq(ptr: *c_uchar, len: uint) -> ~str {
+    str::raw::from_buf_len(ptr, len)
+}
+
+#[lang="start"]
+pub fn start(main: *u8, argc: int, argv: **c_char,
+             crate_map: *u8) -> int {
+    use rt;
+    use sys::Closure;
+    use ptr;
+    use cast;
+    use os;
+
+    unsafe {
+        let use_old_rt = os::getenv("RUST_NEWRT").is_none();
+        if use_old_rt {
+            return rust_start(main as *c_void, argc as c_int, argv,
+                              crate_map as *c_void) as int;
+        } else {
+            return do rt::start(argc, argv as **u8, crate_map) {
+                unsafe {
+                    // `main` is an `fn() -> ()` that doesn't take an environment
+                    // XXX: Could also call this as an `extern "Rust" fn` once they work
+                    let main = Closure {
+                        code: main as *(),
+                        env: ptr::null(),
+                    };
+                    let mainfn: &fn() = cast::transmute(main);
+
+                    mainfn();
+                }
+            };
+        }
+    }
+
+    extern {
+        fn rust_start(main: *c_void, argc: c_int, argv: **c_char,
+                      crate_map: *c_void) -> c_int;
+    }
+}
diff --git a/src/libstd/unstable/mod.rs b/src/libstd/unstable/mod.rs
new file mode 100644
index 00000000000..9681a3f36fc
--- /dev/null
+++ b/src/libstd/unstable/mod.rs
@@ -0,0 +1,77 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[doc(hidden)];
+
+use libc;
+use comm::{GenericChan, GenericPort};
+use prelude::*;
+use task;
+
+pub mod at_exit;
+pub mod global;
+pub mod finally;
+pub mod weak_task;
+pub mod intrinsics;
+pub mod simd;
+pub mod extfmt;
+#[cfg(not(test))]
+pub mod lang;
+pub mod sync;
+
+/**
+
+Start a new thread outside of the current runtime context and wait
+for it to terminate.
+
+The executing thread has no access to a task pointer and will be using
+a normal large stack.
+*/
+pub fn run_in_bare_thread(f: ~fn()) {
+    let (port, chan) = comm::stream();
+    // FIXME #4525: Unfortunate that this creates an extra scheduler but it's
+    // necessary since rust_raw_thread_join_delete is blocking
+    do task::spawn_sched(task::SingleThreaded) {
+        unsafe {
+            let closure: &fn() = || {
+                f()
+            };
+            let thread = rust_raw_thread_start(&closure);
+            rust_raw_thread_join_delete(thread);
+            chan.send(());
+        }
+    }
+    port.recv();
+}
+
+#[test]
+fn test_run_in_bare_thread() {
+    let i = 100;
+    do run_in_bare_thread {
+        assert_eq!(i, 100);
+    }
+}
+
+#[test]
+fn test_run_in_bare_thread_exchange() {
+    // Does the exchange heap work without the runtime?
+    let i = ~100;
+    do run_in_bare_thread {
+        assert!(i == ~100);
+    }
+}
+
+#[allow(non_camel_case_types)] // runtime type
+pub type raw_thread = libc::c_void;
+
+extern {
+    fn rust_raw_thread_start(f: &(&fn())) -> *raw_thread;
+    fn rust_raw_thread_join_delete(thread: *raw_thread);
+}
diff --git a/src/libstd/unstable/simd.rs b/src/libstd/unstable/simd.rs
new file mode 100644
index 00000000000..a05f6e8af5a
--- /dev/null
+++ b/src/libstd/unstable/simd.rs
@@ -0,0 +1,43 @@
+// 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.
+
+//! SIMD vectors
+
+#[allow(non_camel_case_types)];
+
+#[simd]
+pub struct i8x16(i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8);
+
+#[simd]
+pub struct i16x8(i16, i16, i16, i16, i16, i16, i16, i16);
+
+#[simd]
+pub struct i32x4(i32, i32, i32, i32);
+
+#[simd]
+pub struct i64x2(i64, i64);
+
+#[simd]
+pub struct u8x16(u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8, u8);
+
+#[simd]
+pub struct u16x8(u16, u16, u16, u16, u16, u16, u16, u16);
+
+#[simd]
+pub struct u32x4(u32, u32, u32, u32);
+
+#[simd]
+pub struct u64x2(u64, u64);
+
+#[simd]
+pub struct f32x4(f32, f32, f32, f32);
+
+#[simd]
+pub struct f64x2(f64, f64);
diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs
new file mode 100644
index 00000000000..734368c70c4
--- /dev/null
+++ b/src/libstd/unstable/sync.rs
@@ -0,0 +1,261 @@
+// 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 cast;
+use libc;
+use option::*;
+use task;
+use task::atomically;
+use unstable::finally::Finally;
+use unstable::intrinsics;
+use ops::Drop;
+use clone::Clone;
+use kinds::Owned;
+
+/// An atomically reference counted pointer.
+///
+/// Enforces no shared-memory safety.
+pub struct UnsafeAtomicRcBox<T> {
+    data: *mut libc::c_void,
+}
+
+struct AtomicRcBoxData<T> {
+    count: int,
+    data: Option<T>,
+}
+
+impl<T: Owned> UnsafeAtomicRcBox<T> {
+    pub fn new(data: T) -> UnsafeAtomicRcBox<T> {
+        unsafe {
+            let data = ~AtomicRcBoxData { count: 1, data: Some(data) };
+            let ptr = cast::transmute(data);
+            return UnsafeAtomicRcBox { data: ptr };
+        }
+    }
+
+    #[inline(always)]
+    pub unsafe fn get(&self) -> *mut T
+    {
+        let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data);
+        assert!(data.count > 0);
+        let r: *mut T = data.data.get_mut_ref();
+        cast::forget(data);
+        return r;
+    }
+
+    #[inline(always)]
+    pub unsafe fn get_immut(&self) -> *T
+    {
+        let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data);
+        assert!(data.count > 0);
+        let r: *T = cast::transmute_immut(data.data.get_mut_ref());
+        cast::forget(data);
+        return r;
+    }
+}
+
+impl<T: Owned> Clone for UnsafeAtomicRcBox<T> {
+    fn clone(&self) -> UnsafeAtomicRcBox<T> {
+        unsafe {
+            let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data);
+            let new_count = intrinsics::atomic_xadd(&mut data.count, 1) + 1;
+            assert!(new_count >= 2);
+            cast::forget(data);
+            return UnsafeAtomicRcBox { data: self.data };
+        }
+    }
+}
+
+#[unsafe_destructor]
+impl<T> Drop for UnsafeAtomicRcBox<T>{
+    fn finalize(&self) {
+        unsafe {
+            do task::unkillable {
+                let mut data: ~AtomicRcBoxData<T> = cast::transmute(self.data);
+                let new_count = intrinsics::atomic_xsub(&mut data.count, 1) - 1;
+                assert!(new_count >= 0);
+                if new_count == 0 {
+                    // drop glue takes over.
+                } else {
+                    cast::forget(data);
+                }
+            }
+        }
+    }
+}
+
+
+/****************************************************************************/
+
+#[allow(non_camel_case_types)] // runtime type
+pub type rust_little_lock = *libc::c_void;
+
+struct LittleLock {
+    l: rust_little_lock,
+}
+
+impl Drop for LittleLock {
+    fn finalize(&self) {
+        unsafe {
+            rust_destroy_little_lock(self.l);
+        }
+    }
+}
+
+fn LittleLock() -> LittleLock {
+    unsafe {
+        LittleLock {
+            l: rust_create_little_lock()
+        }
+    }
+}
+
+pub impl LittleLock {
+    #[inline(always)]
+    unsafe fn lock<T>(&self, f: &fn() -> T) -> T {
+        do atomically {
+            rust_lock_little_lock(self.l);
+            do (|| {
+                f()
+            }).finally {
+                rust_unlock_little_lock(self.l);
+            }
+        }
+    }
+}
+
+struct ExData<T> {
+    lock: LittleLock,
+    failed: bool,
+    data: T,
+}
+
+/**
+ * An arc over mutable data that is protected by a lock. For library use only.
+ */
+pub struct Exclusive<T> {
+    x: UnsafeAtomicRcBox<ExData<T>>
+}
+
+pub fn exclusive<T:Owned>(user_data: T) -> Exclusive<T> {
+    let data = ExData {
+        lock: LittleLock(),
+        failed: false,
+        data: user_data
+    };
+    Exclusive {
+        x: UnsafeAtomicRcBox::new(data)
+    }
+}
+
+impl<T:Owned> Clone for Exclusive<T> {
+    // Duplicate an exclusive ARC, as std::arc::clone.
+    fn clone(&self) -> Exclusive<T> {
+        Exclusive { x: self.x.clone() }
+    }
+}
+
+pub impl<T:Owned> Exclusive<T> {
+    // Exactly like std::arc::mutex_arc,access(), but with the little_lock
+    // instead of a proper mutex. Same reason for being unsafe.
+    //
+    // Currently, scheduling operations (i.e., yielding, receiving on a pipe,
+    // accessing the provided condition variable) are prohibited while inside
+    // the exclusive. Supporting that is a work in progress.
+    #[inline(always)]
+    unsafe fn with<U>(&self, f: &fn(x: &mut T) -> U) -> U {
+        let rec = self.x.get();
+        do (*rec).lock.lock {
+            if (*rec).failed {
+                fail!("Poisoned exclusive - another task failed inside!");
+            }
+            (*rec).failed = true;
+            let result = f(&mut (*rec).data);
+            (*rec).failed = false;
+            result
+        }
+    }
+
+    #[inline(always)]
+    unsafe fn with_imm<U>(&self, f: &fn(x: &T) -> U) -> U {
+        do self.with |x| {
+            f(cast::transmute_immut(x))
+        }
+    }
+}
+
+fn compare_and_swap(address: &mut int, oldval: int, newval: int) -> bool {
+    unsafe {
+        let old = intrinsics::atomic_cxchg(address, oldval, newval);
+        old == oldval
+    }
+}
+
+extern {
+    fn rust_create_little_lock() -> rust_little_lock;
+    fn rust_destroy_little_lock(lock: rust_little_lock);
+    fn rust_lock_little_lock(lock: rust_little_lock);
+    fn rust_unlock_little_lock(lock: rust_little_lock);
+}
+
+#[cfg(test)]
+mod tests {
+    use comm;
+    use super::exclusive;
+    use task;
+    use uint;
+
+    #[test]
+    fn exclusive_arc() {
+        let mut futures = ~[];
+
+        let num_tasks = 10;
+        let count = 10;
+
+        let total = exclusive(~0);
+
+        for uint::range(0, num_tasks) |_i| {
+            let total = total.clone();
+            let (port, chan) = comm::stream();
+            futures.push(port);
+
+            do task::spawn || {
+                for uint::range(0, count) |_i| {
+                    do total.with |count| {
+                        **count += 1;
+                    }
+                }
+                chan.send(());
+            }
+        };
+
+        for futures.each |f| { f.recv() }
+
+        do total.with |total| {
+            assert!(**total == num_tasks * count)
+        };
+    }
+
+    #[test] #[should_fail] #[ignore(cfg(windows))]
+    fn exclusive_poison() {
+        // Tests that if one task fails inside of an exclusive, subsequent
+        // accesses will also fail.
+        let x = exclusive(1);
+        let x2 = x.clone();
+        do task::try || {
+            do x2.with |one| {
+                assert_eq!(*one, 2);
+            }
+        };
+        do x.with |one| {
+            assert_eq!(*one, 1);
+        }
+    }
+}
diff --git a/src/libstd/unstable/weak_task.rs b/src/libstd/unstable/weak_task.rs
new file mode 100644
index 00000000000..d5c5230cef8
--- /dev/null
+++ b/src/libstd/unstable/weak_task.rs
@@ -0,0 +1,211 @@
+// 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.
+
+/*!
+Weak tasks
+
+Weak tasks are a runtime feature for building global services that
+do not keep the runtime alive. Normally the runtime exits when all
+tasks exits, but if a task is weak then the runtime may exit while
+it is running, sending a notification to the task that the runtime
+is trying to shut down.
+*/
+
+use cell::Cell;
+use comm::{GenericSmartChan, stream};
+use comm::{Port, Chan, SharedChan, GenericChan, GenericPort};
+use hashmap::HashMap;
+use option::{Some, None};
+use unstable::at_exit::at_exit;
+use unstable::finally::Finally;
+use unstable::global::global_data_clone_create;
+use task::rt::{task_id, get_task_id};
+use task::task;
+
+#[cfg(test)] use task::spawn;
+
+type ShutdownMsg = ();
+
+// FIXME #4729: This could be a PortOne but I've experienced bugginess
+// with oneshot pipes and try_send
+pub unsafe fn weaken_task(f: &fn(Port<ShutdownMsg>)) {
+    let service = global_data_clone_create(global_data_key,
+                                           create_global_service);
+    let (shutdown_port, shutdown_chan) = stream::<ShutdownMsg>();
+    let shutdown_port = Cell(shutdown_port);
+    let task = get_task_id();
+    // Expect the weak task service to be alive
+    assert!(service.try_send(RegisterWeakTask(task, shutdown_chan)));
+    rust_dec_kernel_live_count();
+    do (|| {
+        f(shutdown_port.take())
+    }).finally || {
+        rust_inc_kernel_live_count();
+        // Service my have already exited
+        service.send(UnregisterWeakTask(task));
+    }
+}
+
+type WeakTaskService = SharedChan<ServiceMsg>;
+type TaskHandle = task_id;
+
+fn global_data_key(_v: WeakTaskService) { }
+
+enum ServiceMsg {
+    RegisterWeakTask(TaskHandle, Chan<ShutdownMsg>),
+    UnregisterWeakTask(TaskHandle),
+    Shutdown
+}
+
+fn create_global_service() -> ~WeakTaskService {
+
+    debug!("creating global weak task service");
+    let (port, chan) = stream::<ServiceMsg>();
+    let port = Cell(port);
+    let chan = SharedChan::new(chan);
+    let chan_clone = chan.clone();
+
+    let mut task = task();
+    task.unlinked();
+    do task.spawn {
+        debug!("running global weak task service");
+        let port = Cell(port.take());
+        do (|| {
+            let port = port.take();
+            // The weak task service is itself a weak task
+            debug!("weakening the weak service task");
+            unsafe { rust_dec_kernel_live_count(); }
+            run_weak_task_service(port);
+        }).finally {
+            debug!("unweakening the weak service task");
+            unsafe { rust_inc_kernel_live_count(); }
+        }
+    }
+
+    do at_exit {
+        debug!("shutting down weak task service");
+        chan.send(Shutdown);
+    }
+
+    return ~chan_clone;
+}
+
+fn run_weak_task_service(port: Port<ServiceMsg>) {
+
+    let mut shutdown_map = HashMap::new();
+
+    loop {
+        match port.recv() {
+            RegisterWeakTask(task, shutdown_chan) => {
+                let previously_unregistered =
+                    shutdown_map.insert(task, shutdown_chan);
+                assert!(previously_unregistered);
+            }
+            UnregisterWeakTask(task) => {
+                match shutdown_map.pop(&task) {
+                    Some(shutdown_chan) => {
+                        // Oneshot pipes must send, even though
+                        // nobody will receive this
+                        shutdown_chan.send(());
+                    }
+                    None => fail!()
+                }
+            }
+            Shutdown => break
+        }
+    }
+
+    do shutdown_map.consume |_, shutdown_chan| {
+        // Weak task may have already exited
+        shutdown_chan.send(());
+    }
+}
+
+extern {
+    unsafe fn rust_inc_kernel_live_count();
+    unsafe fn rust_dec_kernel_live_count();
+}
+
+#[test]
+fn test_simple() {
+    let (port, chan) = stream();
+    do spawn {
+        unsafe {
+            do weaken_task |_signal| {
+            }
+        }
+        chan.send(());
+    }
+    port.recv();
+}
+
+#[test]
+fn test_weak_weak() {
+    let (port, chan) = stream();
+    do spawn {
+        unsafe {
+            do weaken_task |_signal| {
+            }
+            do weaken_task |_signal| {
+            }
+        }
+        chan.send(());
+    }
+    port.recv();
+}
+
+#[test]
+fn test_wait_for_signal() {
+    do spawn {
+        unsafe {
+            do weaken_task |signal| {
+                signal.recv();
+            }
+        }
+    }
+}
+
+#[test]
+fn test_wait_for_signal_many() {
+    use uint;
+    for uint::range(0, 100) |_| {
+        do spawn {
+            unsafe {
+                do weaken_task |signal| {
+                    signal.recv();
+                }
+            }
+        }
+    }
+}
+
+#[test]
+fn test_select_stream_and_oneshot() {
+    use comm::select2i;
+    use either::{Left, Right};
+
+    let (port, chan) = stream();
+    let port = Cell(port);
+    let (waitport, waitchan) = stream();
+    do spawn {
+        unsafe {
+            do weaken_task |mut signal| {
+                let mut port = port.take();
+                match select2i(&mut port, &mut signal) {
+                    Left(*) => (),
+                    Right(*) => fail!()
+                }
+            }
+        }
+        waitchan.send(());
+    }
+    chan.send(());
+    waitport.recv();
+}
diff --git a/src/libstd/util.rs b/src/libstd/util.rs
new file mode 100644
index 00000000000..e2b91594d12
--- /dev/null
+++ b/src/libstd/util.rs
@@ -0,0 +1,190 @@
+// 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.
+
+/*!
+
+Miscellaneous helpers for common patterns.
+
+*/
+
+use prelude::*;
+use unstable::intrinsics;
+
+/// The identity function.
+#[inline(always)]
+pub fn id<T>(x: T) -> T { x }
+
+/// Ignores a value.
+#[inline(always)]
+pub fn ignore<T>(_x: T) { }
+
+/// Sets `*ptr` to `new_value`, invokes `op()`, and then restores the
+/// original value of `*ptr`.
+///
+/// NB: This function accepts `@mut T` and not `&mut T` to avoid
+/// an obvious borrowck hazard. Typically passing in `&mut T` will
+/// cause borrow check errors because it freezes whatever location
+/// that `&mut T` is stored in (either statically or dynamically).
+#[inline(always)]
+pub fn with<T,R>(
+    ptr: @mut T,
+    value: T,
+    op: &fn() -> R) -> R
+{
+    let prev = replace(ptr, value);
+    let result = op();
+    *ptr = prev;
+    return result;
+}
+
+/**
+ * Swap the values at two mutable locations of the same type, without
+ * deinitialising or copying either one.
+ */
+#[inline(always)]
+pub fn swap<T>(x: &mut T, y: &mut T) {
+    unsafe {
+        swap_ptr(ptr::to_mut_unsafe_ptr(x), ptr::to_mut_unsafe_ptr(y));
+    }
+}
+
+/**
+ * Swap the values at two mutable locations of the same type, without
+ * deinitialising or copying either one.
+ */
+#[inline]
+pub unsafe fn swap_ptr<T>(x: *mut T, y: *mut T) {
+    if x == y { return }
+
+    // Give ourselves some scratch space to work with
+    let mut tmp: T = intrinsics::uninit();
+    let t = ptr::to_mut_unsafe_ptr(&mut tmp);
+
+    // Perform the swap
+    ptr::copy_memory(t, x, 1);
+    ptr::copy_memory(x, y, 1);
+    ptr::copy_memory(y, t, 1);
+
+    // y and t now point to the same thing, but we need to completely forget t
+    // because it's no longer relevant.
+    cast::forget(tmp);
+}
+
+/**
+ * Replace the value at a mutable location with a new one, returning the old
+ * value, without deinitialising or copying either one.
+ */
+#[inline(always)]
+pub fn replace<T>(dest: &mut T, mut src: T) -> T {
+    swap(dest, &mut src);
+    src
+}
+
+/**
+ * Replace the value at a mutable location with a new one, returning the old
+ * value, without deinitialising or copying either one.
+ */
+#[inline(always)]
+pub unsafe fn replace_ptr<T>(dest: *mut T, mut src: T) -> T {
+    swap_ptr(dest, ptr::to_mut_unsafe_ptr(&mut src));
+    src
+}
+
+/// A non-copyable dummy type.
+pub struct NonCopyable {
+    i: (),
+}
+
+impl Drop for NonCopyable {
+    fn finalize(&self) { }
+}
+
+pub fn NonCopyable() -> NonCopyable { NonCopyable { i: () } }
+
+
+/// A type with no inhabitants
+pub enum Void { }
+
+pub impl Void {
+    /// A utility function for ignoring this uninhabited type
+    fn uninhabited(self) -> ! {
+        match self {
+            // Nothing to match on
+        }
+    }
+}
+
+
+/**
+A utility function for indicating unreachable code. It will fail if
+executed. This is occasionally useful to put after loops that never
+terminate normally, but instead directly return from a function.
+
+# Example
+
+~~~
+fn choose_weighted_item(v: &[Item]) -> Item {
+    assert!(!v.is_empty());
+    let mut so_far = 0u;
+    for v.each |item| {
+        so_far += item.weight;
+        if so_far > 100 {
+            return item;
+        }
+    }
+    // The above loop always returns, so we must hint to the
+    // type checker that it isn't possible to get down here
+    util::unreachable();
+}
+~~~
+
+*/
+pub fn unreachable() -> ! {
+    fail!("internal error: entered unreachable code");
+}
+
+#[cfg(test)]
+mod tests {
+    use option::{None, Some};
+    use util::{Void, NonCopyable, id, replace, swap};
+    use either::{Either, Left, Right};
+
+    #[test]
+    pub fn identity_crisis() {
+        // Writing a test for the identity function. How did it come to this?
+        let x = ~[(5, false)];
+        //FIXME #3387 assert!(x.eq(id(copy x)));
+        let y = copy x;
+        assert!(x.eq(&id(y)));
+    }
+    #[test]
+    pub fn test_swap() {
+        let mut x = 31337;
+        let mut y = 42;
+        swap(&mut x, &mut y);
+        assert_eq!(x, 42);
+        assert_eq!(y, 31337);
+    }
+    #[test]
+    pub fn test_replace() {
+        let mut x = Some(NonCopyable());
+        let y = replace(&mut x, None);
+        assert!(x.is_none());
+        assert!(y.is_some());
+    }
+    #[test]
+    pub fn test_uninhabited() {
+        let could_only_be_coin : Either <Void, ()> = Right (());
+        match could_only_be_coin {
+            Right (coin) => coin,
+            Left (is_void) => is_void.uninhabited ()
+        }
+    }
+}
diff --git a/src/libstd/uv.rs b/src/libstd/uv.rs
deleted file mode 100644
index e055b407057..00000000000
--- a/src/libstd/uv.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
- * Rust bindings to libuv
- *
- * This is the base-module for various levels of bindings to
- * the libuv library.
- *
- * These modules are seeing heavy work, currently, and the final
- * API layout should not be inferred from its current form.
- *
- * This base module currently contains a historical, rust-based
- * implementation of a few libuv operations that hews closely to
- * the patterns of the libuv C-API. It was used, mostly, to explore
- * some implementation details and will most likely be deprecated
- * in the near future.
- *
- * The `ll` module contains low-level mappings for working directly
- * with the libuv C-API.
- *
- * The `hl` module contains a set of tools library developers can
- * use for interacting with an active libuv loop. This modules's
- * API is meant to be used to write high-level,
- * rust-idiomatic abstractions for utilizes libuv's asynchronous IO
- * facilities.
- */
-
-pub use ll = super::uv_ll;
-pub use iotask = uv_iotask;
-pub use global_loop = uv_global_loop;
diff --git a/src/libstd/uv_global_loop.rs b/src/libstd/uv_global_loop.rs
deleted file mode 100644
index d1471ba1e77..00000000000
--- a/src/libstd/uv_global_loop.rs
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! A process-wide libuv event loop for library use.
-
-use iotask = uv_iotask;
-use uv_iotask::{IoTask, spawn_iotask};
-
-use core::comm::Chan;
-use core::option::{Some, None};
-use core::task::task;
-use core::unstable::global::{global_data_clone_create, global_data_clone};
-use core::unstable::weak_task::weaken_task;
-
-/**
- * Race-free helper to get access to a global task where a libuv
- * loop is running.
- *
- * Use `uv::hl::interact` to do operations against the global
- * loop that this function returns.
- *
- * # Return
- *
- * * A `hl::high_level_loop` that encapsulates communication with the global
- * loop.
- */
-pub fn get() -> IoTask {
-    return get_monitor_task_gl();
-}
-
-#[doc(hidden)]
-fn get_monitor_task_gl() -> IoTask {
-
-    type MonChan = Chan<IoTask>;
-
-    struct GlobalIoTask(IoTask);
-
-    impl Clone for GlobalIoTask {
-        fn clone(&self) -> GlobalIoTask {
-            GlobalIoTask((**self).clone())
-        }
-    }
-
-    fn key(_: GlobalIoTask) { }
-
-    match unsafe { global_data_clone(key) } {
-        Some(GlobalIoTask(iotask)) => iotask,
-        None => {
-            let iotask: IoTask = spawn_loop();
-            let mut installed = false;
-            let final_iotask = unsafe {
-                do global_data_clone_create(key) {
-                    installed = true;
-                    ~GlobalIoTask(iotask.clone())
-                }
-            };
-            if installed {
-                let mut task = task();
-                task.unlinked();
-                do task.spawn {
-                    unsafe {
-                        debug!("global monitor task starting");
-                        // As a weak task the runtime will notify us
-                        // when to exit
-                        do weaken_task |weak_exit_po| {
-                            debug!("global monitor task is weak");
-                            weak_exit_po.recv();
-                            iotask::exit(&iotask);
-                            debug!("global monitor task is unweak");
-                        };
-                        debug!("global monitor task exiting");
-                    }
-                }
-            } else {
-                iotask::exit(&iotask);
-            }
-
-            match final_iotask {
-                GlobalIoTask(iotask) => iotask
-            }
-        }
-    }
-}
-
-fn spawn_loop() -> IoTask {
-    let mut builder = task();
-
-    do builder.add_wrapper |task_body| {
-        let result: ~fn() = || {
-            // The I/O loop task also needs to be weak so it doesn't keep
-            // the runtime alive
-            unsafe {
-                do weaken_task |_| {
-                    debug!("global libuv task is now weak");
-                    task_body();
-
-                    // We don't wait for the exit message on weak_exit_po
-                    // because the monitor task will tell the uv loop when to
-                    // exit
-
-                    debug!("global libuv task is leaving weakened state");
-                }
-            }
-        };
-        result
-    };
-
-    builder.unlinked();
-    spawn_iotask(builder)
-}
-
-#[cfg(test)]
-mod test {
-
-    use get_gl = uv_global_loop::get;
-    use uv::iotask;
-    use uv::ll;
-    use uv_iotask::IoTask;
-
-    use core::old_iter;
-    use core::libc;
-    use core::ptr;
-    use core::task;
-    use core::cast::transmute;
-    use core::libc::c_void;
-    use core::comm::{stream, SharedChan, Chan};
-
-    extern fn simple_timer_close_cb(timer_ptr: *ll::uv_timer_t) {
-        unsafe {
-            let exit_ch_ptr = ll::get_data_for_uv_handle(
-                timer_ptr as *libc::c_void);
-            let exit_ch = transmute::<*c_void, ~Chan<bool>>(exit_ch_ptr);
-            exit_ch.send(true);
-            debug!("EXIT_CH_PTR simple_timer_close_cb exit_ch_ptr: %?",
-                     exit_ch_ptr);
-        }
-    }
-    extern fn simple_timer_cb(timer_ptr: *ll::uv_timer_t,
-                             _status: libc::c_int) {
-        unsafe {
-            debug!(~"in simple timer cb");
-            ll::timer_stop(timer_ptr);
-            let hl_loop = &get_gl();
-            do iotask::interact(hl_loop) |_loop_ptr| {
-                debug!(~"closing timer");
-                unsafe {
-                    ll::close(timer_ptr, simple_timer_close_cb);
-                }
-                debug!(~"about to deref exit_ch_ptr");
-                debug!(~"after msg sent on deref'd exit_ch");
-            };
-            debug!(~"exiting simple timer cb");
-        }
-    }
-
-    fn impl_uv_hl_simple_timer(iotask: &IoTask) {
-        unsafe {
-            let (exit_po, exit_ch) = stream::<bool>();
-            let exit_ch_ptr: *libc::c_void = transmute(~exit_ch);
-            debug!("EXIT_CH_PTR newly created exit_ch_ptr: %?",
-                            exit_ch_ptr);
-            let timer_handle = ll::timer_t();
-            let timer_ptr: *ll::uv_timer_t = &timer_handle;
-            do iotask::interact(iotask) |loop_ptr| {
-                unsafe {
-                    debug!(~"user code inside interact loop!!!");
-                    let init_status = ll::timer_init(loop_ptr, timer_ptr);
-                    if(init_status == 0i32) {
-                        ll::set_data_for_uv_handle(
-                            timer_ptr as *libc::c_void,
-                            exit_ch_ptr);
-                        let start_status = ll::timer_start(timer_ptr,
-                                                           simple_timer_cb,
-                                                           1u, 0u);
-                        if(start_status != 0i32) {
-                            fail!("failure on ll::timer_start()");
-                        }
-                    }
-                    else {
-                        fail!("failure on ll::timer_init()");
-                    }
-                }
-            };
-            exit_po.recv();
-            debug!(
-                ~"global_loop timer test: msg recv on exit_po, done..");
-        }
-    }
-
-    #[test]
-    fn test_gl_uv_global_loop_high_level_global_timer() {
-        let hl_loop = &get_gl();
-        let (exit_po, exit_ch) = stream::<()>();
-        task::spawn_sched(task::ManualThreads(1u), || {
-            let hl_loop = &get_gl();
-            impl_uv_hl_simple_timer(hl_loop);
-            exit_ch.send(());
-        });
-        impl_uv_hl_simple_timer(hl_loop);
-        exit_po.recv();
-    }
-
-    // keeping this test ignored until some kind of stress-test-harness
-    // is set up for the build bots
-    #[test]
-    #[ignore]
-    fn test_stress_gl_uv_global_loop_high_level_global_timer() {
-        let (exit_po, exit_ch) = stream::<()>();
-        let exit_ch = SharedChan::new(exit_ch);
-        let cycles = 5000u;
-        for cycles.times {
-            let exit_ch_clone = exit_ch.clone();
-            task::spawn_sched(task::ManualThreads(1u), || {
-                let hl_loop = &get_gl();
-                impl_uv_hl_simple_timer(hl_loop);
-                exit_ch_clone.send(());
-            });
-        };
-        for cycles.times {
-            exit_po.recv();
-        };
-        debug!(~"test_stress_gl_uv_global_loop_high_level_global_timer"+
-            ~" exiting successfully!");
-    }
-}
diff --git a/src/libstd/uv_iotask.rs b/src/libstd/uv_iotask.rs
deleted file mode 100644
index 371eb338de3..00000000000
--- a/src/libstd/uv_iotask.rs
+++ /dev/null
@@ -1,305 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
- * A task-based interface to the uv loop
- *
- * The I/O task runs in its own single-threaded scheduler.  By using the
- * `interact` function you can execute code in a uv callback.
- */
-
-use ll = uv_ll;
-
-use core::comm::{stream, Port, Chan, SharedChan};
-use core::libc::c_void;
-use core::libc;
-
-/// Used to abstract-away direct interaction with a libuv loop.
-pub struct IoTask {
-    async_handle: *ll::uv_async_t,
-    op_chan: SharedChan<IoTaskMsg>
-}
-
-impl Clone for IoTask {
-    fn clone(&self) -> IoTask {
-        IoTask{
-            async_handle: self.async_handle,
-            op_chan: self.op_chan.clone()
-        }
-    }
-}
-
-pub fn spawn_iotask(mut task: task::TaskBuilder) -> IoTask {
-    let (iotask_port, iotask_chan) = stream();
-
-    task.sched_mode(task::SingleThreaded);
-    do task.spawn {
-        debug!("entering libuv task");
-        run_loop(&iotask_chan);
-        debug!("libuv task exiting");
-    };
-
-    iotask_port.recv()
-}
-
-
-/**
- * Provide a callback to be processed by `iotask`
- *
- * The primary way to do operations again a running `iotask` that
- * doesn't involve creating a uv handle via `safe_handle`
- *
- * # Warning
- *
- * This function is the only safe way to interact with _any_ `iotask`.
- * Using functions in the `uv::ll` module outside of the `cb` passed into
- * this function is _very dangerous_.
- *
- * # Arguments
- *
- * * iotask - a uv I/O task that you want to do operations against
- * * cb - a function callback to be processed on the running loop's
- * thread. The only parameter passed in is an opaque pointer representing the
- * running `uv_loop_t*`. In the context of this callback, it is safe to use
- * this pointer to do various uv_* API calls contained within the `uv::ll`
- * module. It is not safe to send the `loop_ptr` param to this callback out
- * via ports/chans.
- */
-pub fn interact(iotask: &IoTask, cb: ~fn(*c_void)) {
-    send_msg(iotask, Interaction(cb));
-}
-
-/**
- * Shut down the I/O task
- *
- * Is used to signal to the loop that it should close the internally-held
- * async handle and do a sanity check to make sure that all other handles are
- * closed, causing a failure otherwise.
- */
-pub fn exit(iotask: &IoTask) {
-    send_msg(iotask, TeardownLoop);
-}
-
-
-// INTERNAL API
-
-enum IoTaskMsg {
-    Interaction(~fn(*libc::c_void)),
-    TeardownLoop
-}
-
-/// Run the loop and begin handling messages
-fn run_loop(iotask_ch: &Chan<IoTask>) {
-
-    unsafe {
-        debug!("creating loop");
-        let loop_ptr = ll::loop_new();
-
-        // set up the special async handle we'll use to allow multi-task
-        // communication with this loop
-        let async = ll::async_t();
-        let async_handle: *ll::uv_async_t = &async;
-
-        // associate the async handle with the loop
-        ll::async_init(loop_ptr, async_handle, wake_up_cb);
-
-        let (msg_po, msg_ch) = stream::<IoTaskMsg>();
-
-        // initialize our loop data and store it in the loop
-        let data: IoTaskLoopData = IoTaskLoopData {
-            async_handle: async_handle,
-            msg_po: msg_po
-        };
-        ll::set_data_for_uv_handle(async_handle, &data);
-
-        // Send out a handle through which folks can talk to us
-        // while we dwell in the I/O loop
-        let iotask = IoTask {
-            async_handle: async_handle,
-            op_chan: SharedChan::new(msg_ch)
-        };
-        iotask_ch.send(iotask);
-
-        debug!("about to run uv loop");
-        // enter the loop... this blocks until the loop is done..
-        ll::run(loop_ptr);
-        debug!("uv loop ended");
-        ll::loop_delete(loop_ptr);
-    }
-}
-
-// data that lives for the lifetime of the high-evel oo
-struct IoTaskLoopData {
-    async_handle: *ll::uv_async_t,
-    msg_po: Port<IoTaskMsg>,
-}
-
-fn send_msg(iotask: &IoTask,
-            msg: IoTaskMsg) {
-    iotask.op_chan.send(msg);
-    unsafe {
-        ll::async_send(iotask.async_handle);
-    }
-}
-
-/// Dispatch all pending messages
-extern fn wake_up_cb(async_handle: *ll::uv_async_t,
-                    status: int) {
-
-    debug!("wake_up_cb extern.. handle: %? status: %?",
-                     async_handle, status);
-
-    unsafe {
-        let loop_ptr = ll::get_loop_for_uv_handle(async_handle);
-        let data =
-            ll::get_data_for_uv_handle(async_handle) as *IoTaskLoopData;
-        let msg_po = &(*data).msg_po;
-
-        while msg_po.peek() {
-            match msg_po.recv() {
-                Interaction(ref cb) => (*cb)(loop_ptr),
-                TeardownLoop => begin_teardown(data)
-            }
-        }
-    }
-}
-
-fn begin_teardown(data: *IoTaskLoopData) {
-    unsafe {
-        debug!("iotask begin_teardown() called, close async_handle");
-        let async_handle = (*data).async_handle;
-        ll::close(async_handle as *c_void, tear_down_close_cb);
-    }
-}
-extern fn tear_down_walk_cb(handle: *libc::c_void, arg: *libc::c_void) {
-    debug!("IN TEARDOWN WALK CB");
-    // pretty much, if we still have an active handle and it is *not*
-    // the async handle that facilities global loop communication, we
-    // want to barf out and fail
-    assert_eq!(handle, arg);
-}
-
-extern fn tear_down_close_cb(handle: *ll::uv_async_t) {
-    unsafe {
-        let loop_ptr = ll::get_loop_for_uv_handle(handle);
-        debug!("in tear_down_close_cb");
-        ll::walk(loop_ptr, tear_down_walk_cb, handle as *libc::c_void);
-    }
-}
-
-#[cfg(test)]
-extern fn async_close_cb(handle: *ll::uv_async_t) {
-    unsafe {
-        debug!("async_close_cb handle %?", handle);
-        let exit_ch = &(*(ll::get_data_for_uv_handle(handle)
-                        as *AhData)).exit_ch;
-        let exit_ch = exit_ch.clone();
-        exit_ch.send(());
-    }
-}
-
-#[cfg(test)]
-extern fn async_handle_cb(handle: *ll::uv_async_t, status: libc::c_int) {
-    unsafe {
-        debug!("async_handle_cb handle %? status %?",handle,status);
-        ll::close(handle, async_close_cb);
-    }
-}
-
-#[cfg(test)]
-struct AhData {
-    iotask: IoTask,
-    exit_ch: SharedChan<()>
-}
-
-#[cfg(test)]
-fn impl_uv_iotask_async(iotask: &IoTask) {
-    let async_handle = ll::async_t();
-    let ah_ptr: *ll::uv_async_t = &async_handle;
-    let (exit_po, exit_ch) = stream::<()>();
-    let ah_data = AhData {
-        iotask: iotask.clone(),
-        exit_ch: SharedChan::new(exit_ch)
-    };
-    let ah_data_ptr: *AhData = ptr::to_unsafe_ptr(&ah_data);
-    debug!("about to interact");
-    do interact(iotask) |loop_ptr| {
-        unsafe {
-            debug!("interacting");
-            ll::async_init(loop_ptr, ah_ptr, async_handle_cb);
-            ll::set_data_for_uv_handle(
-                ah_ptr, ah_data_ptr as *libc::c_void);
-            ll::async_send(ah_ptr);
-        }
-    };
-    debug!("waiting for async close");
-    exit_po.recv();
-}
-
-// this fn documents the bear minimum necessary to roll your own
-// high_level_loop
-#[cfg(test)]
-fn spawn_test_loop(exit_ch: ~Chan<()>) -> IoTask {
-    let (iotask_port, iotask_ch) = stream::<IoTask>();
-    do task::spawn_sched(task::ManualThreads(1u)) {
-        debug!("about to run a test loop");
-        run_loop(&iotask_ch);
-        exit_ch.send(());
-    };
-    return iotask_port.recv();
-}
-
-#[cfg(test)]
-extern fn lifetime_handle_close(handle: *libc::c_void) {
-    debug!("lifetime_handle_close ptr %?", handle);
-}
-
-#[cfg(test)]
-extern fn lifetime_async_callback(handle: *libc::c_void,
-                                 status: libc::c_int) {
-    debug!("lifetime_handle_close ptr %? status %?",
-                    handle, status);
-}
-
-#[test]
-fn test_uv_iotask_async() {
-    let (exit_po, exit_ch) = stream::<()>();
-    let iotask = &spawn_test_loop(~exit_ch);
-
-    debug!("spawned iotask");
-
-    // using this handle to manage the lifetime of the
-    // high_level_loop, as it will exit the first time one of
-    // the impl_uv_hl_async() is cleaned up with no one ref'd
-    // handles on the loop (Which can happen under
-    // race-condition type situations.. this ensures that the
-    // loop lives until, at least, all of the
-    // impl_uv_hl_async() runs have been called, at least.
-    let (work_exit_po, work_exit_ch) = stream::<()>();
-    let work_exit_ch = SharedChan::new(work_exit_ch);
-    for 7u.times {
-        let iotask_clone = iotask.clone();
-        let work_exit_ch_clone = work_exit_ch.clone();
-        do task::spawn_sched(task::ManualThreads(1u)) {
-            debug!("async");
-            impl_uv_iotask_async(&iotask_clone);
-            debug!("done async");
-            work_exit_ch_clone.send(());
-        };
-    };
-    for 7u.times {
-        debug!("waiting");
-        work_exit_po.recv();
-    };
-    debug!(~"sending teardown_loop msg..");
-    exit(iotask);
-    exit_po.recv();
-    debug!(~"after recv on exit_po.. exiting..");
-}
diff --git a/src/libstd/uv_ll.rs b/src/libstd/uv_ll.rs
deleted file mode 100644
index bc7703ec30a..00000000000
--- a/src/libstd/uv_ll.rs
+++ /dev/null
@@ -1,1910 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-/*!
- * Low-level bindings to the libuv library.
- *
- * This module contains a set of direct, 'bare-metal' wrappers around
- * the libuv C-API.
- *
- * Also contained herein are a set of rust records that map, in
- * approximate memory-size, to the libuv data structures. The record
- * implementations are adjusted, per-platform, to match their respective
- * representations.
- *
- * There are also a collection of helper functions to ease interacting
- * with the low-level API (such as a function to return the latest
- * libuv error as a rust-formatted string).
- *
- * As new functionality, existant in uv.h, is added to the rust stdlib,
- * the mappings should be added in this module.
- *
- * This module's implementation will hopefully be, eventually, replaced
- * with per-platform, generated source files from rust-bindgen.
- */
-
-#[allow(non_camel_case_types)]; // C types
-
-use core::libc::size_t;
-use core::libc::c_void;
-use core::ptr::to_unsafe_ptr;
-
-pub type uv_handle_t = c_void;
-pub type uv_loop_t = c_void;
-pub type uv_idle_t = c_void;
-pub type uv_idle_cb = *u8;
-
-// libuv struct mappings
-pub struct uv_ip4_addr {
-    ip: ~[u8],
-    port: int,
-}
-pub type uv_ip6_addr = uv_ip4_addr;
-
-pub enum uv_handle_type {
-    UNKNOWN_HANDLE = 0,
-    UV_TCP,
-    UV_UDP,
-    UV_NAMED_PIPE,
-    UV_TTY,
-    UV_FILE,
-    UV_TIMER,
-    UV_PREPARE,
-    UV_CHECK,
-    UV_IDLE,
-    UV_ASYNC,
-    UV_ARES_TASK,
-    UV_ARES_EVENT,
-    UV_PROCESS,
-    UV_FS_EVENT
-}
-
-pub type handle_type = libc::c_uint;
-
-pub struct uv_handle_fields {
-   loop_handle: *libc::c_void,
-   type_: handle_type,
-   close_cb: *u8,
-   data: *libc::c_void,
-}
-
-// unix size: 8
-pub struct uv_err_t {
-    code: libc::c_int,
-    sys_errno_: libc::c_int
-}
-
-// don't create one of these directly. instead,
-// count on it appearing in libuv callbacks or embedded
-// in other types as a pointer to be used in other
-// operations (so mostly treat it as opaque, once you
-// have it in this form..)
-pub struct uv_stream_t {
-    fields: uv_handle_fields,
-}
-
-// 64bit unix size: 216
-#[cfg(target_os="macos")]
-pub struct uv_tcp_t {
-    fields: uv_handle_fields,
-    a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-    a04: *u8, a05: *u8, a06: *u8, a07: *u8,
-    a08: *u8, a09: *u8, a10: *u8, a11: *u8,
-    a12: *u8, a13: *u8, a14: *u8, a15: *u8,
-    a16: *u8, a17: *u8, a18: *u8, a19: *u8,
-    a20: *u8, a21: *u8, a22: *u8,
-    a23: uv_tcp_t_osx_riders
-}
-#[cfg(target_arch="x86_64")]
-pub struct uv_tcp_t_osx_riders {
-    a23: *u8,
-}
-#[cfg(target_arch="x86")]
-#[cfg(target_arch="arm")]
-pub struct uv_tcp_t_osx_riders {
-    a23: *u8,
-    a24: *u8, a25: *u8,
-}
-#[cfg(target_os="linux")]
-#[cfg(target_os="freebsd")]
-#[cfg(target_os="android")]
-pub struct uv_tcp_t {
-    fields: uv_handle_fields,
-    a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-    a04: *u8, a05: *u8, a06: *u8, a07: *u8,
-    a08: *u8, a09: *u8, a10: *u8, a11: *u8,
-    a12: *u8, a13: *u8, a14: *u8, a15: *u8,
-    a16: *u8, a17: *u8, a18: *u8, a19: *u8,
-    a20: *u8, a21: *u8,
-    a22: uv_tcp_t_32bit_unix_riders,
-}
-// 32bit unix size: 328 (164)
-#[cfg(target_arch="x86_64")]
-pub struct uv_tcp_t_32bit_unix_riders {
-    a29: *u8,
-}
-#[cfg(target_arch="x86")]
-#[cfg(target_arch="arm")]
-#[cfg(target_arch="mips")]
-pub struct uv_tcp_t_32bit_unix_riders {
-    a29: *u8, a30: *u8, a31: *u8,
-}
-
-// 32bit win32 size: 240 (120)
-#[cfg(windows)]
-pub struct uv_tcp_t {
-    fields: uv_handle_fields,
-    a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-    a04: *u8, a05: *u8, a06: *u8, a07: *u8,
-    a08: *u8, a09: *u8, a10: *u8, a11: *u8,
-    a12: *u8, a13: *u8, a14: *u8, a15: *u8,
-    a16: *u8, a17: *u8, a18: *u8, a19: *u8,
-    a20: *u8, a21: *u8, a22: *u8, a23: *u8,
-    a24: *u8, a25: *u8,
-}
-
-// unix size: 64
-#[cfg(unix)]
-pub struct uv_connect_t {
-    a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-    a04: *u8, a05: *u8, a06: *u8, a07: *u8
-}
-// win32 size: 88 (44)
-#[cfg(windows)]
-pub struct uv_connect_t {
-    a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-    a04: *u8, a05: *u8, a06: *u8, a07: *u8,
-    a08: *u8, a09: *u8, a10: *u8,
-}
-
-// unix size: 16
-pub struct uv_buf_t {
-    base: *u8,
-    len: libc::size_t,
-}
-// no gen stub method.. should create
-// it via uv::direct::buf_init()
-
-// unix size: 160
-#[cfg(unix)]
-pub struct uv_write_t {
-    fields: uv_handle_fields,
-    a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-    a04: *u8, a05: *u8, a06: *u8, a07: *u8,
-    a08: *u8, a09: *u8, a10: *u8, a11: *u8,
-    a12: *u8,
-    a14: uv_write_t_32bit_unix_riders,
-}
-#[cfg(target_arch="x86_64")]
-pub struct uv_write_t_32bit_unix_riders {
-    a13: *u8, a14: *u8, a15: *u8
-}
-#[cfg(target_arch="x86")]
-#[cfg(target_arch="arm")]
-#[cfg(target_arch="mips")]
-pub struct uv_write_t_32bit_unix_riders {
-    a13: *u8, a14: *u8, a15: *u8,
-    a16: *u8,
-}
-// win32 size: 136 (68)
-#[cfg(windows)]
-pub struct uv_write_t {
-    fields: uv_handle_fields,
-    a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-    a04: *u8, a05: *u8, a06: *u8, a07: *u8,
-    a08: *u8, a09: *u8, a10: *u8, a11: *u8,
-    a12: *u8,
-}
-// 64bit unix size: 96
-// 32bit unix size: 152 (76)
-#[cfg(unix)]
-pub struct uv_async_t {
-    fields: uv_handle_fields,
-    a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-    a04: *u8, a05: *u8, a06: *u8,
-    a07: uv_async_t_32bit_unix_riders,
-}
-#[cfg(target_arch="x86_64")]
-pub struct uv_async_t_32bit_unix_riders {
-    a10: *u8,
-}
-#[cfg(target_arch="x86")]
-#[cfg(target_arch="arm")]
-#[cfg(target_arch="mips")]
-pub struct uv_async_t_32bit_unix_riders {
-    a10: *u8,
-}
-// win32 size 132 (68)
-#[cfg(windows)]
-pub struct uv_async_t {
-    fields: uv_handle_fields,
-    a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-    a04: *u8, a05: *u8, a06: *u8, a07: *u8,
-    a08: *u8, a09: *u8, a10: *u8, a11: *u8,
-    a12: *u8,
-}
-
-// 64bit unix size: 120
-// 32bit unix size: 84
-#[cfg(unix)]
-pub struct uv_timer_t {
-    fields: uv_handle_fields,
-    a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-    a04: *u8, a05: *u8, a06: *u8, a07: *u8,
-    a08: *u8, a09: *u8,
-    a11: uv_timer_t_32bit_unix_riders,
-}
-#[cfg(target_arch="x86_64")]
-pub struct uv_timer_t_32bit_unix_riders {
-    a10: *u8,
-}
-#[cfg(target_arch="x86")]
-#[cfg(target_arch="arm")]
-#[cfg(target_arch="mips")]
-pub struct uv_timer_t_32bit_unix_riders {
-    a10: *u8, a11: *u8, a12: *u8
-}
-// win32 size: 64
-#[cfg(windows)]
-pub struct uv_timer_t {
-    fields: uv_handle_fields,
-    a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-    a04: *u8, a05: *u8, a06: *u8, a07: *u8,
-    a08: *u8, a09: *u8, a10: *u8, a11: *u8,
-}
-
-// unix size: 16
-pub struct sockaddr_in {
-    sin_family: u16,
-    sin_port: u16,
-    sin_addr: u32, // in_addr: this is an opaque, per-platform struct
-    sin_zero: (u8, u8, u8, u8, u8, u8, u8, u8),
-}
-
-// unix size: 28 .. FIXME #1645
-// stuck with 32 because of rust padding structs?
-#[cfg(target_arch="x86_64")]
-pub struct sockaddr_in6 {
-    a0: *u8, a1: *u8,
-    a2: *u8, a3: *u8,
-}
-#[cfg(target_arch="x86")]
-#[cfg(target_arch="arm")]
-#[cfg(target_arch="mips")]
-pub struct sockaddr_in6 {
-    a0: *u8, a1: *u8,
-    a2: *u8, a3: *u8,
-    a4: *u8, a5: *u8,
-    a6: *u8, a7: *u8,
-}
-
-// unix size: 28 .. FIXME #1645
-// stuck with 32 because of rust padding structs?
-pub type addr_in = addr_in_impl::addr_in;
-#[cfg(unix)]
-pub mod addr_in_impl {
-    #[cfg(target_arch="x86_64")]
-    pub struct addr_in {
-        a0: *u8, a1: *u8,
-        a2: *u8, a3: *u8,
-    }
-    #[cfg(target_arch="x86")]
-    #[cfg(target_arch="arm")]
-    #[cfg(target_arch="mips")]
-    pub struct addr_in {
-        a0: *u8, a1: *u8,
-        a2: *u8, a3: *u8,
-        a4: *u8, a5: *u8,
-        a6: *u8, a7: *u8,
-    }
-}
-#[cfg(windows)]
-pub mod addr_in_impl {
-    pub struct addr_in {
-        a0: *u8, a1: *u8,
-        a2: *u8, a3: *u8,
-    }
-}
-
-// unix size: 48, 32bit: 32
-pub type addrinfo = addrinfo_impl::addrinfo;
-#[cfg(target_os="linux")]
-#[cfg(target_os="android")]
-pub mod addrinfo_impl {
-    #[cfg(target_arch="x86_64")]
-    pub struct addrinfo {
-        a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-        a04: *u8, a05: *u8,
-    }
-    #[cfg(target_arch="x86")]
-    #[cfg(target_arch="arm")]
-    #[cfg(target_arch="mips")]
-    pub struct addrinfo {
-        a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-        a04: *u8, a05: *u8, a06: *u8, a07: *u8,
-    }
-}
-#[cfg(target_os="macos")]
-#[cfg(target_os="freebsd")]
-pub mod addrinfo_impl {
-    pub struct addrinfo {
-        a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-        a04: *u8, a05: *u8,
-    }
-}
-#[cfg(windows)]
-pub mod addrinfo_impl {
-    pub struct addrinfo {
-        a00: *u8, a01: *u8, a02: *u8, a03: *u8,
-        a04: *u8, a05: *u8,
-    }
-}
-
-// unix size: 72
-pub struct uv_getaddrinfo_t {
-    a00: *u8, a01: *u8, a02: *u8, a03: *u8, a04: *u8, a05: *u8,
-    a06: *u8, a07: *u8, a08: *u8, a09: *u8,
-    a10: *u8, a11: *u8, a12: *u8, a13: *u8, a14: *u8, a15: *u8
-}
-
-pub mod uv_ll_struct_stubgen {
-
-    use core::ptr;
-
-    use super::{
-        uv_async_t,
-        uv_connect_t,
-        uv_getaddrinfo_t,
-        uv_handle_fields,
-        uv_tcp_t,
-        uv_timer_t,
-        uv_write_t,
-    };
-
-    #[cfg(target_os = "linux")]
-    #[cfg(target_os = "android")]
-    #[cfg(target_os = "macos")]
-    #[cfg(target_os = "freebsd")]
-    use super::{
-        uv_async_t_32bit_unix_riders,
-        uv_timer_t_32bit_unix_riders,
-        uv_write_t_32bit_unix_riders,
-    };
-
-    #[cfg(target_os = "linux")]
-    #[cfg(target_os = "android")]
-    #[cfg(target_os = "freebsd")]
-    use super::uv_tcp_t_32bit_unix_riders;
-
-    pub fn gen_stub_uv_tcp_t() -> uv_tcp_t {
-        return gen_stub_os();
-        #[cfg(target_os = "linux")]
-        #[cfg(target_os = "android")]
-        #[cfg(target_os = "freebsd")]
-        pub fn gen_stub_os() -> uv_tcp_t {
-            return gen_stub_arch();
-            #[cfg(target_arch="x86_64")]
-            pub fn gen_stub_arch() -> uv_tcp_t {
-                uv_tcp_t {
-                    fields: uv_handle_fields {
-                        loop_handle: ptr::null(), type_: 0u32,
-                        close_cb: ptr::null(),
-                        data: ptr::null(),
-                    },
-                    a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-                    a03: 0 as *u8,
-                    a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-                    a07: 0 as *u8,
-                    a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
-                    a11: 0 as *u8,
-                    a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8,
-                    a15: 0 as *u8,
-                    a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8,
-                    a19: 0 as *u8,
-                    a20: 0 as *u8, a21: 0 as *u8,
-                    a22: uv_tcp_t_32bit_unix_riders { a29: 0 as *u8 },
-                }
-            }
-            #[cfg(target_arch="x86")]
-            #[cfg(target_arch="arm")]
-            #[cfg(target_arch="mips")]
-            pub fn gen_stub_arch() -> uv_tcp_t {
-                uv_tcp_t {
-                    fields: uv_handle_fields {
-                        loop_handle: ptr::null(), type_: 0u32,
-                        close_cb: ptr::null(),
-                        data: ptr::null(),
-                    },
-                    a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-                    a03: 0 as *u8,
-                    a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-                    a07: 0 as *u8,
-                    a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
-                    a11: 0 as *u8,
-                    a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8,
-                    a15: 0 as *u8,
-                    a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8,
-                    a19: 0 as *u8,
-                    a20: 0 as *u8, a21: 0 as *u8,
-                    a22: uv_tcp_t_32bit_unix_riders {
-                        a29: 0 as *u8, a30: 0 as *u8, a31: 0 as *u8,
-                    },
-                }
-            }
-        }
-        #[cfg(windows)]
-        pub fn gen_stub_os() -> uv_tcp_t {
-            uv_tcp_t {
-                fields: uv_handle_fields {
-                    loop_handle: ptr::null(), type_: 0u32,
-                    close_cb: ptr::null(),
-                    data: ptr::null(),
-                },
-                a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-                a03: 0 as *u8,
-                a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-                a07: 0 as *u8,
-                a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
-                a11: 0 as *u8,
-                a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8,
-                a15: 0 as *u8,
-                a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8,
-                a19: 0 as *u8,
-                a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8,
-                a23: 0 as *u8,
-                a24: 0 as *u8, a25: 0 as *u8,
-            }
-        }
-        #[cfg(target_os = "macos")]
-        pub fn gen_stub_os() -> uv_tcp_t {
-            use super::uv_tcp_t_osx_riders;
-
-            return gen_stub_arch();
-
-            #[cfg(target_arch = "x86_64")]
-            fn gen_stub_arch() -> uv_tcp_t {
-                uv_tcp_t {
-                    fields: uv_handle_fields {
-                        loop_handle: ptr::null(), type_: 0u32,
-                        close_cb: ptr::null(),
-                        data: ptr::null(),
-                    },
-                    a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-                    a03: 0 as *u8,
-                    a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-                    a07: 0 as *u8,
-                    a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
-                    a11: 0 as *u8,
-                    a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8,
-                    a15: 0 as *u8,
-                    a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8,
-                    a19: 0 as *u8,
-                    a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8,
-                    a23: uv_tcp_t_osx_riders {
-                        a23: 0 as *u8,
-                    }
-                }
-            }
-
-            #[cfg(target_arch = "x86")]
-            #[cfg(target_arch = "arm")]
-            fn gen_stub_arch() -> uv_tcp_t {
-                uv_tcp_t {
-                    fields: uv_handle_fields {
-                        loop_handle: ptr::null(), type_: 0u32,
-                        close_cb: ptr::null(),
-                        data: ptr::null(),
-                    },
-                    a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-                    a03: 0 as *u8,
-                    a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-                    a07: 0 as *u8,
-                    a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
-                    a11: 0 as *u8,
-                    a12: 0 as *u8, a13: 0 as *u8, a14: 0 as *u8,
-                    a15: 0 as *u8,
-                    a16: 0 as *u8, a17: 0 as *u8, a18: 0 as *u8,
-                    a19: 0 as *u8,
-                    a20: 0 as *u8, a21: 0 as *u8, a22: 0 as *u8,
-                    a23: uv_tcp_t_osx_riders {
-                        a23: 0 as *u8,
-                        a24: 0 as *u8, a25: 0 as *u8,
-                    }
-                }
-            }
-        }
-    }
-    #[cfg(unix)]
-    pub fn gen_stub_uv_connect_t() -> uv_connect_t {
-        uv_connect_t {
-            a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-            a03: 0 as *u8,
-            a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-            a07: 0 as *u8
-        }
-    }
-    #[cfg(windows)]
-    pub fn gen_stub_uv_connect_t() -> uv_connect_t {
-        uv_connect_t {
-            a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-            a03: 0 as *u8,
-            a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-            a07: 0 as *u8,
-            a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
-        }
-    }
-    #[cfg(unix)]
-    pub fn gen_stub_uv_async_t() -> uv_async_t {
-        return gen_stub_arch();
-        #[cfg(target_arch = "x86_64")]
-        pub fn gen_stub_arch() -> uv_async_t {
-            uv_async_t {
-                fields: uv_handle_fields {
-                    loop_handle: ptr::null(), type_: 0u32,
-                    close_cb: ptr::null(),
-                    data: ptr::null(),
-                },
-                a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-                a03: 0 as *u8,
-                a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-                a07: uv_async_t_32bit_unix_riders { a10: 0 as *u8 },
-            }
-        }
-        #[cfg(target_arch = "x86")]
-        #[cfg(target_arch="arm")]
-        #[cfg(target_arch="mips")]
-        pub fn gen_stub_arch() -> uv_async_t {
-            uv_async_t {
-                fields: uv_handle_fields {
-                    loop_handle: ptr::null(), type_: 0u32,
-                    close_cb: ptr::null(),
-                    data: ptr::null(),
-                },
-                a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-                a03: 0 as *u8,
-                a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-                a07: uv_async_t_32bit_unix_riders {
-                    a10: 0 as *u8,
-                }
-            }
-        }
-    }
-    #[cfg(windows)]
-    pub fn gen_stub_uv_async_t() -> uv_async_t {
-        uv_async_t {
-            fields: uv_handle_fields {
-                loop_handle: ptr::null(), type_: 0u32,
-                close_cb: ptr::null(),
-                data: ptr::null(),
-            },
-            a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-            a03: 0 as *u8,
-            a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-            a07: 0 as *u8,
-            a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
-            a11: 0 as *u8,
-            a12: 0 as *u8,
-        }
-    }
-    #[cfg(unix)]
-    pub fn gen_stub_uv_timer_t() -> uv_timer_t {
-        return gen_stub_arch();
-        #[cfg(target_arch = "x86_64")]
-        pub fn gen_stub_arch() -> uv_timer_t {
-            uv_timer_t {
-                fields: uv_handle_fields {
-                    loop_handle: ptr::null(), type_: 0u32,
-                    close_cb: ptr::null(),
-                    data: ptr::null(),
-                },
-                a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-                a03: 0 as *u8,
-                a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-                a07: 0 as *u8,
-                a08: 0 as *u8, a09: 0 as *u8,
-                a11: uv_timer_t_32bit_unix_riders {
-                    a10: 0 as *u8
-                },
-            }
-        }
-        #[cfg(target_arch = "x86")]
-        #[cfg(target_arch="arm")]
-        #[cfg(target_arch="mips")]
-        pub fn gen_stub_arch() -> uv_timer_t {
-            uv_timer_t {
-                fields: uv_handle_fields {
-                    loop_handle: ptr::null(), type_: 0u32,
-                    close_cb: ptr::null(),
-                    data: ptr::null(),
-                },
-                a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-                a03: 0 as *u8,
-                a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-                a07: 0 as *u8,
-                a08: 0 as *u8, a09: 0 as *u8,
-                a11: uv_timer_t_32bit_unix_riders {
-                    a10: 0 as *u8, a11: 0 as *u8,
-                    a12: 0 as *u8,
-                },
-            }
-        }
-    }
-    #[cfg(windows)]
-    pub fn gen_stub_uv_timer_t() -> uv_timer_t {
-        uv_timer_t {
-            fields: uv_handle_fields {
-                loop_handle: ptr::null(), type_: 0u32,
-                close_cb: ptr::null(),
-                data: ptr::null(),
-            },
-            a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-            a03: 0 as *u8,
-            a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-            a07: 0 as *u8,
-            a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
-            a11: 0 as *u8,
-        }
-    }
-    #[cfg(unix)]
-    pub fn gen_stub_uv_write_t() -> uv_write_t {
-        return gen_stub_arch();
-        #[cfg(target_arch="x86_64")]
-        pub fn gen_stub_arch() -> uv_write_t {
-            uv_write_t {
-                fields: uv_handle_fields {
-                    loop_handle: ptr::null(), type_: 0u32,
-                    close_cb: ptr::null(),
-                    data: ptr::null(),
-                },
-                a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-                a03: 0 as *u8,
-                a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-                a07: 0 as *u8,
-                a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
-                a11: 0 as *u8,
-                a12: 0 as *u8,
-                a14: uv_write_t_32bit_unix_riders { a13: 0 as *u8,
-                                                   a14: 0 as *u8,
-                                                   a15: 0 as *u8},
-            }
-        }
-        #[cfg(target_arch="x86")]
-        #[cfg(target_arch="arm")]
-        #[cfg(target_arch="mips")]
-        pub fn gen_stub_arch() -> uv_write_t {
-            uv_write_t {
-                fields: uv_handle_fields {
-                    loop_handle: ptr::null(), type_: 0u32,
-                    close_cb: ptr::null(),
-                    data: ptr::null(),
-                },
-                a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-                a03: 0 as *u8,
-                a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-                a07: 0 as *u8,
-                a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
-                a11: 0 as *u8,
-                a12: 0 as *u8,
-                a14: uv_write_t_32bit_unix_riders {
-                    a13: 0 as *u8,
-                    a14: 0 as *u8,
-                    a15: 0 as *u8,
-                    a16: 0 as *u8,
-                }
-            }
-        }
-    }
-    #[cfg(windows)]
-    pub fn gen_stub_uv_write_t() -> uv_write_t {
-        uv_write_t {
-            fields: uv_handle_fields {
-                loop_handle: ptr::null(), type_: 0u32,
-                close_cb: ptr::null(),
-                data: ptr::null(),
-            },
-            a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8,
-            a03: 0 as *u8,
-            a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8,
-            a07: 0 as *u8,
-            a08: 0 as *u8, a09: 0 as *u8, a10: 0 as *u8,
-            a11: 0 as *u8,
-            a12: 0 as *u8
-        }
-    }
-    pub fn gen_stub_uv_getaddrinfo_t() -> uv_getaddrinfo_t {
-        uv_getaddrinfo_t {
-            a00: 0 as *u8, a01: 0 as *u8, a02: 0 as *u8, a03: 0 as *u8,
-            a04: 0 as *u8, a05: 0 as *u8, a06: 0 as *u8, a07: 0 as *u8,
-            a08: 0 as *u8, a09: 0 as *u8,
-            a10: 1 as *u8, a11: 1 as *u8, a12: 1 as *u8, a13: 1 as *u8,
-            a14: 1 as *u8, a15: 1 as *u8
-        }
-    }
-}
-
-#[nolink]
-extern {
-    // libuv public API
-    unsafe fn rust_uv_loop_new() -> *libc::c_void;
-    unsafe fn rust_uv_loop_delete(lp: *libc::c_void);
-    unsafe fn rust_uv_run(loop_handle: *libc::c_void);
-    unsafe fn rust_uv_close(handle: *libc::c_void, cb: *u8);
-    unsafe fn rust_uv_walk(loop_handle: *libc::c_void, cb: *u8,
-                           arg: *libc::c_void);
-
-    unsafe fn rust_uv_idle_new() -> *uv_idle_t;
-    unsafe fn rust_uv_idle_delete(handle: *uv_idle_t);
-    unsafe fn rust_uv_idle_init(loop_handle: *uv_loop_t,
-                                handle: *uv_idle_t) -> libc::c_int;
-    unsafe fn rust_uv_idle_start(handle: *uv_idle_t,
-                                 cb: uv_idle_cb) -> libc::c_int;
-    unsafe fn rust_uv_idle_stop(handle: *uv_idle_t) -> libc::c_int;
-
-    unsafe fn rust_uv_async_send(handle: *uv_async_t);
-    unsafe fn rust_uv_async_init(loop_handle: *libc::c_void,
-                          async_handle: *uv_async_t,
-                          cb: *u8) -> libc::c_int;
-    unsafe fn rust_uv_tcp_init(
-        loop_handle: *libc::c_void,
-        handle_ptr: *uv_tcp_t) -> libc::c_int;
-    // FIXME ref #2604 .. ?
-    unsafe fn rust_uv_buf_init(out_buf: *uv_buf_t, base: *u8,
-                        len: libc::size_t);
-    unsafe fn rust_uv_last_error(loop_handle: *libc::c_void) -> uv_err_t;
-    // FIXME ref #2064
-    unsafe fn rust_uv_strerror(err: *uv_err_t) -> *libc::c_char;
-    // FIXME ref #2064
-    unsafe fn rust_uv_err_name(err: *uv_err_t) -> *libc::c_char;
-    unsafe fn rust_uv_ip4_addr(ip: *u8, port: libc::c_int)
-        -> sockaddr_in;
-    unsafe fn rust_uv_ip6_addr(ip: *u8, port: libc::c_int)
-        -> sockaddr_in6;
-    unsafe fn rust_uv_ip4_name(src: *sockaddr_in,
-                               dst: *u8,
-                               size: libc::size_t)
-                            -> libc::c_int;
-    unsafe fn rust_uv_ip6_name(src: *sockaddr_in6,
-                               dst: *u8,
-                               size: libc::size_t)
-                            -> libc::c_int;
-    unsafe fn rust_uv_ip4_port(src: *sockaddr_in) -> libc::c_uint;
-    unsafe fn rust_uv_ip6_port(src: *sockaddr_in6) -> libc::c_uint;
-    // FIXME ref #2064
-    unsafe fn rust_uv_tcp_connect(connect_ptr: *uv_connect_t,
-                                  tcp_handle_ptr: *uv_tcp_t,
-                                  after_cb: *u8,
-                                  addr: *sockaddr_in)
-                                  -> libc::c_int;
-    // FIXME ref #2064
-    unsafe fn rust_uv_tcp_bind(tcp_server: *uv_tcp_t,
-                               addr: *sockaddr_in) -> libc::c_int;
-    // FIXME ref #2064
-    unsafe fn rust_uv_tcp_connect6(connect_ptr: *uv_connect_t,
-                                   tcp_handle_ptr: *uv_tcp_t,
-                                   after_cb: *u8,
-                                   addr: *sockaddr_in6) -> libc::c_int;
-    // FIXME ref #2064
-    unsafe fn rust_uv_tcp_bind6(tcp_server: *uv_tcp_t,
-                                addr: *sockaddr_in6) -> libc::c_int;
-    unsafe fn rust_uv_tcp_getpeername(tcp_handle_ptr: *uv_tcp_t,
-                                      name: *sockaddr_in) -> libc::c_int;
-    unsafe fn rust_uv_tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t,
-                                       name: *sockaddr_in6) ->libc::c_int;
-    unsafe fn rust_uv_listen(stream: *libc::c_void,
-                             backlog: libc::c_int,
-                             cb: *u8) -> libc::c_int;
-    unsafe fn rust_uv_accept(server: *libc::c_void, client: *libc::c_void)
-                          -> libc::c_int;
-    unsafe fn rust_uv_write(req: *libc::c_void,
-                            stream: *libc::c_void,
-                            buf_in: *uv_buf_t,
-                            buf_cnt: libc::c_int,
-                            cb: *u8)
-        -> libc::c_int;
-    unsafe fn rust_uv_read_start(stream: *libc::c_void,
-                                 on_alloc: *u8,
-                                 on_read: *u8)
-        -> libc::c_int;
-    unsafe fn rust_uv_read_stop(stream: *libc::c_void) -> libc::c_int;
-    unsafe fn rust_uv_timer_init(loop_handle: *libc::c_void,
-                                 timer_handle: *uv_timer_t)
-        -> libc::c_int;
-    unsafe fn rust_uv_timer_start(
-        timer_handle: *uv_timer_t,
-        cb: *u8,
-        timeout: libc::uint64_t,
-        repeat: libc::uint64_t) -> libc::c_int;
-    unsafe fn rust_uv_timer_stop(handle: *uv_timer_t) -> libc::c_int;
-
-    unsafe fn rust_uv_getaddrinfo(loop_ptr: *libc::c_void,
-                                  handle: *uv_getaddrinfo_t,
-                                  cb: *u8,
-                                  node_name_ptr: *u8,
-                                  service_name_ptr: *u8,
-                                  // should probably only pass ptr::null()
-                                  hints: *addrinfo)
-        -> libc::c_int;
-    unsafe fn rust_uv_freeaddrinfo(res: *addrinfo);
-
-    // data accessors/helpers for rust-mapped uv structs
-    unsafe fn rust_uv_helper_get_INADDR_NONE() -> u32;
-    unsafe fn rust_uv_is_ipv4_addrinfo(input: *addrinfo) -> bool;
-    unsafe fn rust_uv_is_ipv6_addrinfo(input: *addrinfo) -> bool;
-    unsafe fn rust_uv_get_next_addrinfo(input: *addrinfo) -> *addrinfo;
-    unsafe fn rust_uv_addrinfo_as_sockaddr_in(input: *addrinfo)
-        -> *sockaddr_in;
-    unsafe fn rust_uv_addrinfo_as_sockaddr_in6(input: *addrinfo)
-        -> *sockaddr_in6;
-    unsafe fn rust_uv_malloc_buf_base_of(sug_size: libc::size_t) -> *u8;
-    unsafe fn rust_uv_free_base_of_buf(buf: uv_buf_t);
-    unsafe fn rust_uv_get_stream_handle_from_connect_req(
-        connect_req: *uv_connect_t)
-        -> *uv_stream_t;
-    unsafe fn rust_uv_get_stream_handle_from_write_req(
-        write_req: *uv_write_t)
-        -> *uv_stream_t;
-    unsafe fn rust_uv_get_loop_for_uv_handle(handle: *libc::c_void)
-        -> *libc::c_void;
-    unsafe fn rust_uv_get_data_for_uv_loop(loop_ptr: *libc::c_void)
-        -> *libc::c_void;
-    unsafe fn rust_uv_set_data_for_uv_loop(loop_ptr: *libc::c_void,
-                                           data: *libc::c_void);
-    unsafe fn rust_uv_get_data_for_uv_handle(handle: *libc::c_void)
-        -> *libc::c_void;
-    unsafe fn rust_uv_set_data_for_uv_handle(handle: *libc::c_void,
-                                             data: *libc::c_void);
-    unsafe fn rust_uv_get_data_for_req(req: *libc::c_void)
-        -> *libc::c_void;
-    unsafe fn rust_uv_set_data_for_req(req: *libc::c_void,
-                                       data: *libc::c_void);
-    unsafe fn rust_uv_get_base_from_buf(buf: uv_buf_t) -> *u8;
-    unsafe fn rust_uv_get_len_from_buf(buf: uv_buf_t) -> libc::size_t;
-
-    // sizeof testing helpers
-    unsafe fn rust_uv_helper_uv_tcp_t_size() -> libc::c_uint;
-    unsafe fn rust_uv_helper_uv_connect_t_size() -> libc::c_uint;
-    unsafe fn rust_uv_helper_uv_buf_t_size() -> libc::c_uint;
-    unsafe fn rust_uv_helper_uv_write_t_size() -> libc::c_uint;
-    unsafe fn rust_uv_helper_uv_err_t_size() -> libc::c_uint;
-    unsafe fn rust_uv_helper_sockaddr_in_size() -> libc::c_uint;
-    unsafe fn rust_uv_helper_sockaddr_in6_size() -> libc::c_uint;
-    unsafe fn rust_uv_helper_uv_async_t_size() -> libc::c_uint;
-    unsafe fn rust_uv_helper_uv_timer_t_size() -> libc::c_uint;
-    unsafe fn rust_uv_helper_uv_getaddrinfo_t_size() -> libc::c_uint;
-    unsafe fn rust_uv_helper_addrinfo_size() -> libc::c_uint;
-    unsafe fn rust_uv_helper_addr_in_size() -> libc::c_uint;
-}
-
-pub unsafe fn loop_new() -> *libc::c_void {
-    return rust_uv_loop_new();
-}
-
-pub unsafe fn loop_delete(loop_handle: *libc::c_void) {
-    rust_uv_loop_delete(loop_handle);
-}
-
-pub unsafe fn run(loop_handle: *libc::c_void) {
-    rust_uv_run(loop_handle);
-}
-
-pub unsafe fn close<T>(handle: *T, cb: *u8) {
-    rust_uv_close(handle as *libc::c_void, cb);
-}
-
-pub unsafe fn walk(loop_handle: *libc::c_void, cb: *u8, arg: *libc::c_void) {
-    rust_uv_walk(loop_handle, cb, arg);
-}
-
-pub unsafe fn idle_new() -> *uv_idle_t {
-    rust_uv_idle_new()
-}
-
-pub unsafe fn idle_delete(handle: *uv_idle_t) {
-    rust_uv_idle_delete(handle)
-}
-
-pub unsafe fn idle_init(loop_handle: *uv_loop_t,
-                        handle: *uv_idle_t) -> libc::c_int {
-    rust_uv_idle_init(loop_handle, handle)
-}
-
-pub unsafe fn idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> libc::c_int {
-    rust_uv_idle_start(handle, cb)
-}
-
-pub unsafe fn idle_stop(handle: *uv_idle_t) -> libc::c_int {
-    rust_uv_idle_stop(handle)
-}
-
-pub unsafe fn tcp_init(loop_handle: *libc::c_void, handle: *uv_tcp_t)
-    -> libc::c_int {
-    return rust_uv_tcp_init(loop_handle, handle);
-}
-// FIXME ref #2064
-pub unsafe fn tcp_connect(connect_ptr: *uv_connect_t,
-                      tcp_handle_ptr: *uv_tcp_t,
-                      addr_ptr: *sockaddr_in,
-                      after_connect_cb: *u8)
--> libc::c_int {
-    return rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr,
-                                    after_connect_cb, addr_ptr);
-}
-// FIXME ref #2064
-pub unsafe fn tcp_connect6(connect_ptr: *uv_connect_t,
-                      tcp_handle_ptr: *uv_tcp_t,
-                      addr_ptr: *sockaddr_in6,
-                      after_connect_cb: *u8)
--> libc::c_int {
-    return rust_uv_tcp_connect6(connect_ptr, tcp_handle_ptr,
-                                    after_connect_cb, addr_ptr);
-}
-// FIXME ref #2064
-pub unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t,
-                   addr_ptr: *sockaddr_in) -> libc::c_int {
-    return rust_uv_tcp_bind(tcp_server_ptr,
-                                 addr_ptr);
-}
-// FIXME ref #2064
-pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t,
-                   addr_ptr: *sockaddr_in6) -> libc::c_int {
-    return rust_uv_tcp_bind6(tcp_server_ptr,
-                                 addr_ptr);
-}
-
-pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t,
-                              name: *sockaddr_in) -> libc::c_int {
-    return rust_uv_tcp_getpeername(tcp_handle_ptr, name);
-}
-
-pub unsafe fn tcp_getpeername6(tcp_handle_ptr: *uv_tcp_t,
-                               name: *sockaddr_in6) ->libc::c_int {
-    return rust_uv_tcp_getpeername6(tcp_handle_ptr, name);
-}
-
-pub unsafe fn listen<T>(stream: *T, backlog: libc::c_int,
-                 cb: *u8) -> libc::c_int {
-    return rust_uv_listen(stream as *libc::c_void, backlog, cb);
-}
-
-pub unsafe fn accept(server: *libc::c_void, client: *libc::c_void)
-    -> libc::c_int {
-    return rust_uv_accept(server as *libc::c_void,
-                               client as *libc::c_void);
-}
-
-pub unsafe fn write<T>(req: *uv_write_t, stream: *T,
-         buf_in: *~[uv_buf_t], cb: *u8) -> libc::c_int {
-    let buf_ptr = vec::raw::to_ptr(*buf_in);
-    let buf_cnt = vec::len(*buf_in) as i32;
-    return rust_uv_write(req as *libc::c_void,
-                              stream as *libc::c_void,
-                              buf_ptr, buf_cnt, cb);
-}
-pub unsafe fn read_start(stream: *uv_stream_t, on_alloc: *u8,
-                     on_read: *u8) -> libc::c_int {
-    return rust_uv_read_start(stream as *libc::c_void,
-                                   on_alloc, on_read);
-}
-
-pub unsafe fn read_stop(stream: *uv_stream_t) -> libc::c_int {
-    return rust_uv_read_stop(stream as *libc::c_void);
-}
-
-pub unsafe fn last_error(loop_handle: *libc::c_void) -> uv_err_t {
-    return rust_uv_last_error(loop_handle);
-}
-
-pub unsafe fn strerror(err: *uv_err_t) -> *libc::c_char {
-    return rust_uv_strerror(err);
-}
-pub unsafe fn err_name(err: *uv_err_t) -> *libc::c_char {
-    return rust_uv_err_name(err);
-}
-
-pub unsafe fn async_init(loop_handle: *libc::c_void,
-                     async_handle: *uv_async_t,
-                     cb: *u8) -> libc::c_int {
-    return rust_uv_async_init(loop_handle,
-                                   async_handle,
-                                   cb);
-}
-
-pub unsafe fn async_send(async_handle: *uv_async_t) {
-    return rust_uv_async_send(async_handle);
-}
-pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t {
-    let out_buf = uv_buf_t { base: ptr::null(), len: 0 as libc::size_t };
-    let out_buf_ptr: *uv_buf_t = &out_buf;
-    rust_uv_buf_init(out_buf_ptr, input, len as size_t);
-    return out_buf;
-}
-pub unsafe fn ip4_addr(ip: &str, port: int) -> sockaddr_in {
-    do str::as_c_str(ip) |ip_buf| {
-        rust_uv_ip4_addr(ip_buf as *u8,
-                                 port as libc::c_int)
-    }
-}
-pub unsafe fn ip6_addr(ip: &str, port: int) -> sockaddr_in6 {
-    do str::as_c_str(ip) |ip_buf| {
-        rust_uv_ip6_addr(ip_buf as *u8,
-                                 port as libc::c_int)
-    }
-}
-pub unsafe fn ip4_name(src: &sockaddr_in) -> ~str {
-    // ipv4 addr max size: 15 + 1 trailing null byte
-    let dst: ~[u8] = ~[0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
-                     0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8];
-    do vec::as_imm_buf(dst) |dst_buf, size| {
-        rust_uv_ip4_name(to_unsafe_ptr(src),
-                                 dst_buf, size as libc::size_t);
-        // seems that checking the result of uv_ip4_name
-        // doesn't work too well..
-        // you're stuck looking at the value of dst_buf
-        // to see if it is the string representation of
-        // INADDR_NONE (0xffffffff or 255.255.255.255 on
-        // many platforms)
-        str::raw::from_buf(dst_buf)
-    }
-}
-pub unsafe fn ip6_name(src: &sockaddr_in6) -> ~str {
-    // ipv6 addr max size: 45 + 1 trailing null byte
-    let dst: ~[u8] = ~[0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
-                       0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
-                       0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
-                       0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
-                       0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,
-                       0u8,0u8,0u8,0u8,0u8,0u8];
-    do vec::as_imm_buf(dst) |dst_buf, size| {
-        let src_unsafe_ptr = to_unsafe_ptr(src);
-        let result = rust_uv_ip6_name(src_unsafe_ptr,
-                                              dst_buf, size as libc::size_t);
-        match result {
-          0i32 => str::raw::from_buf(dst_buf),
-          _ => ~""
-        }
-    }
-}
-pub unsafe fn ip4_port(src: &sockaddr_in) -> uint {
-    rust_uv_ip4_port(to_unsafe_ptr(src)) as uint
-}
-pub unsafe fn ip6_port(src: &sockaddr_in6) -> uint {
-    rust_uv_ip6_port(to_unsafe_ptr(src)) as uint
-}
-
-pub unsafe fn timer_init(loop_ptr: *libc::c_void,
-                     timer_ptr: *uv_timer_t) -> libc::c_int {
-    return rust_uv_timer_init(loop_ptr, timer_ptr);
-}
-pub unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: uint,
-                      repeat: uint) -> libc::c_int {
-    return rust_uv_timer_start(timer_ptr, cb, timeout as libc::uint64_t,
-                               repeat as libc::uint64_t);
-}
-pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> libc::c_int {
-    return rust_uv_timer_stop(timer_ptr);
-}
-pub unsafe fn getaddrinfo(loop_ptr: *libc::c_void,
-                           handle: *uv_getaddrinfo_t,
-                           cb: *u8,
-                           node_name_ptr: *u8,
-                           service_name_ptr: *u8,
-                           hints: *addrinfo) -> libc::c_int {
-    rust_uv_getaddrinfo(loop_ptr,
-                           handle,
-                           cb,
-                           node_name_ptr,
-                           service_name_ptr,
-                           hints)
-}
-pub unsafe fn freeaddrinfo(res: *addrinfo) {
-    rust_uv_freeaddrinfo(res);
-}
-
-// libuv struct initializers
-pub fn tcp_t() -> uv_tcp_t {
-    return uv_ll_struct_stubgen::gen_stub_uv_tcp_t();
-}
-pub fn connect_t() -> uv_connect_t {
-    return uv_ll_struct_stubgen::gen_stub_uv_connect_t();
-}
-pub fn write_t() -> uv_write_t {
-    return uv_ll_struct_stubgen::gen_stub_uv_write_t();
-}
-pub fn async_t() -> uv_async_t {
-    return uv_ll_struct_stubgen::gen_stub_uv_async_t();
-}
-pub fn timer_t() -> uv_timer_t {
-    return uv_ll_struct_stubgen::gen_stub_uv_timer_t();
-}
-pub fn getaddrinfo_t() -> uv_getaddrinfo_t {
-    return uv_ll_struct_stubgen::gen_stub_uv_getaddrinfo_t();
-}
-
-// data access helpers
-pub unsafe fn get_loop_for_uv_handle<T>(handle: *T)
-    -> *libc::c_void {
-    return rust_uv_get_loop_for_uv_handle(handle as *libc::c_void);
-}
-pub unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t)
-    -> *uv_stream_t {
-    return rust_uv_get_stream_handle_from_connect_req(
-        connect);
-}
-pub unsafe fn get_stream_handle_from_write_req(
-    write_req: *uv_write_t)
-    -> *uv_stream_t {
-    return rust_uv_get_stream_handle_from_write_req(
-        write_req);
-}
-pub unsafe fn get_data_for_uv_loop(loop_ptr: *libc::c_void) -> *libc::c_void {
-    rust_uv_get_data_for_uv_loop(loop_ptr)
-}
-pub unsafe fn set_data_for_uv_loop(loop_ptr: *libc::c_void,
-                                   data: *libc::c_void) {
-    rust_uv_set_data_for_uv_loop(loop_ptr, data);
-}
-pub unsafe fn get_data_for_uv_handle<T>(handle: *T) -> *libc::c_void {
-    return rust_uv_get_data_for_uv_handle(handle as *libc::c_void);
-}
-pub unsafe fn set_data_for_uv_handle<T, U>(handle: *T, data: *U) {
-    rust_uv_set_data_for_uv_handle(handle as *libc::c_void,
-                                           data as *libc::c_void);
-}
-pub unsafe fn get_data_for_req<T>(req: *T) -> *libc::c_void {
-    return rust_uv_get_data_for_req(req as *libc::c_void);
-}
-pub unsafe fn set_data_for_req<T, U>(req: *T,
-                    data: *U) {
-    rust_uv_set_data_for_req(req as *libc::c_void,
-                                     data as *libc::c_void);
-}
-pub unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 {
-    return rust_uv_get_base_from_buf(buf);
-}
-pub unsafe fn get_len_from_buf(buf: uv_buf_t) -> libc::size_t {
-    return rust_uv_get_len_from_buf(buf);
-}
-pub unsafe fn malloc_buf_base_of(suggested_size: libc::size_t)
-    -> *u8 {
-    return rust_uv_malloc_buf_base_of(suggested_size);
-}
-pub unsafe fn free_base_of_buf(buf: uv_buf_t) {
-    rust_uv_free_base_of_buf(buf);
-}
-
-pub unsafe fn get_last_err_info(uv_loop: *libc::c_void) -> ~str {
-    let err = last_error(uv_loop);
-    let err_ptr: *uv_err_t = &err;
-    let err_name = str::raw::from_c_str(err_name(err_ptr));
-    let err_msg = str::raw::from_c_str(strerror(err_ptr));
-    return fmt!("LIBUV ERROR: name: %s msg: %s",
-                    err_name, err_msg);
-}
-
-pub unsafe fn get_last_err_data(uv_loop: *libc::c_void) -> uv_err_data {
-    let err = last_error(uv_loop);
-    let err_ptr: *uv_err_t = &err;
-    let err_name = str::raw::from_c_str(err_name(err_ptr));
-    let err_msg = str::raw::from_c_str(strerror(err_ptr));
-    uv_err_data { err_name: err_name, err_msg: err_msg }
-}
-
-pub struct uv_err_data {
-    err_name: ~str,
-    err_msg: ~str,
-}
-
-pub unsafe fn is_ipv4_addrinfo(input: *addrinfo) -> bool {
-    rust_uv_is_ipv4_addrinfo(input)
-}
-pub unsafe fn is_ipv6_addrinfo(input: *addrinfo) -> bool {
-    rust_uv_is_ipv6_addrinfo(input)
-}
-pub unsafe fn get_INADDR_NONE() -> u32 {
-    rust_uv_helper_get_INADDR_NONE()
-}
-pub unsafe fn get_next_addrinfo(input: *addrinfo) -> *addrinfo {
-    rust_uv_get_next_addrinfo(input)
-}
-pub unsafe fn addrinfo_as_sockaddr_in(input: *addrinfo) -> *sockaddr_in {
-    rust_uv_addrinfo_as_sockaddr_in(input)
-}
-pub unsafe fn addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6 {
-    rust_uv_addrinfo_as_sockaddr_in6(input)
-}
-
-#[cfg(test)]
-mod test {
-    use core::comm::{SharedChan, stream, GenericChan, GenericPort};
-    use super::*;
-
-    enum tcp_read_data {
-        tcp_read_eof,
-        tcp_read_more(~[u8]),
-        tcp_read_error
-    }
-
-    struct request_wrapper {
-        write_req: *uv_write_t,
-        req_buf: *~[uv_buf_t],
-        read_chan: SharedChan<~str>,
-    }
-
-    extern fn after_close_cb(handle: *libc::c_void) {
-        debug!("after uv_close! handle ptr: %?",
-                        handle);
-    }
-
-    extern fn on_alloc_cb(handle: *libc::c_void,
-                         suggested_size: libc::size_t)
-        -> uv_buf_t {
-        unsafe {
-            debug!(~"on_alloc_cb!");
-            let char_ptr = malloc_buf_base_of(suggested_size);
-            debug!("on_alloc_cb h: %? char_ptr: %u sugsize: %u",
-                             handle,
-                             char_ptr as uint,
-                             suggested_size as uint);
-            return buf_init(char_ptr, suggested_size as uint);
-        }
-    }
-
-    extern fn on_read_cb(stream: *uv_stream_t,
-                        nread: libc::ssize_t,
-                        buf: uv_buf_t) {
-        unsafe {
-            let nread = nread as int;
-            debug!("CLIENT entering on_read_cb nred: %d",
-                            nread);
-            if (nread > 0) {
-                // we have data
-                debug!("CLIENT read: data! nread: %d", nread);
-                read_stop(stream);
-                let client_data =
-                    get_data_for_uv_handle(stream as *libc::c_void)
-                      as *request_wrapper;
-                let buf_base = get_base_from_buf(buf);
-                let bytes = vec::from_buf(buf_base, nread as uint);
-                let read_chan = (*client_data).read_chan.clone();
-                let msg_from_server = str::from_bytes(bytes);
-                read_chan.send(msg_from_server);
-                close(stream as *libc::c_void, after_close_cb)
-            }
-            else if (nread == -1) {
-                // err .. possibly EOF
-                debug!(~"read: eof!");
-            }
-            else {
-                // nread == 0 .. do nothing, just free buf as below
-                debug!(~"read: do nothing!");
-            }
-            // when we're done
-            free_base_of_buf(buf);
-            debug!(~"CLIENT exiting on_read_cb");
-        }
-    }
-
-    extern fn on_write_complete_cb(write_req: *uv_write_t,
-                                  status: libc::c_int) {
-        unsafe {
-            debug!(
-                "CLIENT beginning on_write_complete_cb status: %d",
-                     status as int);
-            let stream = get_stream_handle_from_write_req(write_req);
-            debug!(
-                "CLIENT on_write_complete_cb: tcp:%d write_handle:%d",
-                stream as int, write_req as int);
-            let result = read_start(stream, on_alloc_cb, on_read_cb);
-            debug!("CLIENT ending on_write_complete_cb .. status: %d",
-                     result as int);
-        }
-    }
-
-    extern fn on_connect_cb(connect_req_ptr: *uv_connect_t,
-                                 status: libc::c_int) {
-        unsafe {
-            debug!("beginning on_connect_cb .. status: %d",
-                             status as int);
-            let stream =
-                get_stream_handle_from_connect_req(connect_req_ptr);
-            if (status == 0i32) {
-                debug!(~"on_connect_cb: in status=0 if..");
-                let client_data = get_data_for_req(
-                    connect_req_ptr as *libc::c_void)
-                    as *request_wrapper;
-                let write_handle = (*client_data).write_req;
-                debug!("on_connect_cb: tcp: %d write_hdl: %d",
-                                stream as int, write_handle as int);
-                let write_result = write(write_handle,
-                                  stream as *libc::c_void,
-                                  (*client_data).req_buf,
-                                  on_write_complete_cb);
-                debug!("on_connect_cb: write() status: %d",
-                                 write_result as int);
-            }
-            else {
-                let test_loop = get_loop_for_uv_handle(
-                    stream as *libc::c_void);
-                let err_msg = get_last_err_info(test_loop);
-                debug!(err_msg);
-                assert!(false);
-            }
-            debug!(~"finishing on_connect_cb");
-        }
-    }
-
-    fn impl_uv_tcp_request(ip: &str, port: int, req_str: &str,
-                          client_chan: SharedChan<~str>) {
-        unsafe {
-            let test_loop = loop_new();
-            let tcp_handle = tcp_t();
-            let tcp_handle_ptr: *uv_tcp_t = &tcp_handle;
-            let connect_handle = connect_t();
-            let connect_req_ptr: *uv_connect_t = &connect_handle;
-
-            // this is the persistent payload of data that we
-            // need to pass around to get this example to work.
-            // In C, this would be a malloc'd or stack-allocated
-            // struct that we'd cast to a void* and store as the
-            // data field in our uv_connect_t struct
-            let req_str_bytes = str::to_bytes(req_str);
-            let req_msg_ptr: *u8 = vec::raw::to_ptr(req_str_bytes);
-            debug!("req_msg ptr: %u", req_msg_ptr as uint);
-            let req_msg = ~[
-                buf_init(req_msg_ptr, req_str_bytes.len())
-            ];
-            // this is the enclosing record, we'll pass a ptr to
-            // this to C..
-            let write_handle = write_t();
-            let write_handle_ptr: *uv_write_t = &write_handle;
-            debug!("tcp req: tcp stream: %d write_handle: %d",
-                             tcp_handle_ptr as int,
-                             write_handle_ptr as int);
-            let client_data = request_wrapper {
-                write_req: write_handle_ptr,
-                req_buf: &req_msg,
-                read_chan: client_chan
-            };
-
-            let tcp_init_result = tcp_init(test_loop as *libc::c_void,
-                                           tcp_handle_ptr);
-            if (tcp_init_result == 0) {
-                debug!(~"successful tcp_init_result");
-
-                debug!(~"building addr...");
-                let addr = ip4_addr(ip, port);
-                // FIXME ref #2064
-                let addr_ptr: *sockaddr_in = &addr;
-                debug!("after build addr in rust. port: %u",
-                       addr.sin_port as uint);
-
-                // this should set up the connection request..
-                debug!("b4 call tcp_connect connect cb: %u ",
-                       on_connect_cb as uint);
-                let tcp_connect_result = tcp_connect(connect_req_ptr,
-                                                     tcp_handle_ptr,
-                                                     addr_ptr,
-                                                     on_connect_cb);
-                if (tcp_connect_result == 0) {
-                    // not set the data on the connect_req
-                    // until its initialized
-                    set_data_for_req(connect_req_ptr as *libc::c_void,
-                                     &client_data);
-                    set_data_for_uv_handle(tcp_handle_ptr as *libc::c_void,
-                                           &client_data);
-                    debug!(~"before run tcp req loop");
-                    run(test_loop);
-                    debug!(~"after run tcp req loop");
-                }
-                else {
-                   debug!(~"tcp_connect() failure");
-                   assert!(false);
-                }
-            }
-            else {
-                debug!(~"tcp_init() failure");
-                assert!(false);
-            }
-            loop_delete(test_loop);
-        }
-    }
-
-    extern fn server_after_close_cb(handle: *libc::c_void) {
-        debug!("SERVER server stream closed, should exit. h: %?",
-                   handle);
-    }
-
-    extern fn client_stream_after_close_cb(handle: *libc::c_void) {
-        unsafe {
-            debug!(~"SERVER: closed client stream, now closing server stream");
-            let client_data = get_data_for_uv_handle(
-                handle) as
-                *tcp_server_data;
-            close((*client_data).server as *libc::c_void,
-                          server_after_close_cb);
-        }
-    }
-
-    extern fn after_server_resp_write(req: *uv_write_t) {
-        unsafe {
-            let client_stream_ptr =
-                get_stream_handle_from_write_req(req);
-            debug!(~"SERVER: resp sent... closing client stream");
-            close(client_stream_ptr as *libc::c_void,
-                          client_stream_after_close_cb)
-        }
-    }
-
-    extern fn on_server_read_cb(client_stream_ptr: *uv_stream_t,
-                               nread: libc::ssize_t,
-                               buf: uv_buf_t) {
-        unsafe {
-            let nread = nread as int;
-            if (nread > 0) {
-                // we have data
-                debug!("SERVER read: data! nread: %d", nread);
-
-                // pull out the contents of the write from the client
-                let buf_base = get_base_from_buf(buf);
-                let buf_len = get_len_from_buf(buf) as uint;
-                debug!("SERVER buf base: %u, len: %u, nread: %d",
-                                buf_base as uint,
-                                buf_len as uint,
-                                nread);
-                let bytes = vec::from_buf(buf_base, nread as uint);
-                let request_str = str::from_bytes(bytes);
-
-                let client_data = get_data_for_uv_handle(
-                    client_stream_ptr as *libc::c_void) as *tcp_server_data;
-
-                let server_kill_msg = copy (*client_data).server_kill_msg;
-                let write_req = (*client_data).server_write_req;
-                if str::contains(request_str, server_kill_msg) {
-                    debug!(~"SERVER: client req contains kill_msg!");
-                    debug!(~"SERVER: sending response to client");
-                    read_stop(client_stream_ptr);
-                    let server_chan = (*client_data).server_chan.clone();
-                    server_chan.send(request_str);
-                    let write_result = write(
-                        write_req,
-                        client_stream_ptr as *libc::c_void,
-                        (*client_data).server_resp_buf,
-                        after_server_resp_write);
-                    debug!("SERVER: resp write result: %d",
-                                write_result as int);
-                    if (write_result != 0i32) {
-                        debug!(~"bad result for server resp write()");
-                        debug!(get_last_err_info(
-                            get_loop_for_uv_handle(client_stream_ptr
-                                as *libc::c_void)));
-                        assert!(false);
-                    }
-                }
-                else {
-                    debug!(~"SERVER: client req !contain kill_msg!");
-                }
-            }
-            else if (nread == -1) {
-                // err .. possibly EOF
-                debug!(~"read: eof!");
-            }
-            else {
-                // nread == 0 .. do nothing, just free buf as below
-                debug!(~"read: do nothing!");
-            }
-            // when we're done
-            free_base_of_buf(buf);
-            debug!(~"SERVER exiting on_read_cb");
-        }
-    }
-
-    extern fn server_connection_cb(server_stream_ptr:
-                                    *uv_stream_t,
-                                  status: libc::c_int) {
-        unsafe {
-            debug!(~"client connecting!");
-            let test_loop = get_loop_for_uv_handle(
-                                   server_stream_ptr as *libc::c_void);
-            if status != 0i32 {
-                let err_msg = get_last_err_info(test_loop);
-                debug!("server_connect_cb: non-zero status: %?",
-                             err_msg);
-                return;
-            }
-            let server_data = get_data_for_uv_handle(
-                server_stream_ptr as *libc::c_void) as *tcp_server_data;
-            let client_stream_ptr = (*server_data).client;
-            let client_init_result = tcp_init(test_loop,
-                                                      client_stream_ptr);
-            set_data_for_uv_handle(
-                client_stream_ptr as *libc::c_void,
-                server_data as *libc::c_void);
-            if (client_init_result == 0i32) {
-                debug!(~"successfully initialized client stream");
-                let accept_result = accept(server_stream_ptr as
-                                                     *libc::c_void,
-                                                   client_stream_ptr as
-                                                     *libc::c_void);
-                if (accept_result == 0i32) {
-                    // start reading
-                    let read_result = read_start(
-                        client_stream_ptr as *uv_stream_t,
-                                                         on_alloc_cb,
-                                                         on_server_read_cb);
-                    if (read_result == 0i32) {
-                        debug!(~"successful server read start");
-                    }
-                    else {
-                        debug!("server_connection_cb: bad read:%d",
-                                        read_result as int);
-                        assert!(false);
-                    }
-                }
-                else {
-                    debug!("server_connection_cb: bad accept: %d",
-                                accept_result as int);
-                    assert!(false);
-                }
-            }
-            else {
-                debug!("server_connection_cb: bad client init: %d",
-                            client_init_result as int);
-                assert!(false);
-            }
-        }
-    }
-
-    struct tcp_server_data {
-        client: *uv_tcp_t,
-        server: *uv_tcp_t,
-        server_kill_msg: ~str,
-        server_resp_buf: *~[uv_buf_t],
-        server_chan: SharedChan<~str>,
-        server_write_req: *uv_write_t,
-    }
-
-    struct async_handle_data {
-        continue_chan: SharedChan<bool>,
-    }
-
-    extern fn async_close_cb(handle: *libc::c_void) {
-        debug!("SERVER: closing async cb... h: %?",
-                   handle);
-    }
-
-    extern fn continue_async_cb(async_handle: *uv_async_t,
-                               status: libc::c_int) {
-        unsafe {
-            // once we're in the body of this callback,
-            // the tcp server's loop is set up, so we
-            // can continue on to let the tcp client
-            // do its thang
-            let data = get_data_for_uv_handle(
-                async_handle as *libc::c_void) as *async_handle_data;
-            let continue_chan = (*data).continue_chan.clone();
-            let should_continue = status == 0i32;
-            continue_chan.send(should_continue);
-            close(async_handle as *libc::c_void, async_close_cb);
-        }
-    }
-
-    fn impl_uv_tcp_server(server_ip: &str,
-                          server_port: int,
-                          kill_server_msg: ~str,
-                          server_resp_msg: ~str,
-                          server_chan: SharedChan<~str>,
-                          continue_chan: SharedChan<bool>) {
-        unsafe {
-            let test_loop = loop_new();
-            let tcp_server = tcp_t();
-            let tcp_server_ptr: *uv_tcp_t = &tcp_server;
-
-            let tcp_client = tcp_t();
-            let tcp_client_ptr: *uv_tcp_t = &tcp_client;
-
-            let server_write_req = write_t();
-            let server_write_req_ptr: *uv_write_t = &server_write_req;
-
-            let resp_str_bytes = str::to_bytes(server_resp_msg);
-            let resp_msg_ptr: *u8 = vec::raw::to_ptr(resp_str_bytes);
-            debug!("resp_msg ptr: %u", resp_msg_ptr as uint);
-            let resp_msg = ~[
-                buf_init(resp_msg_ptr, resp_str_bytes.len())
-            ];
-
-            let continue_async_handle = async_t();
-            let continue_async_handle_ptr: *uv_async_t =
-                &continue_async_handle;
-            let async_data =
-                async_handle_data { continue_chan: continue_chan };
-            let async_data_ptr: *async_handle_data = &async_data;
-
-            let server_data = tcp_server_data {
-                client: tcp_client_ptr,
-                server: tcp_server_ptr,
-                server_kill_msg: kill_server_msg,
-                server_resp_buf: &resp_msg,
-                server_chan: server_chan,
-                server_write_req: server_write_req_ptr
-            };
-            let server_data_ptr: *tcp_server_data = &server_data;
-            set_data_for_uv_handle(tcp_server_ptr as *libc::c_void,
-                                           server_data_ptr as *libc::c_void);
-
-            // uv_tcp_init()
-            let tcp_init_result = tcp_init(
-                test_loop as *libc::c_void, tcp_server_ptr);
-            if (tcp_init_result == 0i32) {
-                let server_addr = ip4_addr(server_ip, server_port);
-                // FIXME ref #2064
-                let server_addr_ptr: *sockaddr_in = &server_addr;
-
-                // uv_tcp_bind()
-                let bind_result = tcp_bind(tcp_server_ptr, server_addr_ptr);
-                if (bind_result == 0i32) {
-                    debug!(~"successful uv_tcp_bind, listening");
-
-                    // uv_listen()
-                    let listen_result = listen(tcp_server_ptr as
-                                                         *libc::c_void,
-                                                       128i32,
-                                                       server_connection_cb);
-                    if (listen_result == 0i32) {
-                        // let the test know it can set up the tcp server,
-                        // now.. this may still present a race, not sure..
-                        let async_result = async_init(test_loop,
-                                           continue_async_handle_ptr,
-                                           continue_async_cb);
-                        if (async_result == 0i32) {
-                            set_data_for_uv_handle(
-                                continue_async_handle_ptr as *libc::c_void,
-                                async_data_ptr as *libc::c_void);
-                            async_send(continue_async_handle_ptr);
-                            // uv_run()
-                            run(test_loop);
-                            debug!(~"server uv::run() has returned");
-                        }
-                        else {
-                            debug!("uv_async_init failure: %d",
-                                    async_result as int);
-                            assert!(false);
-                        }
-                    }
-                    else {
-                        debug!("non-zero result on uv_listen: %d",
-                                    listen_result as int);
-                        assert!(false);
-                    }
-                }
-                else {
-                    debug!("non-zero result on uv_tcp_bind: %d",
-                                bind_result as int);
-                    assert!(false);
-                }
-            }
-            else {
-                debug!("non-zero result on uv_tcp_init: %d",
-                            tcp_init_result as int);
-                assert!(false);
-            }
-            loop_delete(test_loop);
-        }
-    }
-
-    // this is the impl for a test that is (maybe) ran on a
-    // per-platform/arch basis below
-    pub fn impl_uv_tcp_server_and_request() {
-        let bind_ip = ~"0.0.0.0";
-        let request_ip = ~"127.0.0.1";
-        let port = 8886;
-        let kill_server_msg = ~"does a dog have buddha nature?";
-        let server_resp_msg = ~"mu!";
-        let (client_port, client_chan) = stream::<~str>();
-        let client_chan = SharedChan::new(client_chan);
-        let (server_port, server_chan) = stream::<~str>();
-        let server_chan = SharedChan::new(server_chan);
-
-        let (continue_port, continue_chan) = stream::<bool>();
-        let continue_chan = SharedChan::new(continue_chan);
-
-        let kill_server_msg_copy = copy kill_server_msg;
-        let server_resp_msg_copy = copy server_resp_msg;
-        do task::spawn_sched(task::ManualThreads(1)) {
-            impl_uv_tcp_server(bind_ip, port,
-                               copy kill_server_msg_copy,
-                               copy server_resp_msg_copy,
-                               server_chan.clone(),
-                               continue_chan.clone());
-        };
-
-        // block until the server up is.. possibly a race?
-        debug!(~"before receiving on server continue_port");
-        continue_port.recv();
-        debug!(~"received on continue port, set up tcp client");
-
-        let kill_server_msg_copy = copy kill_server_msg;
-        do task::spawn_sched(task::ManualThreads(1u)) {
-            impl_uv_tcp_request(request_ip, port,
-                               kill_server_msg_copy,
-                               client_chan.clone());
-        };
-
-        let msg_from_client = server_port.recv();
-        let msg_from_server = client_port.recv();
-
-        assert!(str::contains(msg_from_client, kill_server_msg));
-        assert!(str::contains(msg_from_server, server_resp_msg));
-    }
-
-    // FIXME don't run on fbsd or linux 32 bit(#2064)
-    #[cfg(target_os="win32")]
-    #[cfg(target_os="darwin")]
-    #[cfg(target_os="linux")]
-    #[cfg(target_os="android")]
-    mod tcp_and_server_client_test {
-        #[cfg(target_arch="x86_64")]
-        mod impl64 {
-            #[test]
-            fn test_uv_ll_tcp_server_and_request() {
-                unsafe {
-                    super::super::impl_uv_tcp_server_and_request();
-                }
-            }
-        }
-        #[cfg(target_arch="x86")]
-        #[cfg(target_arch="arm")]
-        #[cfg(target_arch="mips")]
-        mod impl32 {
-            #[test]
-            #[ignore(cfg(target_os = "linux"))]
-            fn test_uv_ll_tcp_server_and_request() {
-                unsafe {
-                    super::super::impl_uv_tcp_server_and_request();
-                }
-            }
-        }
-    }
-
-    fn struct_size_check_common<TStruct>(t_name: ~str,
-                                         foreign_size: libc::c_uint) {
-        let rust_size = sys::size_of::<TStruct>();
-        let sizes_match = foreign_size as uint == rust_size;
-        if !sizes_match {
-            let output = fmt!(
-                "STRUCT_SIZE FAILURE: %s -- actual: %u expected: %u",
-                t_name, rust_size, foreign_size as uint);
-            debug!(output);
-        }
-        assert!(sizes_match);
-    }
-
-    // struct size tests
-    #[test]
-    fn test_uv_ll_struct_size_uv_tcp_t() {
-        unsafe {
-            struct_size_check_common::<uv_tcp_t>(
-                ~"uv_tcp_t",
-                super::rust_uv_helper_uv_tcp_t_size()
-            );
-        }
-    }
-    #[test]
-    fn test_uv_ll_struct_size_uv_connect_t() {
-        unsafe {
-            struct_size_check_common::<uv_connect_t>(
-                ~"uv_connect_t",
-                super::rust_uv_helper_uv_connect_t_size()
-            );
-        }
-    }
-    #[test]
-    fn test_uv_ll_struct_size_uv_buf_t() {
-        unsafe {
-            struct_size_check_common::<uv_buf_t>(
-                ~"uv_buf_t",
-                super::rust_uv_helper_uv_buf_t_size()
-            );
-        }
-    }
-    #[test]
-    fn test_uv_ll_struct_size_uv_write_t() {
-        unsafe {
-            struct_size_check_common::<uv_write_t>(
-                ~"uv_write_t",
-                super::rust_uv_helper_uv_write_t_size()
-            );
-        }
-    }
-
-    #[test]
-    fn test_uv_ll_struct_size_sockaddr_in() {
-        unsafe {
-            struct_size_check_common::<sockaddr_in>(
-                ~"sockaddr_in",
-                super::rust_uv_helper_sockaddr_in_size()
-            );
-        }
-    }
-    #[test]
-    fn test_uv_ll_struct_size_sockaddr_in6() {
-        unsafe {
-            let foreign_handle_size =
-                super::rust_uv_helper_sockaddr_in6_size();
-            let rust_handle_size = sys::size_of::<sockaddr_in6>();
-            let output = fmt!("sockaddr_in6 -- foreign: %u rust: %u",
-                              foreign_handle_size as uint, rust_handle_size);
-            debug!(output);
-            // FIXME #1645 .. rust appears to pad structs to the nearest
-            // byte..?
-            // .. can't get the uv::ll::sockaddr_in6 to == 28 :/
-            // .. so the type always appears to be 32 in size.. which is
-            // good, i guess.. better too big than too little
-            assert!((4u+foreign_handle_size as uint) ==
-                rust_handle_size);
-        }
-    }
-    #[test]
-    #[ignore(reason = "questionable size calculations")]
-    fn test_uv_ll_struct_size_addr_in() {
-        unsafe {
-            let foreign_handle_size =
-                super::rust_uv_helper_addr_in_size();
-            let rust_handle_size = sys::size_of::<addr_in>();
-            let output = fmt!("addr_in -- foreign: %u rust: %u",
-                              foreign_handle_size as uint, rust_handle_size);
-            debug!(output);
-            // FIXME #1645 .. see note above about struct padding
-            assert!((4u+foreign_handle_size as uint) ==
-                rust_handle_size);
-        }
-    }
-
-    #[test]
-    fn test_uv_ll_struct_size_uv_async_t() {
-        unsafe {
-            struct_size_check_common::<uv_async_t>(
-                ~"uv_async_t",
-                super::rust_uv_helper_uv_async_t_size()
-            );
-        }
-    }
-
-    #[test]
-    fn test_uv_ll_struct_size_uv_timer_t() {
-        unsafe {
-            struct_size_check_common::<uv_timer_t>(
-                ~"uv_timer_t",
-                super::rust_uv_helper_uv_timer_t_size()
-            );
-        }
-    }
-
-    #[test]
-    #[ignore(cfg(target_os = "win32"))]
-    fn test_uv_ll_struct_size_uv_getaddrinfo_t() {
-        unsafe {
-            struct_size_check_common::<uv_getaddrinfo_t>(
-                ~"uv_getaddrinfo_t",
-                super::rust_uv_helper_uv_getaddrinfo_t_size()
-            );
-        }
-    }
-    #[test]
-    #[ignore(cfg(target_os = "macos"))]
-    #[ignore(cfg(target_os = "win32"))]
-    fn test_uv_ll_struct_size_addrinfo() {
-        unsafe {
-            struct_size_check_common::<uv_timer_t>(
-                ~"addrinfo",
-                super::rust_uv_helper_uv_timer_t_size()
-            );
-        }
-    }
-}
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
new file mode 100644
index 00000000000..65f8dab25a5
--- /dev/null
+++ b/src/libstd/vec.rs
@@ -0,0 +1,4615 @@
+// 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.
+
+//! Vectors
+
+#[warn(non_camel_case_types)];
+
+use cast::transmute;
+use cast;
+use container::{Container, Mutable};
+use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
+use clone::Clone;
+use old_iter::BaseIter;
+use old_iter;
+use iterator::Iterator;
+use kinds::Copy;
+use libc;
+use old_iter::CopyableIter;
+use option::{None, Option, Some};
+use ptr::to_unsafe_ptr;
+use ptr;
+use ptr::Ptr;
+use sys;
+use uint;
+use unstable::intrinsics;
+use vec;
+use util;
+
+#[cfg(not(test))] use cmp::Equiv;
+
+pub mod rustrt {
+    use libc;
+    use sys;
+    use vec::raw;
+
+    #[abi = "cdecl"]
+    pub extern {
+        // These names are terrible. reserve_shared applies
+        // to ~[] and reserve_shared_actual applies to @[].
+        #[fast_ffi]
+        unsafe fn vec_reserve_shared(t: *sys::TypeDesc,
+                                     v: **raw::VecRepr,
+                                     n: libc::size_t);
+        #[fast_ffi]
+        unsafe fn vec_reserve_shared_actual(t: *sys::TypeDesc,
+                                            v: **raw::VecRepr,
+                                            n: libc::size_t);
+    }
+}
+
+/// Returns true if a vector contains no elements
+pub fn is_empty<T>(v: &const [T]) -> bool {
+    as_const_buf(v, |_p, len| len == 0u)
+}
+
+/// Returns true if two vectors have the same length
+pub fn same_length<T, U>(xs: &const [T], ys: &const [U]) -> bool {
+    xs.len() == ys.len()
+}
+
+/**
+ * Reserves capacity for exactly `n` elements in the given vector.
+ *
+ * If the capacity for `v` is already equal to or greater than the requested
+ * capacity, then no action is taken.
+ *
+ * # Arguments
+ *
+ * * v - A vector
+ * * n - The number of elements to reserve space for
+ */
+#[inline]
+pub fn reserve<T>(v: &mut ~[T], n: uint) {
+    // Only make the (slow) call into the runtime if we have to
+    use managed;
+    if capacity(v) < n {
+        unsafe {
+            let ptr: **raw::VecRepr = cast::transmute(v);
+            let td = sys::get_type_desc::<T>();
+            if ((**ptr).box_header.ref_count ==
+                managed::raw::RC_MANAGED_UNIQUE) {
+                rustrt::vec_reserve_shared_actual(td, ptr, n as libc::size_t);
+            } else {
+                rustrt::vec_reserve_shared(td, ptr, n as libc::size_t);
+            }
+        }
+    }
+}
+
+/**
+ * Reserves capacity for at least `n` elements in the given vector.
+ *
+ * This function will over-allocate in order to amortize the allocation costs
+ * in scenarios where the caller may need to repeatedly reserve additional
+ * space.
+ *
+ * If the capacity for `v` is already equal to or greater than the requested
+ * capacity, then no action is taken.
+ *
+ * # Arguments
+ *
+ * * v - A vector
+ * * n - The number of elements to reserve space for
+ */
+pub fn reserve_at_least<T>(v: &mut ~[T], n: uint) {
+    reserve(v, uint::next_power_of_two(n));
+}
+
+/// Returns the number of elements the vector can hold without reallocating
+#[inline(always)]
+pub fn capacity<T>(v: &const ~[T]) -> uint {
+    unsafe {
+        let repr: **raw::VecRepr = transmute(v);
+        (**repr).unboxed.alloc / sys::nonzero_size_of::<T>()
+    }
+}
+
+/// Returns the length of a vector
+#[inline(always)]
+pub fn len<T>(v: &const [T]) -> uint {
+    as_const_buf(v, |_p, len| len)
+}
+
+// A botch to tide us over until core and std are fully demuted.
+pub fn uniq_len<T>(v: &const ~[T]) -> uint {
+    unsafe {
+        let v: &~[T] = transmute(v);
+        as_const_buf(*v, |_p, len| len)
+    }
+}
+
+/**
+ * Creates and initializes an owned vector.
+ *
+ * Creates an owned vector of size `n_elts` and initializes the elements
+ * to the value returned by the function `op`.
+ */
+pub fn from_fn<T>(n_elts: uint, op: old_iter::InitOp<T>) -> ~[T] {
+    unsafe {
+        let mut v = with_capacity(n_elts);
+        do as_mut_buf(v) |p, _len| {
+            let mut i: uint = 0u;
+            while i < n_elts {
+                intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i)),
+                                          op(i));
+                i += 1u;
+            }
+        }
+        raw::set_len(&mut v, n_elts);
+        v
+    }
+}
+
+/**
+ * Creates and initializes an owned vector.
+ *
+ * Creates an owned vector of size `n_elts` and initializes the elements
+ * to the value `t`.
+ */
+pub fn from_elem<T:Copy>(n_elts: uint, t: T) -> ~[T] {
+    from_fn(n_elts, |_i| copy t)
+}
+
+/// Creates a new unique vector with the same contents as the slice
+pub fn to_owned<T:Copy>(t: &[T]) -> ~[T] {
+    from_fn(t.len(), |i| t[i])
+}
+
+/// Creates a new vector with a capacity of `capacity`
+pub fn with_capacity<T>(capacity: uint) -> ~[T] {
+    let mut vec = ~[];
+    reserve(&mut vec, capacity);
+    vec
+}
+
+/**
+ * Builds a vector by calling a provided function with an argument
+ * function that pushes an element to the back of a vector.
+ * This version takes an initial capacity for the vector.
+ *
+ * # Arguments
+ *
+ * * size - An initial size of the vector to reserve
+ * * builder - A function that will construct the vector. It receives
+ *             as an argument a function that will push an element
+ *             onto the vector being constructed.
+ */
+#[inline(always)]
+pub fn build_sized<A>(size: uint, builder: &fn(push: &fn(v: A))) -> ~[A] {
+    let mut vec = with_capacity(size);
+    builder(|x| vec.push(x));
+    vec
+}
+
+/**
+ * Builds a vector by calling a provided function with an argument
+ * function that pushes an element to the back of a vector.
+ *
+ * # Arguments
+ *
+ * * builder - A function that will construct the vector. It receives
+ *             as an argument a function that will push an element
+ *             onto the vector being constructed.
+ */
+#[inline(always)]
+pub fn build<A>(builder: &fn(push: &fn(v: A))) -> ~[A] {
+    build_sized(4, builder)
+}
+
+/**
+ * Builds a vector by calling a provided function with an argument
+ * function that pushes an element to the back of a vector.
+ * This version takes an initial size for the vector.
+ *
+ * # Arguments
+ *
+ * * size - An option, maybe containing initial size of the vector to reserve
+ * * builder - A function that will construct the vector. It receives
+ *             as an argument a function that will push an element
+ *             onto the vector being constructed.
+ */
+#[inline(always)]
+pub fn build_sized_opt<A>(size: Option<uint>,
+                          builder: &fn(push: &fn(v: A)))
+                       -> ~[A] {
+    build_sized(size.get_or_default(4), builder)
+}
+
+// Accessors
+
+/// Returns the first element of a vector
+pub fn head<'r,T>(v: &'r [T]) -> &'r T {
+    if v.len() == 0 { fail!("head: empty vector") }
+    &v[0]
+}
+
+/// Returns `Some(x)` where `x` is the first element of the slice `v`,
+/// or `None` if the vector is empty.
+pub fn head_opt<'r,T>(v: &'r [T]) -> Option<&'r T> {
+    if v.len() == 0 { None } else { Some(&v[0]) }
+}
+
+/// Returns a vector containing all but the first element of a slice
+pub fn tail<'r,T>(v: &'r [T]) -> &'r [T] { slice(v, 1, v.len()) }
+
+/// Returns a vector containing all but the first `n` elements of a slice
+pub fn tailn<'r,T>(v: &'r [T], n: uint) -> &'r [T] { slice(v, n, v.len()) }
+
+/// Returns a vector containing all but the last element of a slice
+pub fn init<'r,T>(v: &'r [T]) -> &'r [T] { slice(v, 0, v.len() - 1) }
+
+/// Returns a vector containing all but the last `n' elements of a slice
+pub fn initn<'r,T>(v: &'r [T], n: uint) -> &'r [T] {
+    slice(v, 0, v.len() - n)
+}
+
+/// Returns the last element of the slice `v`, failing if the slice is empty.
+pub fn last<'r,T>(v: &'r [T]) -> &'r T {
+    if v.len() == 0 { fail!("last: empty vector") }
+    &v[v.len() - 1]
+}
+
+/// Returns `Some(x)` where `x` is the last element of the slice `v`, or
+/// `None` if the vector is empty.
+pub fn last_opt<'r,T>(v: &'r [T]) -> Option<&'r T> {
+    if v.len() == 0 { None } else { Some(&v[v.len() - 1]) }
+}
+
+/// Return a slice that points into another slice.
+#[inline(always)]
+pub fn slice<'r,T>(v: &'r [T], start: uint, end: uint) -> &'r [T] {
+    assert!(start <= end);
+    assert!(end <= len(v));
+    do as_imm_buf(v) |p, _len| {
+        unsafe {
+            transmute((ptr::offset(p, start),
+                       (end - start) * sys::nonzero_size_of::<T>()))
+        }
+    }
+}
+
+/// Return a slice that points into another slice.
+#[inline(always)]
+pub fn mut_slice<'r,T>(v: &'r mut [T], start: uint, end: uint)
+                    -> &'r mut [T] {
+    assert!(start <= end);
+    assert!(end <= v.len());
+    do as_mut_buf(v) |p, _len| {
+        unsafe {
+            transmute((ptr::mut_offset(p, start),
+                       (end - start) * sys::nonzero_size_of::<T>()))
+        }
+    }
+}
+
+/// Return a slice that points into another slice.
+#[inline(always)]
+pub fn const_slice<'r,T>(v: &'r const [T], start: uint, end: uint)
+                      -> &'r const [T] {
+    assert!(start <= end);
+    assert!(end <= len(v));
+    do as_const_buf(v) |p, _len| {
+        unsafe {
+            transmute((ptr::const_offset(p, start),
+                       (end - start) * sys::nonzero_size_of::<T>()))
+        }
+    }
+}
+
+/// Copies
+
+/// Split the vector `v` by applying each element against the predicate `f`.
+pub fn split<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[~[T]] {
+    let ln = len(v);
+    if (ln == 0u) { return ~[] }
+
+    let mut start = 0u;
+    let mut result = ~[];
+    while start < ln {
+        match position_between(v, start, ln, f) {
+            None => break,
+            Some(i) => {
+                result.push(slice(v, start, i).to_vec());
+                start = i + 1u;
+            }
+        }
+    }
+    result.push(slice(v, start, ln).to_vec());
+    result
+}
+
+/**
+ * Split the vector `v` by applying each element against the predicate `f` up
+ * to `n` times.
+ */
+pub fn splitn<T:Copy>(v: &[T], n: uint, f: &fn(t: &T) -> bool) -> ~[~[T]] {
+    let ln = len(v);
+    if (ln == 0u) { return ~[] }
+
+    let mut start = 0u;
+    let mut count = n;
+    let mut result = ~[];
+    while start < ln && count > 0u {
+        match position_between(v, start, ln, f) {
+            None => break,
+            Some(i) => {
+                result.push(slice(v, start, i).to_vec());
+                // Make sure to skip the separator.
+                start = i + 1u;
+                count -= 1u;
+            }
+        }
+    }
+    result.push(slice(v, start, ln).to_vec());
+    result
+}
+
+/**
+ * Reverse split the vector `v` by applying each element against the predicate
+ * `f`.
+ */
+pub fn rsplit<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[~[T]] {
+    let ln = len(v);
+    if (ln == 0) { return ~[] }
+
+    let mut end = ln;
+    let mut result = ~[];
+    while end > 0 {
+        match rposition_between(v, 0, end, f) {
+            None => break,
+            Some(i) => {
+                result.push(slice(v, i + 1, end).to_vec());
+                end = i;
+            }
+        }
+    }
+    result.push(slice(v, 0u, end).to_vec());
+    reverse(result);
+    result
+}
+
+/**
+ * Reverse split the vector `v` by applying each element against the predicate
+ * `f` up to `n times.
+ */
+pub fn rsplitn<T:Copy>(v: &[T], n: uint, f: &fn(t: &T) -> bool) -> ~[~[T]] {
+    let ln = len(v);
+    if (ln == 0u) { return ~[] }
+
+    let mut end = ln;
+    let mut count = n;
+    let mut result = ~[];
+    while end > 0u && count > 0u {
+        match rposition_between(v, 0u, end, f) {
+            None => break,
+            Some(i) => {
+                result.push(slice(v, i + 1u, end).to_vec());
+                // Make sure to skip the separator.
+                end = i;
+                count -= 1u;
+            }
+        }
+    }
+    result.push(slice(v, 0u, end).to_vec());
+    reverse(result);
+    result
+}
+
+/**
+ * Partitions a vector into two new vectors: those that satisfies the
+ * predicate, and those that do not.
+ */
+pub fn partition<T>(v: ~[T], f: &fn(&T) -> bool) -> (~[T], ~[T]) {
+    let mut lefts  = ~[];
+    let mut rights = ~[];
+
+    // FIXME (#4355 maybe): using v.consume here crashes
+    // do v.consume |_, elt| {
+    do consume(v) |_, elt| {
+        if f(&elt) {
+            lefts.push(elt);
+        } else {
+            rights.push(elt);
+        }
+    }
+
+    (lefts, rights)
+}
+
+/**
+ * Partitions a vector into two new vectors: those that satisfies the
+ * predicate, and those that do not.
+ */
+pub fn partitioned<T:Copy>(v: &[T], f: &fn(&T) -> bool) -> (~[T], ~[T]) {
+    let mut lefts  = ~[];
+    let mut rights = ~[];
+
+    for each(v) |elt| {
+        if f(elt) {
+            lefts.push(*elt);
+        } else {
+            rights.push(*elt);
+        }
+    }
+
+    (lefts, rights)
+}
+
+// Mutators
+
+/// Removes the first element from a vector and return it
+pub fn shift<T>(v: &mut ~[T]) -> T {
+    unsafe {
+        assert!(!v.is_empty());
+
+        if v.len() == 1 { return v.pop() }
+
+        if v.len() == 2 {
+            let last = v.pop();
+            let first = v.pop();
+            v.push(last);
+            return first;
+        }
+
+        let ln = v.len();
+        let next_ln = v.len() - 1;
+
+        // Save the last element. We're going to overwrite its position
+        let work_elt = v.pop();
+        // We still should have room to work where what last element was
+        assert!(capacity(v) >= ln);
+        // Pretend like we have the original length so we can use
+        // the vector copy_memory to overwrite the hole we just made
+        raw::set_len(&mut *v, ln);
+
+        // Memcopy the head element (the one we want) to the location we just
+        // popped. For the moment it unsafely exists at both the head and last
+        // positions
+        {
+            let first_slice = slice(*v, 0, 1);
+            let last_slice = slice(*v, next_ln, ln);
+            raw::copy_memory(transmute(last_slice), first_slice, 1);
+        }
+
+        // Memcopy everything to the left one element
+        {
+            let init_slice = slice(*v, 0, next_ln);
+            let tail_slice = slice(*v, 1, ln);
+            raw::copy_memory(transmute(init_slice),
+                             tail_slice,
+                             next_ln);
+        }
+
+        // Set the new length. Now the vector is back to normal
+        raw::set_len(&mut *v, next_ln);
+
+        // Swap out the element we want from the end
+        let vp = raw::to_mut_ptr(*v);
+        let vp = ptr::mut_offset(vp, next_ln - 1);
+
+        util::replace_ptr(vp, work_elt)
+    }
+}
+
+/// Prepend an element to the vector
+pub fn unshift<T>(v: &mut ~[T], x: T) {
+    let vv = util::replace(v, ~[x]);
+    v.push_all_move(vv);
+}
+
+/// Insert an element at position i within v, shifting all
+/// elements after position i one position to the right.
+pub fn insert<T>(v: &mut ~[T], i: uint, x: T) {
+    let len = v.len();
+    assert!(i <= len);
+
+    v.push(x);
+    let mut j = len;
+    while j > i {
+        swap(*v, j, j - 1);
+        j -= 1;
+    }
+}
+
+/// Remove and return the element at position i within v, shifting
+/// all elements after position i one position to the left.
+pub fn remove<T>(v: &mut ~[T], i: uint) -> T {
+    let len = v.len();
+    assert!(i < len);
+
+    let mut j = i;
+    while j < len - 1 {
+        swap(*v, j, j + 1);
+        j += 1;
+    }
+    v.pop()
+}
+
+pub fn consume<T>(mut v: ~[T], f: &fn(uint, v: T)) {
+    unsafe {
+        do as_mut_buf(v) |p, ln| {
+            for uint::range(0, ln) |i| {
+                // NB: This unsafe operation counts on init writing 0s to the
+                // holes we create in the vector. That ensures that, if the
+                // iterator fails then we won't try to clean up the consumed
+                // elements during unwinding
+                let x = intrinsics::init();
+                let p = ptr::mut_offset(p, i);
+                f(i, util::replace_ptr(p, x));
+            }
+        }
+
+        raw::set_len(&mut v, 0);
+    }
+}
+
+pub fn consume_reverse<T>(mut v: ~[T], f: &fn(uint, v: T)) {
+    unsafe {
+        do as_mut_buf(v) |p, ln| {
+            let mut i = ln;
+            while i > 0 {
+                i -= 1;
+
+                // NB: This unsafe operation counts on init writing 0s to the
+                // holes we create in the vector. That ensures that, if the
+                // iterator fails then we won't try to clean up the consumed
+                // elements during unwinding
+                let x = intrinsics::init();
+                let p = ptr::mut_offset(p, i);
+                f(i, util::replace_ptr(p, x));
+            }
+        }
+
+        raw::set_len(&mut v, 0);
+    }
+}
+
+/// Remove the last element from a vector and return it
+pub fn pop<T>(v: &mut ~[T]) -> T {
+    let ln = v.len();
+    if ln == 0 {
+        fail!("sorry, cannot vec::pop an empty vector")
+    }
+    let valptr = ptr::to_mut_unsafe_ptr(&mut v[ln - 1u]);
+    unsafe {
+        let val = util::replace_ptr(valptr, intrinsics::init());
+        raw::set_len(v, ln - 1u);
+        val
+    }
+}
+
+/**
+ * Remove an element from anywhere in the vector and return it, replacing it
+ * with the last element. This does not preserve ordering, but is O(1).
+ *
+ * Fails if index >= length.
+ */
+pub fn swap_remove<T>(v: &mut ~[T], index: uint) -> T {
+    let ln = v.len();
+    if index >= ln {
+        fail!("vec::swap_remove - index %u >= length %u", index, ln);
+    }
+    if index < ln - 1 {
+        swap(*v, index, ln - 1);
+    }
+    v.pop()
+}
+
+/// Append an element to a vector
+#[inline(always)]
+pub fn push<T>(v: &mut ~[T], initval: T) {
+    unsafe {
+        let repr: **raw::VecRepr = transmute(&mut *v);
+        let fill = (**repr).unboxed.fill;
+        if (**repr).unboxed.alloc > fill {
+            push_fast(v, initval);
+        }
+        else {
+            push_slow(v, initval);
+        }
+    }
+}
+
+// This doesn't bother to make sure we have space.
+#[inline(always)] // really pretty please
+unsafe fn push_fast<T>(v: &mut ~[T], initval: T) {
+    let repr: **mut raw::VecRepr = transmute(v);
+    let fill = (**repr).unboxed.fill;
+    (**repr).unboxed.fill += sys::nonzero_size_of::<T>();
+    let p = to_unsafe_ptr(&((**repr).unboxed.data));
+    let p = ptr::offset(p, fill) as *mut T;
+    intrinsics::move_val_init(&mut(*p), initval);
+}
+
+#[inline(never)]
+fn push_slow<T>(v: &mut ~[T], initval: T) {
+    let new_len = v.len() + 1;
+    reserve_at_least(&mut *v, new_len);
+    unsafe { push_fast(v, initval) }
+}
+
+#[inline(always)]
+pub fn push_all<T:Copy>(v: &mut ~[T], rhs: &const [T]) {
+    let new_len = v.len() + rhs.len();
+    reserve(&mut *v, new_len);
+
+    for uint::range(0u, rhs.len()) |i| {
+        push(&mut *v, unsafe { raw::get(rhs, i) })
+    }
+}
+
+#[inline(always)]
+pub fn push_all_move<T>(v: &mut ~[T], mut rhs: ~[T]) {
+    let new_len = v.len() + rhs.len();
+    reserve(&mut *v, new_len);
+    unsafe {
+        do as_mut_buf(rhs) |p, len| {
+            for uint::range(0, len) |i| {
+                let x = util::replace_ptr(ptr::mut_offset(p, i),
+                                          intrinsics::uninit());
+                push(&mut *v, x);
+            }
+        }
+        raw::set_len(&mut rhs, 0);
+    }
+}
+
+/// Shorten a vector, dropping excess elements.
+pub fn truncate<T>(v: &mut ~[T], newlen: uint) {
+    do as_mut_buf(*v) |p, oldlen| {
+        assert!(newlen <= oldlen);
+        unsafe {
+            // This loop is optimized out for non-drop types.
+            for uint::range(newlen, oldlen) |i| {
+                util::replace_ptr(ptr::mut_offset(p, i), intrinsics::uninit());
+            }
+        }
+    }
+    unsafe { raw::set_len(&mut *v, newlen); }
+}
+
+/**
+ * Remove consecutive repeated elements from a vector; if the vector is
+ * sorted, this removes all duplicates.
+ */
+pub fn dedup<T:Eq>(v: &mut ~[T]) {
+    unsafe {
+        if v.len() < 1 { return; }
+        let mut last_written = 0, next_to_read = 1;
+        do as_const_buf(*v) |p, ln| {
+            // We have a mutable reference to v, so we can make arbitrary
+            // changes. (cf. push and pop)
+            let p = p as *mut T;
+            // last_written < next_to_read <= ln
+            while next_to_read < ln {
+                // last_written < next_to_read < ln
+                if *ptr::mut_offset(p, next_to_read) ==
+                    *ptr::mut_offset(p, last_written) {
+                    util::replace_ptr(ptr::mut_offset(p, next_to_read),
+                                      intrinsics::uninit());
+                } else {
+                    last_written += 1;
+                    // last_written <= next_to_read < ln
+                    if next_to_read != last_written {
+                        util::swap_ptr(ptr::mut_offset(p, last_written),
+                                       ptr::mut_offset(p, next_to_read));
+                    }
+                }
+                // last_written <= next_to_read < ln
+                next_to_read += 1;
+                // last_written < next_to_read <= ln
+            }
+        }
+        // last_written < next_to_read == ln
+        raw::set_len(v, last_written + 1);
+    }
+}
+
+// Appending
+#[inline(always)]
+pub fn append<T:Copy>(lhs: ~[T], rhs: &const [T]) -> ~[T] {
+    let mut v = lhs;
+    v.push_all(rhs);
+    v
+}
+
+#[inline(always)]
+pub fn append_one<T>(lhs: ~[T], x: T) -> ~[T] {
+    let mut v = lhs;
+    v.push(x);
+    v
+}
+
+/**
+ * Expands a vector in place, initializing the new elements to a given value
+ *
+ * # Arguments
+ *
+ * * v - The vector to grow
+ * * n - The number of elements to add
+ * * initval - The value for the new elements
+ */
+pub fn grow<T:Copy>(v: &mut ~[T], n: uint, initval: &T) {
+    let new_len = v.len() + n;
+    reserve_at_least(&mut *v, new_len);
+    let mut i: uint = 0u;
+
+    while i < n {
+        v.push(*initval);
+        i += 1u;
+    }
+}
+
+/**
+ * Expands a vector in place, initializing the new elements to the result of
+ * a function
+ *
+ * Function `init_op` is called `n` times with the values [0..`n`)
+ *
+ * # Arguments
+ *
+ * * v - The vector to grow
+ * * n - The number of elements to add
+ * * init_op - A function to call to retreive each appended element's
+ *             value
+ */
+pub fn grow_fn<T>(v: &mut ~[T], n: uint, op: old_iter::InitOp<T>) {
+    let new_len = v.len() + n;
+    reserve_at_least(&mut *v, new_len);
+    let mut i: uint = 0u;
+    while i < n {
+        v.push(op(i));
+        i += 1u;
+    }
+}
+
+/**
+ * Sets the value of a vector element at a given index, growing the vector as
+ * needed
+ *
+ * Sets the element at position `index` to `val`. If `index` is past the end
+ * of the vector, expands the vector by replicating `initval` to fill the
+ * intervening space.
+ */
+pub fn grow_set<T:Copy>(v: &mut ~[T], index: uint, initval: &T, val: T) {
+    let l = v.len();
+    if index >= l { grow(&mut *v, index - l + 1u, initval); }
+    v[index] = val;
+}
+
+// Functional utilities
+
+/// Apply a function to each element of a vector and return the results
+pub fn map<T, U>(v: &[T], f: &fn(t: &T) -> U) -> ~[U] {
+    let mut result = with_capacity(len(v));
+    for each(v) |elem| {
+        result.push(f(elem));
+    }
+    result
+}
+
+pub fn map_consume<T, U>(v: ~[T], f: &fn(v: T) -> U) -> ~[U] {
+    let mut result = ~[];
+    do consume(v) |_i, x| {
+        result.push(f(x));
+    }
+    result
+}
+
+/// Apply a function to each element of a vector and return the results
+pub fn mapi<T, U>(v: &[T], f: &fn(uint, t: &T) -> U) -> ~[U] {
+    let mut i = 0;
+    do map(v) |e| {
+        i += 1;
+        f(i - 1, e)
+    }
+}
+
+/**
+ * Apply a function to each element of a vector and return a concatenation
+ * of each result vector
+ */
+pub fn flat_map<T, U>(v: &[T], f: &fn(t: &T) -> ~[U]) -> ~[U] {
+    let mut result = ~[];
+    for each(v) |elem| { result.push_all_move(f(elem)); }
+    result
+}
+
+/**
+ * Apply a function to each pair of elements and return the results.
+ * Equivalent to `map(zip(v0, v1), f)`.
+ */
+pub fn map_zip<T:Copy,U:Copy,V>(v0: &[T], v1: &[U],
+                                  f: &fn(t: &T, v: &U) -> V) -> ~[V] {
+    let v0_len = len(v0);
+    if v0_len != len(v1) { fail!(); }
+    let mut u: ~[V] = ~[];
+    let mut i = 0u;
+    while i < v0_len {
+        u.push(f(&v0[i], &v1[i]));
+        i += 1u;
+    }
+    u
+}
+
+pub fn filter_map<T, U>(
+    v: ~[T],
+    f: &fn(t: T) -> Option<U>) -> ~[U]
+{
+    /*!
+     *
+     * Apply a function to each element of a vector and return the results.
+     * Consumes the input vector.  If function `f` returns `None` then that
+     * element is excluded from the resulting vector.
+     */
+
+    let mut result = ~[];
+    do consume(v) |_, elem| {
+        match f(elem) {
+            None => {}
+            Some(result_elem) => { result.push(result_elem); }
+        }
+    }
+    result
+}
+
+pub fn filter_mapped<T, U: Copy>(
+    v: &[T],
+    f: &fn(t: &T) -> Option<U>) -> ~[U]
+{
+    /*!
+     *
+     * Like `filter_map()`, but operates on a borrowed slice
+     * and does not consume the input.
+     */
+
+    let mut result = ~[];
+    for each(v) |elem| {
+        match f(elem) {
+          None => {/* no-op */ }
+          Some(result_elem) => { result.push(result_elem); }
+        }
+    }
+    result
+}
+
+/**
+ * Construct a new vector from the elements of a vector for which some
+ * predicate holds.
+ *
+ * Apply function `f` to each element of `v` and return a vector containing
+ * only those elements for which `f` returned true.
+ */
+pub fn filter<T>(v: ~[T], f: &fn(t: &T) -> bool) -> ~[T] {
+    let mut result = ~[];
+    // FIXME (#4355 maybe): using v.consume here crashes
+    // do v.consume |_, elem| {
+    do consume(v) |_, elem| {
+        if f(&elem) { result.push(elem); }
+    }
+    result
+}
+
+/**
+ * Construct a new vector from the elements of a vector for which some
+ * predicate holds.
+ *
+ * Apply function `f` to each element of `v` and return a vector containing
+ * only those elements for which `f` returned true.
+ */
+pub fn filtered<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> ~[T] {
+    let mut result = ~[];
+    for each(v) |elem| {
+        if f(elem) { result.push(*elem); }
+    }
+    result
+}
+
+/**
+ * Like `filter()`, but in place.  Preserves order of `v`.  Linear time.
+ */
+pub fn retain<T>(v: &mut ~[T], f: &fn(t: &T) -> bool) {
+    let len = v.len();
+    let mut deleted: uint = 0;
+
+    for uint::range(0, len) |i| {
+        if !f(&v[i]) {
+            deleted += 1;
+        } else if deleted > 0 {
+            swap(*v, i - deleted, i);
+        }
+    }
+
+    if deleted > 0 {
+        v.truncate(len - deleted);
+    }
+}
+
+/**
+ * Concatenate a vector of vectors.
+ *
+ * Flattens a vector of vectors of T into a single vector of T.
+ */
+pub fn concat<T:Copy>(v: &[~[T]]) -> ~[T] {
+    let mut r = ~[];
+    for each(v) |inner| { r.push_all(*inner); }
+    r
+}
+
+/// Concatenate a vector of vectors, placing a given separator between each
+pub fn connect<T:Copy>(v: &[~[T]], sep: &T) -> ~[T] {
+    let mut r: ~[T] = ~[];
+    let mut first = true;
+    for each(v) |inner| {
+        if first { first = false; } else { r.push(*sep); }
+        r.push_all(*inner);
+    }
+    r
+}
+
+/**
+ * Reduces a vector from left to right.
+ *
+ * # Arguments
+ * * `z` - initial accumulator value
+ * * `v` - vector to iterate over
+ * * `p` - a closure to operate on vector elements
+ *
+ * # Examples
+ *
+ * Sum all values in the vector [1, 2, 3]:
+ *
+ * ~~~
+ * vec::foldl(0, [1, 2, 3], |a, b| a + *b);
+ * ~~~
+ *
+ */
+pub fn foldl<'a, T, U>(z: T, v: &'a [U], p: &fn(t: T, u: &'a U) -> T) -> T {
+    let mut accum = z;
+    let mut i = 0;
+    let l = v.len();
+    while i < l {
+        // Use a while loop so that liveness analysis can handle moving
+        // the accumulator.
+        accum = p(accum, &v[i]);
+        i += 1;
+    }
+    accum
+}
+
+/**
+ * Reduces a vector from right to left. Note that the argument order is
+ * reversed compared to `foldl` to reflect the order they are provided to
+ * the closure.
+ *
+ * # Arguments
+ * * `v` - vector to iterate over
+ * * `z` - initial accumulator value
+ * * `p` - a closure to do operate on vector elements
+ *
+ * # Examples
+ *
+ * Sum all values in the vector [1, 2, 3]:
+ *
+ * ~~~
+ * vec::foldr([1, 2, 3], 0, |a, b| a + *b);
+ * ~~~
+ *
+ */
+pub fn foldr<'a, T, U>(v: &'a [T], mut z: U, p: &fn(t: &'a T, u: U) -> U) -> U {
+    let mut i = v.len();
+    while i > 0 {
+        i -= 1;
+        z = p(&v[i], z);
+    }
+    return z;
+}
+
+/**
+ * Return true if a predicate matches any elements
+ *
+ * If the vector contains no elements then false is returned.
+ */
+pub fn any<T>(v: &[T], f: &fn(t: &T) -> bool) -> bool {
+    for each(v) |elem| { if f(elem) { return true; } }
+    false
+}
+
+/**
+ * Return true if a predicate matches any elements in both vectors.
+ *
+ * If the vectors contains no elements then false is returned.
+ */
+pub fn any2<T, U>(v0: &[T], v1: &[U],
+                   f: &fn(a: &T, b: &U) -> bool) -> bool {
+    let v0_len = len(v0);
+    let v1_len = len(v1);
+    let mut i = 0u;
+    while i < v0_len && i < v1_len {
+        if f(&v0[i], &v1[i]) { return true; };
+        i += 1u;
+    }
+    false
+}
+
+/**
+ * Return true if a predicate matches all elements
+ *
+ * If the vector contains no elements then true is returned.
+ */
+pub fn all<T>(v: &[T], f: &fn(t: &T) -> bool) -> bool {
+    for each(v) |elem| { if !f(elem) { return false; } }
+    true
+}
+
+/**
+ * Return true if a predicate matches all elements
+ *
+ * If the vector contains no elements then true is returned.
+ */
+pub fn alli<T>(v: &[T], f: &fn(uint, t: &T) -> bool) -> bool {
+    for eachi(v) |i, elem| { if !f(i, elem) { return false; } }
+    true
+}
+
+/**
+ * Return true if a predicate matches all elements in both vectors.
+ *
+ * If the vectors are not the same size then false is returned.
+ */
+pub fn all2<T, U>(v0: &[T], v1: &[U],
+                   f: &fn(t: &T, u: &U) -> bool) -> bool {
+    let v0_len = len(v0);
+    if v0_len != len(v1) { return false; }
+    let mut i = 0u;
+    while i < v0_len { if !f(&v0[i], &v1[i]) { return false; }; i += 1u; }
+    true
+}
+
+/// Return true if a vector contains an element with the given value
+pub fn contains<T:Eq>(v: &[T], x: &T) -> bool {
+    for each(v) |elt| { if *x == *elt { return true; } }
+    false
+}
+
+/// Returns the number of elements that are equal to a given value
+pub fn count<T:Eq>(v: &[T], x: &T) -> uint {
+    let mut cnt = 0u;
+    for each(v) |elt| { if *x == *elt { cnt += 1u; } }
+    cnt
+}
+
+/**
+ * Search for the first element that matches a given predicate
+ *
+ * Apply function `f` to each element of `v`, starting from the first.
+ * When function `f` returns true then an option containing the element
+ * is returned. If `f` matches no elements then none is returned.
+ */
+pub fn find<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> Option<T> {
+    find_between(v, 0u, len(v), f)
+}
+
+/**
+ * Search for the first element that matches a given predicate within a range
+ *
+ * Apply function `f` to each element of `v` within the range
+ * [`start`, `end`). When function `f` returns true then an option containing
+ * the element is returned. If `f` matches no elements then none is returned.
+ */
+pub fn find_between<T:Copy>(v: &[T], start: uint, end: uint,
+                      f: &fn(t: &T) -> bool) -> Option<T> {
+    position_between(v, start, end, f).map(|i| v[*i])
+}
+
+/**
+ * Search for the last element that matches a given predicate
+ *
+ * Apply function `f` to each element of `v` in reverse order. When function
+ * `f` returns true then an option containing the element is returned. If `f`
+ * matches no elements then none is returned.
+ */
+pub fn rfind<T:Copy>(v: &[T], f: &fn(t: &T) -> bool) -> Option<T> {
+    rfind_between(v, 0u, len(v), f)
+}
+
+/**
+ * Search for the last element that matches a given predicate within a range
+ *
+ * Apply function `f` to each element of `v` in reverse order within the range
+ * [`start`, `end`). When function `f` returns true then an option containing
+ * the element is returned. If `f` matches no elements then none is return.
+ */
+pub fn rfind_between<T:Copy>(v: &[T],
+                             start: uint,
+                             end: uint,
+                             f: &fn(t: &T) -> bool)
+                          -> Option<T> {
+    rposition_between(v, start, end, f).map(|i| v[*i])
+}
+
+/// Find the first index containing a matching value
+pub fn position_elem<T:Eq>(v: &[T], x: &T) -> Option<uint> {
+    position(v, |y| *x == *y)
+}
+
+/**
+ * Find the first index matching some predicate
+ *
+ * Apply function `f` to each element of `v`.  When function `f` returns true
+ * then an option containing the index is returned. If `f` matches no elements
+ * then none is returned.
+ */
+pub fn position<T>(v: &[T], f: &fn(t: &T) -> bool) -> Option<uint> {
+    position_between(v, 0u, len(v), f)
+}
+
+/**
+ * Find the first index matching some predicate within a range
+ *
+ * Apply function `f` to each element of `v` between the range
+ * [`start`, `end`). When function `f` returns true then an option containing
+ * the index is returned. If `f` matches no elements then none is returned.
+ */
+pub fn position_between<T>(v: &[T],
+                           start: uint,
+                           end: uint,
+                           f: &fn(t: &T) -> bool)
+                        -> Option<uint> {
+    assert!(start <= end);
+    assert!(end <= len(v));
+    let mut i = start;
+    while i < end { if f(&v[i]) { return Some::<uint>(i); } i += 1u; }
+    None
+}
+
+/// Find the last index containing a matching value
+pub fn rposition_elem<T:Eq>(v: &[T], x: &T) -> Option<uint> {
+    rposition(v, |y| *x == *y)
+}
+
+/**
+ * Find the last index matching some predicate
+ *
+ * Apply function `f` to each element of `v` in reverse order.  When function
+ * `f` returns true then an option containing the index is returned. If `f`
+ * matches no elements then none is returned.
+ */
+pub fn rposition<T>(v: &[T], f: &fn(t: &T) -> bool) -> Option<uint> {
+    rposition_between(v, 0u, len(v), f)
+}
+
+/**
+ * Find the last index matching some predicate within a range
+ *
+ * Apply function `f` to each element of `v` in reverse order between the
+ * range [`start`, `end`). When function `f` returns true then an option
+ * containing the index is returned. If `f` matches no elements then none is
+ * returned.
+ */
+pub fn rposition_between<T>(v: &[T], start: uint, end: uint,
+                             f: &fn(t: &T) -> bool) -> Option<uint> {
+    assert!(start <= end);
+    assert!(end <= len(v));
+    let mut i = end;
+    while i > start {
+        if f(&v[i - 1u]) { return Some::<uint>(i - 1u); }
+        i -= 1u;
+    }
+    None
+}
+
+
+
+/**
+ * Binary search a sorted vector with a comparator function.
+ *
+ * The comparator should implement an order consistent with the sort
+ * order of the underlying vector, returning an order code that indicates
+ * whether its argument is `Less`, `Equal` or `Greater` the desired target.
+ *
+ * Returns the index where the comparator returned `Equal`, or `None` if
+ * not found.
+ */
+pub fn bsearch<T>(v: &[T], f: &fn(&T) -> Ordering) -> Option<uint> {
+    let mut base : uint = 0;
+    let mut lim : uint = v.len();
+
+    while lim != 0 {
+        let ix = base + (lim >> 1);
+        match f(&v[ix]) {
+            Equal => return Some(ix),
+            Less => {
+                base = ix + 1;
+                lim -= 1;
+            }
+            Greater => ()
+        }
+        lim >>= 1;
+    }
+    return None;
+}
+
+/**
+ * Binary search a sorted vector for a given element.
+ *
+ * Returns the index of the element or None if not found.
+ */
+pub fn bsearch_elem<T:TotalOrd>(v: &[T], x: &T) -> Option<uint> {
+    bsearch(v, |p| p.cmp(x))
+}
+
+// FIXME: if issue #586 gets implemented, could have a postcondition
+// saying the two result lists have the same length -- or, could
+// return a nominal record with a constraint saying that, instead of
+// returning a tuple (contingent on issue #869)
+/**
+ * Convert a vector of pairs into a pair of vectors, by reference. As unzip().
+ */
+pub fn unzip_slice<T:Copy,U:Copy>(v: &[(T, U)]) -> (~[T], ~[U]) {
+    let mut ts = ~[], us = ~[];
+    for each(v) |p| {
+        let (t, u) = *p;
+        ts.push(t);
+        us.push(u);
+    }
+    (ts, us)
+}
+
+/**
+ * Convert a vector of pairs into a pair of vectors.
+ *
+ * Returns a tuple containing two vectors where the i-th element of the first
+ * vector contains the first element of the i-th tuple of the input vector,
+ * and the i-th element of the second vector contains the second element
+ * of the i-th tuple of the input vector.
+ */
+pub fn unzip<T,U>(v: ~[(T, U)]) -> (~[T], ~[U]) {
+    let mut ts = ~[], us = ~[];
+    do consume(v) |_i, p| {
+        let (t, u) = p;
+        ts.push(t);
+        us.push(u);
+    }
+    (ts, us)
+}
+
+/**
+ * Convert two vectors to a vector of pairs, by reference. As zip().
+ */
+pub fn zip_slice<T:Copy,U:Copy>(v: &const [T], u: &const [U])
+        -> ~[(T, U)] {
+    let mut zipped = ~[];
+    let sz = len(v);
+    let mut i = 0u;
+    assert_eq!(sz, len(u));
+    while i < sz {
+        zipped.push((v[i], u[i]));
+        i += 1u;
+    }
+    zipped
+}
+
+/**
+ * Convert two vectors to a vector of pairs.
+ *
+ * Returns a vector of tuples, where the i-th tuple contains contains the
+ * i-th elements from each of the input vectors.
+ */
+pub fn zip<T, U>(mut v: ~[T], mut u: ~[U]) -> ~[(T, U)] {
+    let mut i = len(v);
+    assert_eq!(i, len(u));
+    let mut w = with_capacity(i);
+    while i > 0 {
+        w.push((v.pop(),u.pop()));
+        i -= 1;
+    }
+    reverse(w);
+    w
+}
+
+/**
+ * Swaps two elements in a vector
+ *
+ * # Arguments
+ *
+ * * v  The input vector
+ * * a - The index of the first element
+ * * b - The index of the second element
+ */
+#[inline(always)]
+pub fn swap<T>(v: &mut [T], a: uint, b: uint) {
+    unsafe {
+        // Can't take two mutable loans from one vector, so instead just cast
+        // them to their raw pointers to do the swap
+        let pa: *mut T = ptr::to_mut_unsafe_ptr(&mut v[a]);
+        let pb: *mut T = ptr::to_mut_unsafe_ptr(&mut v[b]);
+        util::swap_ptr(pa, pb);
+    }
+}
+
+/// Reverse the order of elements in a vector, in place
+pub fn reverse<T>(v: &mut [T]) {
+    let mut i: uint = 0;
+    let ln = len::<T>(v);
+    while i < ln / 2 {
+        swap(v, i, ln - i - 1);
+        i += 1;
+    }
+}
+
+/**
+ * Reverse part of a vector in place.
+ *
+ * Reverse the elements in the vector between `start` and `end - 1`.
+ *
+ * If either start or end do not represent valid positions in the vector, the
+ * vector is returned unchanged.
+ *
+ * # Arguments
+ *
+ * * `v` - The mutable vector to be modified
+ *
+ * * `start` - Index of the first element of the slice
+ *
+ * * `end` - Index one past the final element to be reversed.
+ *
+ * # Example
+ *
+ * Assume a mutable vector `v` contains `[1,2,3,4,5]`. After the call:
+ *
+ * ~~~
+ *
+ * reverse_part(v, 1, 4);
+ *
+ * ~~~
+ *
+ * `v` now contains `[1,4,3,2,5]`.
+ */
+pub fn reverse_part<T>(v: &mut [T], start: uint, end : uint) {
+    let sz = v.len();
+    if start >= sz || end > sz { return; }
+    let mut i = start;
+    let mut j = end - 1;
+    while i < j {
+        vec::swap(v, i, j);
+        i += 1;
+        j -= 1;
+    }
+}
+
+/// Returns a vector with the order of elements reversed
+pub fn reversed<T:Copy>(v: &const [T]) -> ~[T] {
+    let mut rs: ~[T] = ~[];
+    let mut i = len::<T>(v);
+    if i == 0 { return (rs); } else { i -= 1; }
+    while i != 0 { rs.push(v[i]); i -= 1; }
+    rs.push(v[0]);
+    rs
+}
+
+/**
+ * Iterates over a vector, yielding each element to a closure.
+ *
+ * # Arguments
+ *
+ * * `v` - A vector, to be iterated over
+ * * `f` - A closure to do the iterating. Within this closure, return true to
+ * * continue iterating, false to break.
+ *
+ * # Examples
+ * ~~~
+ * [1,2,3].each(|&i| {
+ *     io::println(int::str(i));
+ *     true
+ * });
+ * ~~~
+ *
+ * ~~~
+ * [1,2,3,4,5].each(|&i| {
+ *     if i < 4 {
+ *         io::println(int::str(i));
+ *         true
+ *     }
+ *     else {
+ *         false
+ *     }
+ * });
+ * ~~~
+ *
+ * You probably will want to use each with a `for`/`do` expression, depending
+ * on your iteration needs:
+ *
+ * ~~~
+ * for [1,2,3].each |&i| {
+ *     io::println(int::str(i));
+ * }
+ * ~~~
+ */
+#[inline(always)]
+pub fn _each<'r,T>(v: &'r [T], f: &fn(&'r T) -> bool) -> bool {
+    //             ^^^^
+    // NB---this CANNOT be &const [T]!  The reason
+    // is that you are passing it to `f()` using
+    // an immutable.
+
+    let mut broke = false;
+    do as_imm_buf(v) |p, n| {
+        let mut n = n;
+        let mut p = p;
+        while n > 0u {
+            unsafe {
+                let q = cast::copy_lifetime_vec(v, &*p);
+                if !f(q) { break; }
+                p = ptr::offset(p, 1u);
+            }
+            n -= 1u;
+        }
+        broke = n > 0;
+    }
+    return true;
+}
+
+pub fn each<'r,T>(v: &'r [T], f: &fn(&'r T) -> bool) -> bool { _each(v, f) }
+
+/// Like `each()`, but for the case where you have
+/// a vector with mutable contents and you would like
+/// to mutate the contents as you iterate.
+#[inline(always)]
+pub fn _each_mut<'r,T>(v: &'r mut [T], f: &fn(elem: &'r mut T) -> bool) -> bool {
+    let mut broke = false;
+    do as_mut_buf(v) |p, n| {
+        let mut n = n;
+        let mut p = p;
+        while n > 0 {
+            unsafe {
+                let q: &'r mut T = cast::transmute_mut_region(&mut *p);
+                if !f(q) { break; }
+                p = p.offset(1);
+            }
+            n -= 1;
+        }
+        broke = n > 0;
+    }
+    return broke;
+}
+
+pub fn each_mut<'r,T>(v: &'r mut [T], f: &fn(elem: &'r mut T) -> bool) -> bool {
+    _each_mut(v, f)
+}
+
+/// Like `each()`, but for the case where you have a vector that *may or may
+/// not* have mutable contents.
+#[inline(always)]
+pub fn _each_const<T>(v: &const [T], f: &fn(elem: &const T) -> bool) -> bool {
+    let mut i = 0;
+    let n = v.len();
+    while i < n {
+        if !f(&const v[i]) {
+            return false;
+        }
+        i += 1;
+    }
+    return true;
+}
+
+pub fn each_const<t>(v: &const [t], f: &fn(elem: &const t) -> bool) -> bool {
+    _each_const(v, f)
+}
+
+/**
+ * Iterates over a vector's elements and indices
+ *
+ * Return true to continue, false to break.
+ */
+#[inline(always)]
+pub fn _eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) -> bool {
+    let mut i = 0;
+    for each(v) |p| {
+        if !f(i, p) { return false; }
+        i += 1;
+    }
+    return true;
+}
+
+pub fn eachi<'r,T>(v: &'r [T], f: &fn(uint, v: &'r T) -> bool) -> bool {
+    _eachi(v, f)
+}
+
+/**
+ * Iterates over a mutable vector's elements and indices
+ *
+ * Return true to continue, false to break.
+ */
+#[inline(always)]
+pub fn _eachi_mut<'r,T>(v: &'r mut [T],
+                        f: &fn(uint, v: &'r mut T) -> bool) -> bool {
+    let mut i = 0;
+    for each_mut(v) |p| {
+        if !f(i, p) {
+            return false;
+        }
+        i += 1;
+    }
+    return true;
+}
+
+pub fn eachi_mut<'r,T>(v: &'r mut [T],
+                       f: &fn(uint, v: &'r mut T) -> bool) -> bool {
+    _eachi_mut(v, f)
+}
+
+/**
+ * Iterates over a vector's elements in reverse
+ *
+ * Return true to continue, false to break.
+ */
+#[inline(always)]
+pub fn _each_reverse<'r,T>(v: &'r [T], blk: &fn(v: &'r T) -> bool) -> bool {
+    _eachi_reverse(v, |_i, v| blk(v))
+}
+
+pub fn each_reverse<'r,T>(v: &'r [T], blk: &fn(v: &'r T) -> bool) -> bool {
+    _each_reverse(v, blk)
+}
+
+/**
+ * Iterates over a vector's elements and indices in reverse
+ *
+ * Return true to continue, false to break.
+ */
+#[inline(always)]
+pub fn _eachi_reverse<'r,T>(v: &'r [T],
+                            blk: &fn(i: uint, v: &'r T) -> bool) -> bool {
+    let mut i = v.len();
+    while i > 0 {
+        i -= 1;
+        if !blk(i, &v[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+pub fn eachi_reverse<'r,T>(v: &'r [T],
+                           blk: &fn(i: uint, v: &'r T) -> bool) -> bool {
+    _eachi_reverse(v, blk)
+}
+
+/**
+ * Iterates over two vectors simultaneously
+ *
+ * # Failure
+ *
+ * Both vectors must have the same length
+ */
+#[inline]
+pub fn _each2<U, T>(v1: &[U], v2: &[T], f: &fn(u: &U, t: &T) -> bool) -> bool {
+    assert_eq!(v1.len(), v2.len());
+    for uint::range(0u, v1.len()) |i| {
+        if !f(&v1[i], &v2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+pub fn each2<U, T>(v1: &[U], v2: &[T], f: &fn(u: &U, t: &T) -> bool) -> bool {
+    _each2(v1, v2, f)
+}
+
+/**
+ *
+ * Iterates over two vector with mutable.
+ *
+ * # Failure
+ *
+ * Both vectors must have the same length
+ */
+#[inline]
+pub fn _each2_mut<U, T>(v1: &mut [U], v2: &mut [T], f: &fn(u: &mut U, t: &mut T) -> bool) -> bool {
+    assert_eq!(v1.len(), v2.len());
+    for uint::range(0u, v1.len()) |i| {
+        if !f(&mut v1[i], &mut v2[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+pub fn each2_mut<U, T>(v1: &mut [U], v2: &mut [T], f: &fn(u: &mut U, t: &mut T) -> bool) -> bool {
+    _each2_mut(v1, v2, f)
+}
+
+/**
+ * Iterate over all permutations of vector `v`.
+ *
+ * Permutations are produced in lexicographic order with respect to the order
+ * of elements in `v` (so if `v` is sorted then the permutations are
+ * lexicographically sorted).
+ *
+ * The total number of permutations produced is `len(v)!`.  If `v` contains
+ * repeated elements, then some permutations are repeated.
+ *
+ * See [Algorithms to generate
+ * permutations](http://en.wikipedia.org/wiki/Permutation).
+ *
+ *  # Arguments
+ *
+ *  * `values` - A vector of values from which the permutations are
+ *  chosen
+ *
+ *  * `fun` - The function to iterate over the combinations
+ */
+pub fn each_permutation<T:Copy>(values: &[T], fun: &fn(perm : &[T]) -> bool) -> bool {
+    let length = values.len();
+    let mut permutation = vec::from_fn(length, |i| values[i]);
+    if length <= 1 {
+        fun(permutation);
+        return true;
+    }
+    let mut indices = vec::from_fn(length, |i| i);
+    loop {
+        if !fun(permutation) { return true; }
+        // find largest k such that indices[k] < indices[k+1]
+        // if no such k exists, all permutations have been generated
+        let mut k = length - 2;
+        while k > 0 && indices[k] >= indices[k+1] {
+            k -= 1;
+        }
+        if k == 0 && indices[0] > indices[1] { return true; }
+        // find largest l such that indices[k] < indices[l]
+        // k+1 is guaranteed to be such
+        let mut l = length - 1;
+        while indices[k] >= indices[l] {
+            l -= 1;
+        }
+        // swap indices[k] and indices[l]; sort indices[k+1..]
+        // (they're just reversed)
+        vec::swap(indices, k, l);
+        reverse_part(indices, k+1, length);
+        // fixup permutation based on indices
+        for uint::range(k, length) |i| {
+            permutation[i] = values[indices[i]];
+        }
+    }
+}
+
+/**
+ * Iterate over all contiguous windows of length `n` of the vector `v`.
+ *
+ * # Example
+ *
+ * Print the adjacent pairs of a vector (i.e. `[1,2]`, `[2,3]`, `[3,4]`)
+ *
+ * ~~~
+ * for windowed(2, &[1,2,3,4]) |v| {
+ *     io::println(fmt!("%?", v));
+ * }
+ * ~~~
+ *
+ */
+pub fn windowed<'r, T>(n: uint, v: &'r [T], it: &fn(&'r [T]) -> bool) -> bool {
+    assert!(1u <= n);
+    if n > v.len() { return true; }
+    for uint::range(0, v.len() - n + 1) |i| {
+        if !it(v.slice(i, i + n)) { return false; }
+    }
+    return true;
+}
+
+/**
+ * Work with the buffer of a vector.
+ *
+ * Allows for unsafe manipulation of vector contents, which is useful for
+ * foreign interop.
+ */
+#[inline(always)]
+pub fn as_imm_buf<T,U>(s: &[T],
+                       /* NB---this CANNOT be const, see below */
+                       f: &fn(*T, uint) -> U) -> U {
+
+    // NB---Do not change the type of s to `&const [T]`.  This is
+    // unsound.  The reason is that we are going to create immutable pointers
+    // into `s` and pass them to `f()`, but in fact they are potentially
+    // pointing at *mutable memory*.  Use `as_const_buf` or `as_mut_buf`
+    // instead!
+
+    unsafe {
+        let v : *(*T,uint) = transmute(&s);
+        let (buf,len) = *v;
+        f(buf, len / sys::nonzero_size_of::<T>())
+    }
+}
+
+/// Similar to `as_imm_buf` but passing a `*const T`
+#[inline(always)]
+pub fn as_const_buf<T,U>(s: &const [T], f: &fn(*const T, uint) -> U) -> U {
+    unsafe {
+        let v : *(*const T,uint) = transmute(&s);
+        let (buf,len) = *v;
+        f(buf, len / sys::nonzero_size_of::<T>())
+    }
+}
+
+/// Similar to `as_imm_buf` but passing a `*mut T`
+#[inline(always)]
+pub fn as_mut_buf<T,U>(s: &mut [T], f: &fn(*mut T, uint) -> U) -> U {
+    unsafe {
+        let v : *(*mut T,uint) = transmute(&s);
+        let (buf,len) = *v;
+        f(buf, len / sys::nonzero_size_of::<T>())
+    }
+}
+
+// Equality
+
+fn eq<T: Eq>(a: &[T], b: &[T]) -> bool {
+    let (a_len, b_len) = (a.len(), b.len());
+    if a_len != b_len { return false; }
+
+    let mut i = 0;
+    while i < a_len {
+        if a[i] != b[i] { return false; }
+        i += 1;
+    }
+    true
+}
+
+fn equals<T: TotalEq>(a: &[T], b: &[T]) -> bool {
+    let (a_len, b_len) = (a.len(), b.len());
+    if a_len != b_len { return false; }
+
+    let mut i = 0;
+    while i < a_len {
+        if !a[i].equals(&b[i]) { return false; }
+        i += 1;
+    }
+    true
+}
+
+#[cfg(not(test))]
+impl<'self,T:Eq> Eq for &'self [T] {
+    #[inline(always)]
+    fn eq(&self, other: & &'self [T]) -> bool { eq(*self, *other) }
+    #[inline(always)]
+    fn ne(&self, other: & &'self [T]) -> bool { !self.eq(other) }
+}
+
+#[cfg(not(test))]
+impl<T:Eq> Eq for ~[T] {
+    #[inline(always)]
+    fn eq(&self, other: &~[T]) -> bool { eq(*self, *other) }
+    #[inline(always)]
+    fn ne(&self, other: &~[T]) -> bool { !self.eq(other) }
+}
+
+#[cfg(not(test))]
+impl<T:Eq> Eq for @[T] {
+    #[inline(always)]
+    fn eq(&self, other: &@[T]) -> bool { eq(*self, *other) }
+    #[inline(always)]
+    fn ne(&self, other: &@[T]) -> bool { !self.eq(other) }
+}
+
+#[cfg(not(test))]
+impl<'self,T:TotalEq> TotalEq for &'self [T] {
+    #[inline(always)]
+    fn equals(&self, other: & &'self [T]) -> bool { equals(*self, *other) }
+}
+
+#[cfg(not(test))]
+impl<T:TotalEq> TotalEq for ~[T] {
+    #[inline(always)]
+    fn equals(&self, other: &~[T]) -> bool { equals(*self, *other) }
+}
+
+#[cfg(not(test))]
+impl<T:TotalEq> TotalEq for @[T] {
+    #[inline(always)]
+    fn equals(&self, other: &@[T]) -> bool { equals(*self, *other) }
+}
+
+#[cfg(not(test))]
+impl<'self,T:Eq> Equiv<~[T]> for &'self [T] {
+    #[inline(always)]
+    fn equiv(&self, other: &~[T]) -> bool { eq(*self, *other) }
+}
+
+// Lexicographical comparison
+
+fn cmp<T: TotalOrd>(a: &[T], b: &[T]) -> Ordering {
+    let low = uint::min(a.len(), b.len());
+
+    for uint::range(0, low) |idx| {
+        match a[idx].cmp(&b[idx]) {
+          Greater => return Greater,
+          Less => return Less,
+          Equal => ()
+        }
+    }
+
+    a.len().cmp(&b.len())
+}
+
+#[cfg(not(test))]
+impl<'self,T:TotalOrd> TotalOrd for &'self [T] {
+    #[inline(always)]
+    fn cmp(&self, other: & &'self [T]) -> Ordering { cmp(*self, *other) }
+}
+
+#[cfg(not(test))]
+impl<T: TotalOrd> TotalOrd for ~[T] {
+    #[inline(always)]
+    fn cmp(&self, other: &~[T]) -> Ordering { cmp(*self, *other) }
+}
+
+#[cfg(not(test))]
+impl<T: TotalOrd> TotalOrd for @[T] {
+    #[inline(always)]
+    fn cmp(&self, other: &@[T]) -> Ordering { cmp(*self, *other) }
+}
+
+fn lt<T:Ord>(a: &[T], b: &[T]) -> bool {
+    let (a_len, b_len) = (a.len(), b.len());
+    let end = uint::min(a_len, b_len);
+
+    let mut i = 0;
+    while i < end {
+        let (c_a, c_b) = (&a[i], &b[i]);
+        if *c_a < *c_b { return true; }
+        if *c_a > *c_b { return false; }
+        i += 1;
+    }
+
+    a_len < b_len
+}
+
+fn le<T:Ord>(a: &[T], b: &[T]) -> bool { !lt(b, a) }
+fn ge<T:Ord>(a: &[T], b: &[T]) -> bool { !lt(a, b) }
+fn gt<T:Ord>(a: &[T], b: &[T]) -> bool { lt(b, a)  }
+
+#[cfg(not(test))]
+impl<'self,T:Ord> Ord for &'self [T] {
+    #[inline(always)]
+    fn lt(&self, other: & &'self [T]) -> bool { lt((*self), (*other)) }
+    #[inline(always)]
+    fn le(&self, other: & &'self [T]) -> bool { le((*self), (*other)) }
+    #[inline(always)]
+    fn ge(&self, other: & &'self [T]) -> bool { ge((*self), (*other)) }
+    #[inline(always)]
+    fn gt(&self, other: & &'self [T]) -> bool { gt((*self), (*other)) }
+}
+
+#[cfg(not(test))]
+impl<T:Ord> Ord for ~[T] {
+    #[inline(always)]
+    fn lt(&self, other: &~[T]) -> bool { lt((*self), (*other)) }
+    #[inline(always)]
+    fn le(&self, other: &~[T]) -> bool { le((*self), (*other)) }
+    #[inline(always)]
+    fn ge(&self, other: &~[T]) -> bool { ge((*self), (*other)) }
+    #[inline(always)]
+    fn gt(&self, other: &~[T]) -> bool { gt((*self), (*other)) }
+}
+
+#[cfg(not(test))]
+impl<T:Ord> Ord for @[T] {
+    #[inline(always)]
+    fn lt(&self, other: &@[T]) -> bool { lt((*self), (*other)) }
+    #[inline(always)]
+    fn le(&self, other: &@[T]) -> bool { le((*self), (*other)) }
+    #[inline(always)]
+    fn ge(&self, other: &@[T]) -> bool { ge((*self), (*other)) }
+    #[inline(always)]
+    fn gt(&self, other: &@[T]) -> bool { gt((*self), (*other)) }
+}
+
+#[cfg(not(test))]
+pub mod traits {
+    use kinds::Copy;
+    use ops::Add;
+    use vec::append;
+
+    impl<'self,T:Copy> Add<&'self const [T],~[T]> for ~[T] {
+        #[inline(always)]
+        fn add(&self, rhs: & &'self const [T]) -> ~[T] {
+            append(copy *self, (*rhs))
+        }
+    }
+}
+
+impl<'self,T> Container for &'self const [T] {
+    /// Returns true if a vector contains no elements
+    #[inline]
+    fn is_empty(&const self) -> bool { is_empty(*self) }
+
+    /// Returns the length of a vector
+    #[inline]
+    fn len(&const self) -> uint { len(*self) }
+}
+
+pub trait CopyableVector<T> {
+    fn to_owned(&self) -> ~[T];
+}
+
+/// Extension methods for vectors
+impl<'self,T:Copy> CopyableVector<T> for &'self [T] {
+    /// Returns a copy of `v`.
+    #[inline]
+    fn to_owned(&self) -> ~[T] {
+        let mut result = ~[];
+        reserve(&mut result, self.len());
+        for self.each |e| {
+            result.push(copy *e);
+        }
+        result
+
+    }
+}
+
+pub trait ImmutableVector<'self, T> {
+    fn slice(&self, start: uint, end: uint) -> &'self [T];
+    fn iter(self) -> VecIterator<'self, T>;
+    fn head(&self) -> &'self T;
+    fn head_opt(&self) -> Option<&'self T>;
+    fn tail(&self) -> &'self [T];
+    fn tailn(&self, n: uint) -> &'self [T];
+    fn init(&self) -> &'self [T];
+    fn initn(&self, n: uint) -> &'self [T];
+    fn last(&self) -> &'self T;
+    fn last_opt(&self) -> Option<&'self T>;
+    fn position(&self, f: &fn(t: &T) -> bool) -> Option<uint>;
+    fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint>;
+    fn each_reverse(&self, blk: &fn(&T) -> bool) -> bool;
+    fn eachi_reverse(&self, blk: &fn(uint, &T) -> bool) -> bool;
+    fn foldr<'a, U>(&'a self, z: U, p: &fn(t: &'a T, u: U) -> U) -> U;
+    fn map<U>(&self, f: &fn(t: &T) -> U) -> ~[U];
+    fn mapi<U>(&self, f: &fn(uint, t: &T) -> U) -> ~[U];
+    fn map_r<U>(&self, f: &fn(x: &T) -> U) -> ~[U];
+    fn alli(&self, f: &fn(uint, t: &T) -> bool) -> bool;
+    fn flat_map<U>(&self, f: &fn(t: &T) -> ~[U]) -> ~[U];
+    fn filter_mapped<U:Copy>(&self, f: &fn(t: &T) -> Option<U>) -> ~[U];
+    unsafe fn unsafe_ref(&self, index: uint) -> *T;
+}
+
+/// Extension methods for vectors
+impl<'self,T> ImmutableVector<'self, T> for &'self [T] {
+    /// Return a slice that points into another slice.
+    #[inline]
+    fn slice(&self, start: uint, end: uint) -> &'self [T] {
+        slice(*self, start, end)
+    }
+
+    #[inline]
+    fn iter(self) -> VecIterator<'self, T> {
+        unsafe {
+            let p = vec::raw::to_ptr(self);
+            VecIterator{ptr: p, end: p.offset(self.len()),
+                        lifetime: cast::transmute(p)}
+        }
+    }
+
+    /// Returns the first element of a vector, failing if the vector is empty.
+    #[inline]
+    fn head(&self) -> &'self T { head(*self) }
+
+    /// Returns the first element of a vector
+    #[inline]
+    fn head_opt(&self) -> Option<&'self T> { head_opt(*self) }
+
+    /// Returns all but the first element of a vector
+    #[inline]
+    fn tail(&self) -> &'self [T] { tail(*self) }
+
+    /// Returns all but the first `n' elements of a vector
+    #[inline]
+    fn tailn(&self, n: uint) -> &'self [T] { tailn(*self, n) }
+
+    /// Returns all but the last elemnt of a vector
+    #[inline]
+    fn init(&self) -> &'self [T] { init(*self) }
+
+    /// Returns all but the last `n' elemnts of a vector
+    #[inline]
+    fn initn(&self, n: uint) -> &'self [T] { initn(*self, n) }
+
+    /// Returns the last element of a `v`, failing if the vector is empty.
+    #[inline]
+    fn last(&self) -> &'self T { last(*self) }
+
+    /// Returns the last element of a `v`, failing if the vector is empty.
+    #[inline]
+    fn last_opt(&self) -> Option<&'self T> { last_opt(*self) }
+
+    /**
+     * Find the first index matching some predicate
+     *
+     * Apply function `f` to each element of `v`.  When function `f` returns
+     * true then an option containing the index is returned. If `f` matches no
+     * elements then none is returned.
+     */
+    #[inline]
+    fn position(&self, f: &fn(t: &T) -> bool) -> Option<uint> {
+        position(*self, f)
+    }
+
+    /**
+     * Find the last index matching some predicate
+     *
+     * Apply function `f` to each element of `v` in reverse order.  When
+     * function `f` returns true then an option containing the index is
+     * returned. If `f` matches no elements then none is returned.
+     */
+    #[inline]
+    fn rposition(&self, f: &fn(t: &T) -> bool) -> Option<uint> {
+        rposition(*self, f)
+    }
+
+    /// Iterates over a vector's elements in reverse.
+    #[inline]
+    fn each_reverse(&self, blk: &fn(&T) -> bool) -> bool {
+        each_reverse(*self, blk)
+    }
+
+    /// Iterates over a vector's elements and indices in reverse.
+    #[inline]
+    fn eachi_reverse(&self, blk: &fn(uint, &T) -> bool) -> bool {
+        eachi_reverse(*self, blk)
+    }
+
+    /// Reduce a vector from right to left
+    #[inline]
+    fn foldr<'a, U>(&'a self, z: U, p: &fn(t: &'a T, u: U) -> U) -> U {
+        foldr(*self, z, p)
+    }
+
+    /// Apply a function to each element of a vector and return the results
+    #[inline]
+    fn map<U>(&self, f: &fn(t: &T) -> U) -> ~[U] { map(*self, f) }
+
+    /**
+     * Apply a function to the index and value of each element in the vector
+     * and return the results
+     */
+    fn mapi<U>(&self, f: &fn(uint, t: &T) -> U) -> ~[U] {
+        mapi(*self, f)
+    }
+
+    #[inline]
+    fn map_r<U>(&self, f: &fn(x: &T) -> U) -> ~[U] {
+        let mut r = ~[];
+        let mut i = 0;
+        while i < self.len() {
+            r.push(f(&self[i]));
+            i += 1;
+        }
+        r
+    }
+
+    /**
+     * Returns true if the function returns true for all elements.
+     *
+     *     If the vector is empty, true is returned.
+     */
+    fn alli(&self, f: &fn(uint, t: &T) -> bool) -> bool {
+        alli(*self, f)
+    }
+    /**
+     * Apply a function to each element of a vector and return a concatenation
+     * of each result vector
+     */
+    #[inline]
+    fn flat_map<U>(&self, f: &fn(t: &T) -> ~[U]) -> ~[U] {
+        flat_map(*self, f)
+    }
+    /**
+     * Apply a function to each element of a vector and return the results
+     *
+     * If function `f` returns `none` then that element is excluded from
+     * the resulting vector.
+     */
+    #[inline]
+    fn filter_mapped<U:Copy>(&self, f: &fn(t: &T) -> Option<U>) -> ~[U] {
+        filter_mapped(*self, f)
+    }
+
+    /// Returns a pointer to the element at the given index, without doing
+    /// bounds checking.
+    #[inline(always)]
+    unsafe fn unsafe_ref(&self, index: uint) -> *T {
+        let (ptr, _): (*T, uint) = transmute(*self);
+        ptr.offset(index)
+    }
+}
+
+pub trait ImmutableEqVector<T:Eq> {
+    fn position_elem(&self, t: &T) -> Option<uint>;
+    fn rposition_elem(&self, t: &T) -> Option<uint>;
+}
+
+impl<'self,T:Eq> ImmutableEqVector<T> for &'self [T] {
+    /// Find the first index containing a matching value
+    #[inline]
+    fn position_elem(&self, x: &T) -> Option<uint> {
+        position_elem(*self, x)
+    }
+
+    /// Find the last index containing a matching value
+    #[inline]
+    fn rposition_elem(&self, t: &T) -> Option<uint> {
+        rposition_elem(*self, t)
+    }
+}
+
+pub trait ImmutableCopyableVector<T> {
+    fn filtered(&self, f: &fn(&T) -> bool) -> ~[T];
+    fn rfind(&self, f: &fn(t: &T) -> bool) -> Option<T>;
+    fn partitioned(&self, f: &fn(&T) -> bool) -> (~[T], ~[T]);
+    unsafe fn unsafe_get(&self, elem: uint) -> T;
+}
+
+/// Extension methods for vectors
+impl<'self,T:Copy> ImmutableCopyableVector<T> for &'self [T] {
+    /**
+     * Construct a new vector from the elements of a vector for which some
+     * predicate holds.
+     *
+     * Apply function `f` to each element of `v` and return a vector
+     * containing only those elements for which `f` returned true.
+     */
+    #[inline]
+    fn filtered(&self, f: &fn(t: &T) -> bool) -> ~[T] {
+        filtered(*self, f)
+    }
+
+    /**
+     * Search for the last element that matches a given predicate
+     *
+     * Apply function `f` to each element of `v` in reverse order. When
+     * function `f` returns true then an option containing the element is
+     * returned. If `f` matches no elements then none is returned.
+     */
+    #[inline]
+    fn rfind(&self, f: &fn(t: &T) -> bool) -> Option<T> {
+        rfind(*self, f)
+    }
+
+    /**
+     * Partitions the vector into those that satisfies the predicate, and
+     * those that do not.
+     */
+    #[inline]
+    fn partitioned(&self, f: &fn(&T) -> bool) -> (~[T], ~[T]) {
+        partitioned(*self, f)
+    }
+
+    /// Returns the element at the given index, without doing bounds checking.
+    #[inline(always)]
+    unsafe fn unsafe_get(&self, index: uint) -> T {
+        *self.unsafe_ref(index)
+    }
+}
+
+pub trait OwnedVector<T> {
+    fn push(&mut self, t: T);
+    fn push_all_move(&mut self, rhs: ~[T]);
+    fn pop(&mut self) -> T;
+    fn shift(&mut self) -> T;
+    fn unshift(&mut self, x: T);
+    fn insert(&mut self, i: uint, x:T);
+    fn remove(&mut self, i: uint) -> T;
+    fn swap_remove(&mut self, index: uint) -> T;
+    fn truncate(&mut self, newlen: uint);
+    fn retain(&mut self, f: &fn(t: &T) -> bool);
+    fn consume(self, f: &fn(uint, v: T));
+    fn consume_reverse(self, f: &fn(uint, v: T));
+    fn filter(self, f: &fn(t: &T) -> bool) -> ~[T];
+    fn partition(self, f: &fn(&T) -> bool) -> (~[T], ~[T]);
+    fn grow_fn(&mut self, n: uint, op: old_iter::InitOp<T>);
+}
+
+impl<T> OwnedVector<T> for ~[T] {
+    #[inline]
+    fn push(&mut self, t: T) {
+        push(self, t);
+    }
+
+    #[inline]
+    fn push_all_move(&mut self, rhs: ~[T]) {
+        push_all_move(self, rhs);
+    }
+
+    #[inline]
+    fn pop(&mut self) -> T {
+        pop(self)
+    }
+
+    #[inline]
+    fn shift(&mut self) -> T {
+        shift(self)
+    }
+
+    #[inline]
+    fn unshift(&mut self, x: T) {
+        unshift(self, x)
+    }
+
+    #[inline]
+    fn insert(&mut self, i: uint, x:T) {
+        insert(self, i, x)
+    }
+
+    #[inline]
+    fn remove(&mut self, i: uint) -> T {
+        remove(self, i)
+    }
+
+    #[inline]
+    fn swap_remove(&mut self, index: uint) -> T {
+        swap_remove(self, index)
+    }
+
+    #[inline]
+    fn truncate(&mut self, newlen: uint) {
+        truncate(self, newlen);
+    }
+
+    #[inline]
+    fn retain(&mut self, f: &fn(t: &T) -> bool) {
+        retain(self, f);
+    }
+
+    #[inline]
+    fn consume(self, f: &fn(uint, v: T)) {
+        consume(self, f)
+    }
+
+    #[inline]
+    fn consume_reverse(self, f: &fn(uint, v: T)) {
+        consume_reverse(self, f)
+    }
+
+    #[inline]
+    fn filter(self, f: &fn(&T) -> bool) -> ~[T] {
+        filter(self, f)
+    }
+
+    /**
+     * Partitions the vector into those that satisfies the predicate, and
+     * those that do not.
+     */
+    #[inline]
+    fn partition(self, f: &fn(&T) -> bool) -> (~[T], ~[T]) {
+        partition(self, f)
+    }
+
+    #[inline]
+    fn grow_fn(&mut self, n: uint, op: old_iter::InitOp<T>) {
+        grow_fn(self, n, op);
+    }
+}
+
+impl<T> Mutable for ~[T] {
+    /// Clear the vector, removing all values.
+    fn clear(&mut self) { self.truncate(0) }
+}
+
+pub trait OwnedCopyableVector<T:Copy> {
+    fn push_all(&mut self, rhs: &const [T]);
+    fn grow(&mut self, n: uint, initval: &T);
+    fn grow_set(&mut self, index: uint, initval: &T, val: T);
+}
+
+impl<T:Copy> OwnedCopyableVector<T> for ~[T] {
+    #[inline]
+    fn push_all(&mut self, rhs: &const [T]) {
+        push_all(self, rhs);
+    }
+
+    #[inline]
+    fn grow(&mut self, n: uint, initval: &T) {
+        grow(self, n, initval);
+    }
+
+    #[inline]
+    fn grow_set(&mut self, index: uint, initval: &T, val: T) {
+        grow_set(self, index, initval, val);
+    }
+}
+
+trait OwnedEqVector<T:Eq> {
+    fn dedup(&mut self);
+}
+
+impl<T:Eq> OwnedEqVector<T> for ~[T] {
+    #[inline]
+    fn dedup(&mut self) {
+        dedup(self)
+    }
+}
+
+pub trait MutableVector<T> {
+    unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T;
+    unsafe fn unsafe_set(&self, index: uint, val: T);
+}
+
+impl<'self,T> MutableVector<T> for &'self mut [T] {
+    #[inline(always)]
+    unsafe fn unsafe_mut_ref(&self, index: uint) -> *mut T {
+        let pair_ptr: &(*mut T, uint) = transmute(self);
+        let (ptr, _) = *pair_ptr;
+        ptr.offset(index)
+    }
+
+    #[inline(always)]
+    unsafe fn unsafe_set(&self, index: uint, val: T) {
+        *self.unsafe_mut_ref(index) = val;
+    }
+}
+
+/**
+* Constructs a vector from an unsafe pointer to a buffer
+*
+* # Arguments
+*
+* * ptr - An unsafe pointer to a buffer of `T`
+* * elts - The number of elements in the buffer
+*/
+// Wrapper for fn in raw: needs to be called by net_tcp::on_tcp_read_cb
+pub unsafe fn from_buf<T>(ptr: *T, elts: uint) -> ~[T] {
+    raw::from_buf_raw(ptr, elts)
+}
+
+/// The internal 'unboxed' representation of a vector
+pub struct UnboxedVecRepr {
+    fill: uint,
+    alloc: uint,
+    data: u8
+}
+
+/// Unsafe operations
+pub mod raw {
+    use cast::transmute;
+    use kinds::Copy;
+    use managed;
+    use option::{None, Some};
+    use ptr;
+    use sys;
+    use unstable::intrinsics;
+    use vec::{UnboxedVecRepr, as_const_buf, as_mut_buf, len, with_capacity};
+    use util;
+
+    /// The internal representation of a (boxed) vector
+    pub struct VecRepr {
+        box_header: managed::raw::BoxHeaderRepr,
+        unboxed: UnboxedVecRepr
+    }
+
+    pub struct SliceRepr {
+        data: *u8,
+        len: uint
+    }
+
+    /**
+     * Sets the length of a vector
+     *
+     * This will explicitly set the size of the vector, without actually
+     * modifing its buffers, so it is up to the caller to ensure that
+     * the vector is actually the specified size.
+     */
+    #[inline(always)]
+    pub unsafe fn set_len<T>(v: &mut ~[T], new_len: uint) {
+        let repr: **mut VecRepr = transmute(v);
+        (**repr).unboxed.fill = new_len * sys::nonzero_size_of::<T>();
+    }
+
+    /**
+     * Returns an unsafe pointer to the vector's buffer
+     *
+     * The caller must ensure that the vector outlives the pointer this
+     * function returns, or else it will end up pointing to garbage.
+     *
+     * Modifying the vector may cause its buffer to be reallocated, which
+     * would also make any pointers to it invalid.
+     */
+    #[inline(always)]
+    pub fn to_ptr<T>(v: &[T]) -> *T {
+        unsafe {
+            let repr: **SliceRepr = transmute(&v);
+            transmute(&((**repr).data))
+        }
+    }
+
+    /** see `to_ptr()` */
+    #[inline(always)]
+    pub fn to_const_ptr<T>(v: &const [T]) -> *const T {
+        unsafe {
+            let repr: **SliceRepr = transmute(&v);
+            transmute(&((**repr).data))
+        }
+    }
+
+    /** see `to_ptr()` */
+    #[inline(always)]
+    pub fn to_mut_ptr<T>(v: &mut [T]) -> *mut T {
+        unsafe {
+            let repr: **SliceRepr = transmute(&v);
+            transmute(&((**repr).data))
+        }
+    }
+
+    /**
+     * Form a slice from a pointer and length (as a number of units,
+     * not bytes).
+     */
+    #[inline(always)]
+    pub unsafe fn buf_as_slice<T,U>(p: *T,
+                                    len: uint,
+                                    f: &fn(v: &[T]) -> U) -> U {
+        let pair = (p, len * sys::nonzero_size_of::<T>());
+        let v : *(&'blk [T]) = transmute(&pair);
+        f(*v)
+    }
+
+    /**
+     * Form a slice from a pointer and length (as a number of units,
+     * not bytes).
+     */
+    #[inline(always)]
+    pub unsafe fn mut_buf_as_slice<T,U>(p: *mut T,
+                                        len: uint,
+                                        f: &fn(v: &mut [T]) -> U) -> U {
+        let pair = (p, len * sys::nonzero_size_of::<T>());
+        let v : *(&'blk mut [T]) = transmute(&pair);
+        f(*v)
+    }
+
+    /**
+     * Unchecked vector indexing.
+     */
+    #[inline(always)]
+    pub unsafe fn get<T:Copy>(v: &const [T], i: uint) -> T {
+        as_const_buf(v, |p, _len| *ptr::const_offset(p, i))
+    }
+
+    /**
+     * Unchecked vector index assignment.  Does not drop the
+     * old value and hence is only suitable when the vector
+     * is newly allocated.
+     */
+    #[inline(always)]
+    pub unsafe fn init_elem<T>(v: &mut [T], i: uint, val: T) {
+        let mut box = Some(val);
+        do as_mut_buf(v) |p, _len| {
+            let box2 = util::replace(&mut box, None);
+            intrinsics::move_val_init(&mut(*ptr::mut_offset(p, i)),
+                                      box2.unwrap());
+        }
+    }
+
+    /**
+    * Constructs a vector from an unsafe pointer to a buffer
+    *
+    * # Arguments
+    *
+    * * ptr - An unsafe pointer to a buffer of `T`
+    * * elts - The number of elements in the buffer
+    */
+    // Was in raw, but needs to be called by net_tcp::on_tcp_read_cb
+    #[inline(always)]
+    pub unsafe fn from_buf_raw<T>(ptr: *T, elts: uint) -> ~[T] {
+        let mut dst = with_capacity(elts);
+        set_len(&mut dst, elts);
+        as_mut_buf(dst, |p_dst, _len_dst| ptr::copy_memory(p_dst, ptr, elts));
+        dst
+    }
+
+    /**
+      * Copies data from one vector to another.
+      *
+      * Copies `count` bytes from `src` to `dst`. The source and destination
+      * may overlap.
+      */
+    #[inline(always)]
+    pub unsafe fn copy_memory<T>(dst: &mut [T], src: &const [T],
+                                 count: uint) {
+        assert!(dst.len() >= count);
+        assert!(src.len() >= count);
+
+        do as_mut_buf(dst) |p_dst, _len_dst| {
+            do as_const_buf(src) |p_src, _len_src| {
+                ptr::copy_memory(p_dst, p_src, count)
+            }
+        }
+    }
+}
+
+/// Operations on `[u8]`
+pub mod bytes {
+    use libc;
+    use uint;
+    use vec::raw;
+    use vec;
+
+    /// Bytewise string comparison
+    pub fn memcmp(a: &~[u8], b: &~[u8]) -> int {
+        let a_len = a.len();
+        let b_len = b.len();
+        let n = uint::min(a_len, b_len) as libc::size_t;
+        let r = unsafe {
+            libc::memcmp(raw::to_ptr(*a) as *libc::c_void,
+                         raw::to_ptr(*b) as *libc::c_void, n) as int
+        };
+
+        if r != 0 { r } else {
+            if a_len == b_len {
+                0
+            } else if a_len < b_len {
+                -1
+            } else {
+                1
+            }
+        }
+    }
+
+    /// Bytewise less than or equal
+    pub fn lt(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) < 0 }
+
+    /// Bytewise less than or equal
+    pub fn le(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) <= 0 }
+
+    /// Bytewise equality
+    pub fn eq(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) == 0 }
+
+    /// Bytewise inequality
+    pub fn ne(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) != 0 }
+
+    /// Bytewise greater than or equal
+    pub fn ge(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) >= 0 }
+
+    /// Bytewise greater than
+    pub fn gt(a: &~[u8], b: &~[u8]) -> bool { memcmp(a, b) > 0 }
+
+    /**
+      * Copies data from one vector to another.
+      *
+      * Copies `count` bytes from `src` to `dst`. The source and destination
+      * may overlap.
+      */
+    #[inline(always)]
+    pub fn copy_memory(dst: &mut [u8], src: &const [u8], count: uint) {
+        // Bound checks are done at vec::raw::copy_memory.
+        unsafe { vec::raw::copy_memory(dst, src, count) }
+    }
+}
+
+// ___________________________________________________________________________
+// ITERATION TRAIT METHODS
+
+impl<'self,A> old_iter::BaseIter<A> for &'self [A] {
+    #[inline(always)]
+    fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool {
+        each(*self, blk)
+    }
+    #[inline(always)]
+    fn size_hint(&self) -> Option<uint> { Some(self.len()) }
+}
+
+// FIXME(#4148): This should be redundant
+impl<A> old_iter::BaseIter<A> for ~[A] {
+    #[inline(always)]
+    fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool {
+        each(*self, blk)
+    }
+    #[inline(always)]
+    fn size_hint(&self) -> Option<uint> { Some(self.len()) }
+}
+
+// FIXME(#4148): This should be redundant
+impl<A> old_iter::BaseIter<A> for @[A] {
+    #[inline(always)]
+    fn each<'a>(&'a self, blk: &fn(v: &'a A) -> bool) -> bool {
+        each(*self, blk)
+    }
+    #[inline(always)]
+    fn size_hint(&self) -> Option<uint> { Some(self.len()) }
+}
+
+impl<'self,A> old_iter::MutableIter<A> for &'self mut [A] {
+    #[inline(always)]
+    fn each_mut<'a>(&'a mut self, blk: &fn(v: &'a mut A) -> bool) -> bool {
+        each_mut(*self, blk)
+    }
+}
+
+// FIXME(#4148): This should be redundant
+impl<A> old_iter::MutableIter<A> for ~[A] {
+    #[inline(always)]
+    fn each_mut<'a>(&'a mut self, blk: &fn(v: &'a mut A) -> bool) -> bool {
+        each_mut(*self, blk)
+    }
+}
+
+// FIXME(#4148): This should be redundant
+impl<A> old_iter::MutableIter<A> for @mut [A] {
+    #[inline(always)]
+    fn each_mut(&mut self, blk: &fn(v: &mut A) -> bool) -> bool {
+        each_mut(*self, blk)
+    }
+}
+
+impl<'self,A> old_iter::ExtendedIter<A> for &'self [A] {
+    pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool {
+        old_iter::eachi(self, blk)
+    }
+    pub fn all(&self, blk: &fn(&A) -> bool) -> bool {
+        old_iter::all(self, blk)
+    }
+    pub fn any(&self, blk: &fn(&A) -> bool) -> bool {
+        old_iter::any(self, blk)
+    }
+    pub fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B {
+        old_iter::foldl(self, b0, blk)
+    }
+    pub fn position(&self, f: &fn(&A) -> bool) -> Option<uint> {
+        old_iter::position(self, f)
+    }
+    fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B] {
+        old_iter::map_to_vec(self, op)
+    }
+    fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: &fn(&A) -> IB)
+        -> ~[B] {
+        old_iter::flat_map_to_vec(self, op)
+    }
+}
+
+impl<'self,A> old_iter::ExtendedMutableIter<A> for &'self mut [A] {
+    #[inline(always)]
+    pub fn eachi_mut(&mut self, blk: &fn(uint, v: &mut A) -> bool) -> bool {
+        eachi_mut(*self, blk)
+    }
+}
+
+// FIXME(#4148): This should be redundant
+impl<A> old_iter::ExtendedIter<A> for ~[A] {
+    pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool {
+        old_iter::eachi(self, blk)
+    }
+    pub fn all(&self, blk: &fn(&A) -> bool) -> bool {
+        old_iter::all(self, blk)
+    }
+    pub fn any(&self, blk: &fn(&A) -> bool) -> bool {
+        old_iter::any(self, blk)
+    }
+    pub fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B {
+        old_iter::foldl(self, b0, blk)
+    }
+    pub fn position(&self, f: &fn(&A) -> bool) -> Option<uint> {
+        old_iter::position(self, f)
+    }
+    fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B] {
+        old_iter::map_to_vec(self, op)
+    }
+    fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: &fn(&A) -> IB)
+        -> ~[B] {
+        old_iter::flat_map_to_vec(self, op)
+    }
+}
+
+// FIXME(#4148): This should be redundant
+impl<A> old_iter::ExtendedIter<A> for @[A] {
+    pub fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool {
+        old_iter::eachi(self, blk)
+    }
+    pub fn all(&self, blk: &fn(&A) -> bool) -> bool {
+        old_iter::all(self, blk)
+    }
+    pub fn any(&self, blk: &fn(&A) -> bool) -> bool {
+        old_iter::any(self, blk)
+    }
+    pub fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B {
+        old_iter::foldl(self, b0, blk)
+    }
+    pub fn position(&self, f: &fn(&A) -> bool) -> Option<uint> {
+        old_iter::position(self, f)
+    }
+    fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B] {
+        old_iter::map_to_vec(self, op)
+    }
+    fn flat_map_to_vec<B,IB:BaseIter<B>>(&self, op: &fn(&A) -> IB)
+        -> ~[B] {
+        old_iter::flat_map_to_vec(self, op)
+    }
+}
+
+impl<'self,A:Eq> old_iter::EqIter<A> for &'self [A] {
+    pub fn contains(&self, x: &A) -> bool { old_iter::contains(self, x) }
+    pub fn count(&self, x: &A) -> uint { old_iter::count(self, x) }
+}
+
+// FIXME(#4148): This should be redundant
+impl<A:Eq> old_iter::EqIter<A> for ~[A] {
+    pub fn contains(&self, x: &A) -> bool { old_iter::contains(self, x) }
+    pub fn count(&self, x: &A) -> uint { old_iter::count(self, x) }
+}
+
+// FIXME(#4148): This should be redundant
+impl<A:Eq> old_iter::EqIter<A> for @[A] {
+    pub fn contains(&self, x: &A) -> bool { old_iter::contains(self, x) }
+    pub fn count(&self, x: &A) -> uint { old_iter::count(self, x) }
+}
+
+impl<'self,A:Copy> old_iter::CopyableIter<A> for &'self [A] {
+    fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A] {
+        old_iter::filter_to_vec(self, pred)
+    }
+    fn to_vec(&self) -> ~[A] { old_iter::to_vec(self) }
+    pub fn find(&self, f: &fn(&A) -> bool) -> Option<A> {
+        old_iter::find(self, f)
+    }
+}
+
+// FIXME(#4148): This should be redundant
+impl<A:Copy> old_iter::CopyableIter<A> for ~[A] {
+    fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A] {
+        old_iter::filter_to_vec(self, pred)
+    }
+    fn to_vec(&self) -> ~[A] { old_iter::to_vec(self) }
+    pub fn find(&self, f: &fn(&A) -> bool) -> Option<A> {
+        old_iter::find(self, f)
+    }
+}
+
+// FIXME(#4148): This should be redundant
+impl<A:Copy> old_iter::CopyableIter<A> for @[A] {
+    fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A] {
+        old_iter::filter_to_vec(self, pred)
+    }
+    fn to_vec(&self) -> ~[A] { old_iter::to_vec(self) }
+    pub fn find(&self, f: &fn(&A) -> bool) -> Option<A> {
+        old_iter::find(self, f)
+    }
+}
+
+impl<'self,A:Copy + Ord> old_iter::CopyableOrderedIter<A> for &'self [A] {
+    fn min(&self) -> A { old_iter::min(self) }
+    fn max(&self) -> A { old_iter::max(self) }
+}
+
+// FIXME(#4148): This should be redundant
+impl<A:Copy + Ord> old_iter::CopyableOrderedIter<A> for ~[A] {
+    fn min(&self) -> A { old_iter::min(self) }
+    fn max(&self) -> A { old_iter::max(self) }
+}
+
+// FIXME(#4148): This should be redundant
+impl<A:Copy + Ord> old_iter::CopyableOrderedIter<A> for @[A] {
+    fn min(&self) -> A { old_iter::min(self) }
+    fn max(&self) -> A { old_iter::max(self) }
+}
+
+impl<'self,A:Copy> old_iter::CopyableNonstrictIter<A> for &'self [A] {
+    fn each_val(&const self, f: &fn(A) -> bool) -> bool {
+        let mut i = 0;
+        while i < self.len() {
+            if !f(copy self[i]) { return false; }
+            i += 1;
+        }
+        return true;
+    }
+}
+
+// FIXME(#4148): This should be redundant
+impl<A:Copy> old_iter::CopyableNonstrictIter<A> for ~[A] {
+    fn each_val(&const self, f: &fn(A) -> bool) -> bool {
+        let mut i = 0;
+        while i < uniq_len(self) {
+            if !f(copy self[i]) { return false; }
+            i += 1;
+        }
+        return true;
+    }
+}
+
+// FIXME(#4148): This should be redundant
+impl<A:Copy> old_iter::CopyableNonstrictIter<A> for @[A] {
+    fn each_val(&const self, f: &fn(A) -> bool) -> bool {
+        let mut i = 0;
+        while i < self.len() {
+            if !f(copy self[i]) { return false; }
+            i += 1;
+        }
+        return true;
+    }
+}
+
+impl<A:Clone> Clone for ~[A] {
+    #[inline]
+    fn clone(&self) -> ~[A] {
+        self.map(|item| item.clone())
+    }
+}
+
+// could be implemented with &[T] with .slice(), but this avoids bounds checks
+pub struct VecIterator<'self, T> {
+    priv ptr: *T,
+    priv end: *T,
+    priv lifetime: &'self T // FIXME: #5922
+}
+
+impl<'self, T> Iterator<&'self T> for VecIterator<'self, T> {
+    #[inline]
+    fn next(&mut self) -> Option<&'self T> {
+        unsafe {
+            if self.ptr == self.end {
+                None
+            } else {
+                let old = self.ptr;
+                self.ptr = self.ptr.offset(1);
+                Some(cast::transmute(old))
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use option::{None, Option, Some};
+    use sys;
+    use vec::*;
+    use cmp::*;
+
+    fn square(n: uint) -> uint { n * n }
+
+    fn square_ref(n: &uint) -> uint { square(*n) }
+
+    fn is_three(n: &uint) -> bool { *n == 3u }
+
+    fn is_odd(n: &uint) -> bool { *n % 2u == 1u }
+
+    fn is_equal(x: &uint, y:&uint) -> bool { *x == *y }
+
+    fn square_if_odd_r(n: &uint) -> Option<uint> {
+        if *n % 2u == 1u { Some(*n * *n) } else { None }
+    }
+
+    fn square_if_odd_v(n: uint) -> Option<uint> {
+        if n % 2u == 1u { Some(n * n) } else { None }
+    }
+
+    fn add(x: uint, y: &uint) -> uint { x + *y }
+
+    #[test]
+    fn test_unsafe_ptrs() {
+        unsafe {
+            // Test on-stack copy-from-buf.
+            let a = ~[1, 2, 3];
+            let mut ptr = raw::to_ptr(a);
+            let b = from_buf(ptr, 3u);
+            assert_eq!(b.len(), 3u);
+            assert_eq!(b[0], 1);
+            assert_eq!(b[1], 2);
+            assert_eq!(b[2], 3);
+
+            // Test on-heap copy-from-buf.
+            let c = ~[1, 2, 3, 4, 5];
+            ptr = raw::to_ptr(c);
+            let d = from_buf(ptr, 5u);
+            assert_eq!(d.len(), 5u);
+            assert_eq!(d[0], 1);
+            assert_eq!(d[1], 2);
+            assert_eq!(d[2], 3);
+            assert_eq!(d[3], 4);
+            assert_eq!(d[4], 5);
+        }
+    }
+
+    #[test]
+    fn test_from_fn() {
+        // Test on-stack from_fn.
+        let mut v = from_fn(3u, square);
+        assert_eq!(v.len(), 3u);
+        assert_eq!(v[0], 0u);
+        assert_eq!(v[1], 1u);
+        assert_eq!(v[2], 4u);
+
+        // Test on-heap from_fn.
+        v = from_fn(5u, square);
+        assert_eq!(v.len(), 5u);
+        assert_eq!(v[0], 0u);
+        assert_eq!(v[1], 1u);
+        assert_eq!(v[2], 4u);
+        assert_eq!(v[3], 9u);
+        assert_eq!(v[4], 16u);
+    }
+
+    #[test]
+    fn test_from_elem() {
+        // Test on-stack from_elem.
+        let mut v = from_elem(2u, 10u);
+        assert_eq!(v.len(), 2u);
+        assert_eq!(v[0], 10u);
+        assert_eq!(v[1], 10u);
+
+        // Test on-heap from_elem.
+        v = from_elem(6u, 20u);
+        assert_eq!(v[0], 20u);
+        assert_eq!(v[1], 20u);
+        assert_eq!(v[2], 20u);
+        assert_eq!(v[3], 20u);
+        assert_eq!(v[4], 20u);
+        assert_eq!(v[5], 20u);
+    }
+
+    #[test]
+    fn test_is_empty() {
+        assert!(is_empty::<int>(~[]));
+        assert!(!is_empty(~[0]));
+    }
+
+    #[test]
+    fn test_len_divzero() {
+        type Z = [i8, ..0];
+        let v0 : &[Z] = &[];
+        let v1 : &[Z] = &[[]];
+        let v2 : &[Z] = &[[], []];
+        assert_eq!(sys::size_of::<Z>(), 0);
+        assert_eq!(v0.len(), 0);
+        assert_eq!(v1.len(), 1);
+        assert_eq!(v2.len(), 2);
+    }
+
+    #[test]
+    fn test_head() {
+        let mut a = ~[11];
+        assert_eq!(a.head(), &11);
+        a = ~[11, 12];
+        assert_eq!(a.head(), &11);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_head_empty() {
+        let a: ~[int] = ~[];
+        a.head();
+    }
+
+    #[test]
+    fn test_head_opt() {
+        let mut a = ~[];
+        assert_eq!(a.head_opt(), None);
+        a = ~[11];
+        assert_eq!(a.head_opt().unwrap(), &11);
+        a = ~[11, 12];
+        assert_eq!(a.head_opt().unwrap(), &11);
+    }
+
+    #[test]
+    fn test_tail() {
+        let mut a = ~[11];
+        assert_eq!(a.tail(), &[]);
+        a = ~[11, 12];
+        assert_eq!(a.tail(), &[12]);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_tail_empty() {
+        let a: ~[int] = ~[];
+        a.tail();
+    }
+
+    #[test]
+    fn test_tailn() {
+        let mut a = ~[11, 12, 13];
+        assert_eq!(a.tailn(0), &[11, 12, 13]);
+        a = ~[11, 12, 13];
+        assert_eq!(a.tailn(2), &[13]);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_tailn_empty() {
+        let a: ~[int] = ~[];
+        a.tailn(2);
+    }
+
+    #[test]
+    fn test_init() {
+        let mut a = ~[11];
+        assert_eq!(a.init(), &[]);
+        a = ~[11, 12];
+        assert_eq!(a.init(), &[11]);
+    }
+
+    #[init]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_init_empty() {
+        let a: ~[int] = ~[];
+        a.init();
+    }
+
+    #[test]
+    fn test_initn() {
+        let mut a = ~[11, 12, 13];
+        assert_eq!(a.initn(0), &[11, 12, 13]);
+        a = ~[11, 12, 13];
+        assert_eq!(a.initn(2), &[11]);
+    }
+
+    #[init]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_initn_empty() {
+        let a: ~[int] = ~[];
+        a.initn(2);
+    }
+
+    #[test]
+    fn test_last() {
+        let mut a = ~[11];
+        assert_eq!(a.last(), &11);
+        a = ~[11, 12];
+        assert_eq!(a.last(), &12);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_last_empty() {
+        let a: ~[int] = ~[];
+        a.last();
+    }
+
+    #[test]
+    fn test_last_opt() {
+        let mut a = ~[];
+        assert_eq!(a.last_opt(), None);
+        a = ~[11];
+        assert_eq!(a.last_opt().unwrap(), &11);
+        a = ~[11, 12];
+        assert_eq!(a.last_opt().unwrap(), &12);
+    }
+
+    #[test]
+    fn test_slice() {
+        // Test fixed length vector.
+        let vec_fixed = [1, 2, 3, 4];
+        let v_a = slice(vec_fixed, 1u, vec_fixed.len()).to_vec();
+        assert_eq!(v_a.len(), 3u);
+        assert_eq!(v_a[0], 2);
+        assert_eq!(v_a[1], 3);
+        assert_eq!(v_a[2], 4);
+
+        // Test on stack.
+        let vec_stack = &[1, 2, 3];
+        let v_b = slice(vec_stack, 1u, 3u).to_vec();
+        assert_eq!(v_b.len(), 2u);
+        assert_eq!(v_b[0], 2);
+        assert_eq!(v_b[1], 3);
+
+        // Test on managed heap.
+        let vec_managed = @[1, 2, 3, 4, 5];
+        let v_c = slice(vec_managed, 0u, 3u).to_vec();
+        assert_eq!(v_c.len(), 3u);
+        assert_eq!(v_c[0], 1);
+        assert_eq!(v_c[1], 2);
+        assert_eq!(v_c[2], 3);
+
+        // Test on exchange heap.
+        let vec_unique = ~[1, 2, 3, 4, 5, 6];
+        let v_d = slice(vec_unique, 1u, 6u).to_vec();
+        assert_eq!(v_d.len(), 5u);
+        assert_eq!(v_d[0], 2);
+        assert_eq!(v_d[1], 3);
+        assert_eq!(v_d[2], 4);
+        assert_eq!(v_d[3], 5);
+        assert_eq!(v_d[4], 6);
+    }
+
+    #[test]
+    fn test_pop() {
+        // Test on-heap pop.
+        let mut v = ~[1, 2, 3, 4, 5];
+        let e = v.pop();
+        assert_eq!(v.len(), 4u);
+        assert_eq!(v[0], 1);
+        assert_eq!(v[1], 2);
+        assert_eq!(v[2], 3);
+        assert_eq!(v[3], 4);
+        assert_eq!(e, 5);
+    }
+
+    #[test]
+    fn test_swap_remove() {
+        let mut v = ~[1, 2, 3, 4, 5];
+        let mut e = v.swap_remove(0);
+        assert_eq!(v.len(), 4);
+        assert_eq!(e, 1);
+        assert_eq!(v[0], 5);
+        e = v.swap_remove(3);
+        assert_eq!(v.len(), 3);
+        assert_eq!(e, 4);
+        assert_eq!(v[0], 5);
+        assert_eq!(v[1], 2);
+        assert_eq!(v[2], 3);
+    }
+
+    #[test]
+    fn test_swap_remove_noncopyable() {
+        // Tests that we don't accidentally run destructors twice.
+        let mut v = ~[::unstable::sync::exclusive(()),
+                      ::unstable::sync::exclusive(()),
+                      ::unstable::sync::exclusive(())];
+        let mut _e = v.swap_remove(0);
+        assert_eq!(v.len(), 2);
+        _e = v.swap_remove(1);
+        assert_eq!(v.len(), 1);
+        _e = v.swap_remove(0);
+        assert_eq!(v.len(), 0);
+    }
+
+    #[test]
+    fn test_push() {
+        // Test on-stack push().
+        let mut v = ~[];
+        v.push(1);
+        assert_eq!(v.len(), 1u);
+        assert_eq!(v[0], 1);
+
+        // Test on-heap push().
+        v.push(2);
+        assert_eq!(v.len(), 2u);
+        assert_eq!(v[0], 1);
+        assert_eq!(v[1], 2);
+    }
+
+    #[test]
+    fn test_grow() {
+        // Test on-stack grow().
+        let mut v = ~[];
+        v.grow(2u, &1);
+        assert_eq!(v.len(), 2u);
+        assert_eq!(v[0], 1);
+        assert_eq!(v[1], 1);
+
+        // Test on-heap grow().
+        v.grow(3u, &2);
+        assert_eq!(v.len(), 5u);
+        assert_eq!(v[0], 1);
+        assert_eq!(v[1], 1);
+        assert_eq!(v[2], 2);
+        assert_eq!(v[3], 2);
+        assert_eq!(v[4], 2);
+    }
+
+    #[test]
+    fn test_grow_fn() {
+        let mut v = ~[];
+        v.grow_fn(3u, square);
+        assert_eq!(v.len(), 3u);
+        assert_eq!(v[0], 0u);
+        assert_eq!(v[1], 1u);
+        assert_eq!(v[2], 4u);
+    }
+
+    #[test]
+    fn test_grow_set() {
+        let mut v = ~[1, 2, 3];
+        v.grow_set(4u, &4, 5);
+        assert_eq!(v.len(), 5u);
+        assert_eq!(v[0], 1);
+        assert_eq!(v[1], 2);
+        assert_eq!(v[2], 3);
+        assert_eq!(v[3], 4);
+        assert_eq!(v[4], 5);
+    }
+
+    #[test]
+    fn test_truncate() {
+        let mut v = ~[@6,@5,@4];
+        v.truncate(1);
+        assert_eq!(v.len(), 1);
+        assert_eq!(*(v[0]), 6);
+        // If the unsafe block didn't drop things properly, we blow up here.
+    }
+
+    #[test]
+    fn test_clear() {
+        let mut v = ~[@6,@5,@4];
+        v.clear();
+        assert_eq!(v.len(), 0);
+        // If the unsafe block didn't drop things properly, we blow up here.
+    }
+
+    #[test]
+    fn test_dedup() {
+        fn case(a: ~[uint], b: ~[uint]) {
+            let mut v = a;
+            v.dedup();
+            assert_eq!(v, b);
+        }
+        case(~[], ~[]);
+        case(~[1], ~[1]);
+        case(~[1,1], ~[1]);
+        case(~[1,2,3], ~[1,2,3]);
+        case(~[1,1,2,3], ~[1,2,3]);
+        case(~[1,2,2,3], ~[1,2,3]);
+        case(~[1,2,3,3], ~[1,2,3]);
+        case(~[1,1,2,2,2,3,3], ~[1,2,3]);
+    }
+
+    #[test]
+    fn test_dedup_unique() {
+        let mut v0 = ~[~1, ~1, ~2, ~3];
+        v0.dedup();
+        let mut v1 = ~[~1, ~2, ~2, ~3];
+        v1.dedup();
+        let mut v2 = ~[~1, ~2, ~3, ~3];
+        v2.dedup();
+        /*
+         * If the ~pointers were leaked or otherwise misused, valgrind and/or
+         * rustrt should raise errors.
+         */
+    }
+
+    #[test]
+    fn test_dedup_shared() {
+        let mut v0 = ~[@1, @1, @2, @3];
+        v0.dedup();
+        let mut v1 = ~[@1, @2, @2, @3];
+        v1.dedup();
+        let mut v2 = ~[@1, @2, @3, @3];
+        v2.dedup();
+        /*
+         * If the @pointers were leaked or otherwise misused, valgrind and/or
+         * rustrt should raise errors.
+         */
+    }
+
+    #[test]
+    fn test_map() {
+        // Test on-stack map.
+        let mut v = ~[1u, 2u, 3u];
+        let mut w = map(v, square_ref);
+        assert_eq!(w.len(), 3u);
+        assert_eq!(w[0], 1u);
+        assert_eq!(w[1], 4u);
+        assert_eq!(w[2], 9u);
+
+        // Test on-heap map.
+        v = ~[1u, 2u, 3u, 4u, 5u];
+        w = map(v, square_ref);
+        assert_eq!(w.len(), 5u);
+        assert_eq!(w[0], 1u);
+        assert_eq!(w[1], 4u);
+        assert_eq!(w[2], 9u);
+        assert_eq!(w[3], 16u);
+        assert_eq!(w[4], 25u);
+    }
+
+    #[test]
+    fn test_map_zip() {
+        fn times(x: &int, y: &int) -> int { *x * *y }
+        let f = times;
+        let v0 = ~[1, 2, 3, 4, 5];
+        let v1 = ~[5, 4, 3, 2, 1];
+        let u = map_zip::<int, int, int>(v0, v1, f);
+        let mut i = 0;
+        while i < 5 { assert!(v0[i] * v1[i] == u[i]); i += 1; }
+    }
+
+    #[test]
+    fn test_filter_mapped() {
+        // Test on-stack filter-map.
+        let mut v = ~[1u, 2u, 3u];
+        let mut w = filter_mapped(v, square_if_odd_r);
+        assert_eq!(w.len(), 2u);
+        assert_eq!(w[0], 1u);
+        assert_eq!(w[1], 9u);
+
+        // Test on-heap filter-map.
+        v = ~[1u, 2u, 3u, 4u, 5u];
+        w = filter_mapped(v, square_if_odd_r);
+        assert_eq!(w.len(), 3u);
+        assert_eq!(w[0], 1u);
+        assert_eq!(w[1], 9u);
+        assert_eq!(w[2], 25u);
+
+        fn halve(i: &int) -> Option<int> {
+            if *i % 2 == 0 {
+                Some::<int>(*i / 2)
+            } else {
+                None::<int>
+            }
+        }
+        fn halve_for_sure(i: &int) -> int { *i / 2 }
+        let all_even: ~[int] = ~[0, 2, 8, 6];
+        let all_odd1: ~[int] = ~[1, 7, 3];
+        let all_odd2: ~[int] = ~[];
+        let mix: ~[int] = ~[9, 2, 6, 7, 1, 0, 0, 3];
+        let mix_dest: ~[int] = ~[1, 3, 0, 0];
+        assert!(filter_mapped(all_even, halve) ==
+                     map(all_even, halve_for_sure));
+        assert_eq!(filter_mapped(all_odd1, halve), ~[]);
+        assert_eq!(filter_mapped(all_odd2, halve), ~[]);
+        assert_eq!(filter_mapped(mix, halve), mix_dest);
+    }
+
+    #[test]
+    fn test_filter_map() {
+        // Test on-stack filter-map.
+        let mut v = ~[1u, 2u, 3u];
+        let mut w = filter_map(v, square_if_odd_v);
+        assert_eq!(w.len(), 2u);
+        assert_eq!(w[0], 1u);
+        assert_eq!(w[1], 9u);
+
+        // Test on-heap filter-map.
+        v = ~[1u, 2u, 3u, 4u, 5u];
+        w = filter_map(v, square_if_odd_v);
+        assert_eq!(w.len(), 3u);
+        assert_eq!(w[0], 1u);
+        assert_eq!(w[1], 9u);
+        assert_eq!(w[2], 25u);
+
+        fn halve(i: int) -> Option<int> {
+            if i % 2 == 0 {
+                Some::<int>(i / 2)
+            } else {
+                None::<int>
+            }
+        }
+        fn halve_for_sure(i: &int) -> int { *i / 2 }
+        let all_even: ~[int] = ~[0, 2, 8, 6];
+        let all_even0: ~[int] = copy all_even;
+        let all_odd1: ~[int] = ~[1, 7, 3];
+        let all_odd2: ~[int] = ~[];
+        let mix: ~[int] = ~[9, 2, 6, 7, 1, 0, 0, 3];
+        let mix_dest: ~[int] = ~[1, 3, 0, 0];
+        assert!(filter_map(all_even, halve) ==
+                     map(all_even0, halve_for_sure));
+        assert_eq!(filter_map(all_odd1, halve), ~[]);
+        assert_eq!(filter_map(all_odd2, halve), ~[]);
+        assert_eq!(filter_map(mix, halve), mix_dest);
+    }
+
+    #[test]
+    fn test_filter() {
+        assert_eq!(filter(~[1u, 2u, 3u], is_odd), ~[1u, 3u]);
+        assert_eq!(filter(~[1u, 2u, 4u, 8u, 16u], is_three), ~[]);
+    }
+
+    #[test]
+    fn test_retain() {
+        let mut v = ~[1, 2, 3, 4, 5];
+        v.retain(is_odd);
+        assert_eq!(v, ~[1, 3, 5]);
+    }
+
+    #[test]
+    fn test_foldl() {
+        // Test on-stack fold.
+        let mut v = ~[1u, 2u, 3u];
+        let mut sum = foldl(0u, v, add);
+        assert_eq!(sum, 6u);
+
+        // Test on-heap fold.
+        v = ~[1u, 2u, 3u, 4u, 5u];
+        sum = foldl(0u, v, add);
+        assert_eq!(sum, 15u);
+    }
+
+    #[test]
+    fn test_foldl2() {
+        fn sub(a: int, b: &int) -> int {
+            a - *b
+        }
+        let v = ~[1, 2, 3, 4];
+        let sum = foldl(0, v, sub);
+        assert_eq!(sum, -10);
+    }
+
+    #[test]
+    fn test_foldr() {
+        fn sub(a: &int, b: int) -> int {
+            *a - b
+        }
+        let v = ~[1, 2, 3, 4];
+        let sum = foldr(v, 0, sub);
+        assert_eq!(sum, -2);
+    }
+
+    #[test]
+    fn test_each_empty() {
+        for each::<int>(~[]) |_v| {
+            fail!(); // should never be executed
+        }
+    }
+
+    #[test]
+    fn test_each_nonempty() {
+        let mut i = 0;
+        for each(~[1, 2, 3]) |v| {
+            i += *v;
+        }
+        assert_eq!(i, 6);
+    }
+
+    #[test]
+    fn test_eachi() {
+        let mut i = 0;
+        for eachi(~[1, 2, 3]) |j, v| {
+            if i == 0 { assert!(*v == 1); }
+            assert_eq!(j + 1u, *v as uint);
+            i += *v;
+        }
+        assert_eq!(i, 6);
+    }
+
+    #[test]
+    fn test_each_reverse_empty() {
+        let v: ~[int] = ~[];
+        for v.each_reverse |_v| {
+            fail!(); // should never execute
+        }
+    }
+
+    #[test]
+    fn test_each_reverse_nonempty() {
+        let mut i = 0;
+        for each_reverse(~[1, 2, 3]) |v| {
+            if i == 0 { assert!(*v == 3); }
+            i += *v
+        }
+        assert_eq!(i, 6);
+    }
+
+    #[test]
+    fn test_eachi_reverse() {
+        let mut i = 0;
+        for eachi_reverse(~[0, 1, 2]) |j, v| {
+            if i == 0 { assert!(*v == 2); }
+            assert_eq!(j, *v as uint);
+            i += *v;
+        }
+        assert_eq!(i, 3);
+    }
+
+    #[test]
+    fn test_eachi_reverse_empty() {
+        let v: ~[int] = ~[];
+        for v.eachi_reverse |_i, _v| {
+            fail!(); // should never execute
+        }
+    }
+
+    #[test]
+    fn test_each_permutation() {
+        let mut results: ~[~[int]];
+
+        results = ~[];
+        for each_permutation(~[]) |v| { results.push(to_owned(v)); }
+        assert_eq!(results, ~[~[]]);
+
+        results = ~[];
+        for each_permutation(~[7]) |v| { results.push(to_owned(v)); }
+        assert_eq!(results, ~[~[7]]);
+
+        results = ~[];
+        for each_permutation(~[1,1]) |v| { results.push(to_owned(v)); }
+        assert_eq!(results, ~[~[1,1],~[1,1]]);
+
+        results = ~[];
+        for each_permutation(~[5,2,0]) |v| { results.push(to_owned(v)); }
+        assert!(results ==
+            ~[~[5,2,0],~[5,0,2],~[2,5,0],~[2,0,5],~[0,5,2],~[0,2,5]]);
+    }
+
+    #[test]
+    fn test_any_and_all() {
+        assert!(any(~[1u, 2u, 3u], is_three));
+        assert!(!any(~[0u, 1u, 2u], is_three));
+        assert!(any(~[1u, 2u, 3u, 4u, 5u], is_three));
+        assert!(!any(~[1u, 2u, 4u, 5u, 6u], is_three));
+
+        assert!(all(~[3u, 3u, 3u], is_three));
+        assert!(!all(~[3u, 3u, 2u], is_three));
+        assert!(all(~[3u, 3u, 3u, 3u, 3u], is_three));
+        assert!(!all(~[3u, 3u, 0u, 1u, 2u], is_three));
+    }
+
+    #[test]
+    fn test_any2_and_all2() {
+
+        assert!(any2(~[2u, 4u, 6u], ~[2u, 4u, 6u], is_equal));
+        assert!(any2(~[1u, 2u, 3u], ~[4u, 5u, 3u], is_equal));
+        assert!(!any2(~[1u, 2u, 3u], ~[4u, 5u, 6u], is_equal));
+        assert!(any2(~[2u, 4u, 6u], ~[2u, 4u], is_equal));
+
+        assert!(all2(~[2u, 4u, 6u], ~[2u, 4u, 6u], is_equal));
+        assert!(!all2(~[1u, 2u, 3u], ~[4u, 5u, 3u], is_equal));
+        assert!(!all2(~[1u, 2u, 3u], ~[4u, 5u, 6u], is_equal));
+        assert!(!all2(~[2u, 4u, 6u], ~[2u, 4u], is_equal));
+    }
+
+    #[test]
+    fn test_zip_unzip() {
+        let v1 = ~[1, 2, 3];
+        let v2 = ~[4, 5, 6];
+
+        let z1 = zip(v1, v2);
+
+        assert_eq!((1, 4), z1[0]);
+        assert_eq!((2, 5), z1[1]);
+        assert_eq!((3, 6), z1[2]);
+
+        let (left, right) = unzip(z1);
+
+        assert_eq!((1, 4), (left[0], right[0]));
+        assert_eq!((2, 5), (left[1], right[1]));
+        assert_eq!((3, 6), (left[2], right[2]));
+    }
+
+    #[test]
+    fn test_position_elem() {
+        assert!(position_elem(~[], &1).is_none());
+
+        let v1 = ~[1, 2, 3, 3, 2, 5];
+        assert_eq!(position_elem(v1, &1), Some(0u));
+        assert_eq!(position_elem(v1, &2), Some(1u));
+        assert_eq!(position_elem(v1, &5), Some(5u));
+        assert!(position_elem(v1, &4).is_none());
+    }
+
+    #[test]
+    fn test_position() {
+        fn less_than_three(i: &int) -> bool { *i < 3 }
+        fn is_eighteen(i: &int) -> bool { *i == 18 }
+
+        assert!(position(~[], less_than_three).is_none());
+
+        let v1 = ~[5, 4, 3, 2, 1];
+        assert_eq!(position(v1, less_than_three), Some(3u));
+        assert!(position(v1, is_eighteen).is_none());
+    }
+
+    #[test]
+    fn test_position_between() {
+        assert!(position_between(~[], 0u, 0u, f).is_none());
+
+        fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
+        let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+
+        assert!(position_between(v, 0u, 0u, f).is_none());
+        assert!(position_between(v, 0u, 1u, f).is_none());
+        assert_eq!(position_between(v, 0u, 2u, f), Some(1u));
+        assert_eq!(position_between(v, 0u, 3u, f), Some(1u));
+        assert_eq!(position_between(v, 0u, 4u, f), Some(1u));
+
+        assert!(position_between(v, 1u, 1u, f).is_none());
+        assert_eq!(position_between(v, 1u, 2u, f), Some(1u));
+        assert_eq!(position_between(v, 1u, 3u, f), Some(1u));
+        assert_eq!(position_between(v, 1u, 4u, f), Some(1u));
+
+        assert!(position_between(v, 2u, 2u, f).is_none());
+        assert!(position_between(v, 2u, 3u, f).is_none());
+        assert_eq!(position_between(v, 2u, 4u, f), Some(3u));
+
+        assert!(position_between(v, 3u, 3u, f).is_none());
+        assert_eq!(position_between(v, 3u, 4u, f), Some(3u));
+
+        assert!(position_between(v, 4u, 4u, f).is_none());
+    }
+
+    #[test]
+    fn test_find() {
+        assert!(find(~[], f).is_none());
+
+        fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
+        fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' }
+        let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+
+        assert_eq!(find(v, f), Some((1, 'b')));
+        assert!(find(v, g).is_none());
+    }
+
+    #[test]
+    fn test_find_between() {
+        assert!(find_between(~[], 0u, 0u, f).is_none());
+
+        fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
+        let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+
+        assert!(find_between(v, 0u, 0u, f).is_none());
+        assert!(find_between(v, 0u, 1u, f).is_none());
+        assert_eq!(find_between(v, 0u, 2u, f), Some((1, 'b')));
+        assert_eq!(find_between(v, 0u, 3u, f), Some((1, 'b')));
+        assert_eq!(find_between(v, 0u, 4u, f), Some((1, 'b')));
+
+        assert!(find_between(v, 1u, 1u, f).is_none());
+        assert_eq!(find_between(v, 1u, 2u, f), Some((1, 'b')));
+        assert_eq!(find_between(v, 1u, 3u, f), Some((1, 'b')));
+        assert_eq!(find_between(v, 1u, 4u, f), Some((1, 'b')));
+
+        assert!(find_between(v, 2u, 2u, f).is_none());
+        assert!(find_between(v, 2u, 3u, f).is_none());
+        assert_eq!(find_between(v, 2u, 4u, f), Some((3, 'b')));
+
+        assert!(find_between(v, 3u, 3u, f).is_none());
+        assert_eq!(find_between(v, 3u, 4u, f), Some((3, 'b')));
+
+        assert!(find_between(v, 4u, 4u, f).is_none());
+    }
+
+    #[test]
+    fn test_rposition() {
+        assert!(find(~[], f).is_none());
+
+        fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
+        fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' }
+        let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+
+        assert_eq!(position(v, f), Some(1u));
+        assert!(position(v, g).is_none());
+    }
+
+    #[test]
+    fn test_rposition_between() {
+        assert!(rposition_between(~[], 0u, 0u, f).is_none());
+
+        fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
+        let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+
+        assert!(rposition_between(v, 0u, 0u, f).is_none());
+        assert!(rposition_between(v, 0u, 1u, f).is_none());
+        assert_eq!(rposition_between(v, 0u, 2u, f), Some(1u));
+        assert_eq!(rposition_between(v, 0u, 3u, f), Some(1u));
+        assert_eq!(rposition_between(v, 0u, 4u, f), Some(3u));
+
+        assert!(rposition_between(v, 1u, 1u, f).is_none());
+        assert_eq!(rposition_between(v, 1u, 2u, f), Some(1u));
+        assert_eq!(rposition_between(v, 1u, 3u, f), Some(1u));
+        assert_eq!(rposition_between(v, 1u, 4u, f), Some(3u));
+
+        assert!(rposition_between(v, 2u, 2u, f).is_none());
+        assert!(rposition_between(v, 2u, 3u, f).is_none());
+        assert_eq!(rposition_between(v, 2u, 4u, f), Some(3u));
+
+        assert!(rposition_between(v, 3u, 3u, f).is_none());
+        assert_eq!(rposition_between(v, 3u, 4u, f), Some(3u));
+
+        assert!(rposition_between(v, 4u, 4u, f).is_none());
+    }
+
+    #[test]
+    fn test_rfind() {
+        assert!(rfind(~[], f).is_none());
+
+        fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
+        fn g(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'd' }
+        let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+
+        assert_eq!(rfind(v, f), Some((3, 'b')));
+        assert!(rfind(v, g).is_none());
+    }
+
+    #[test]
+    fn test_rfind_between() {
+        assert!(rfind_between(~[], 0u, 0u, f).is_none());
+
+        fn f(xy: &(int, char)) -> bool { let (_x, y) = *xy; y == 'b' }
+        let v = ~[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'b')];
+
+        assert!(rfind_between(v, 0u, 0u, f).is_none());
+        assert!(rfind_between(v, 0u, 1u, f).is_none());
+        assert_eq!(rfind_between(v, 0u, 2u, f), Some((1, 'b')));
+        assert_eq!(rfind_between(v, 0u, 3u, f), Some((1, 'b')));
+        assert_eq!(rfind_between(v, 0u, 4u, f), Some((3, 'b')));
+
+        assert!(rfind_between(v, 1u, 1u, f).is_none());
+        assert_eq!(rfind_between(v, 1u, 2u, f), Some((1, 'b')));
+        assert_eq!(rfind_between(v, 1u, 3u, f), Some((1, 'b')));
+        assert_eq!(rfind_between(v, 1u, 4u, f), Some((3, 'b')));
+
+        assert!(rfind_between(v, 2u, 2u, f).is_none());
+        assert!(rfind_between(v, 2u, 3u, f).is_none());
+        assert_eq!(rfind_between(v, 2u, 4u, f), Some((3, 'b')));
+
+        assert!(rfind_between(v, 3u, 3u, f).is_none());
+        assert_eq!(rfind_between(v, 3u, 4u, f), Some((3, 'b')));
+
+        assert!(rfind_between(v, 4u, 4u, f).is_none());
+    }
+
+    #[test]
+    fn test_bsearch_elem() {
+        assert_eq!(bsearch_elem([1,2,3,4,5], &5), Some(4));
+        assert_eq!(bsearch_elem([1,2,3,4,5], &4), Some(3));
+        assert_eq!(bsearch_elem([1,2,3,4,5], &3), Some(2));
+        assert_eq!(bsearch_elem([1,2,3,4,5], &2), Some(1));
+        assert_eq!(bsearch_elem([1,2,3,4,5], &1), Some(0));
+
+        assert_eq!(bsearch_elem([2,4,6,8,10], &1), None);
+        assert_eq!(bsearch_elem([2,4,6,8,10], &5), None);
+        assert_eq!(bsearch_elem([2,4,6,8,10], &4), Some(1));
+        assert_eq!(bsearch_elem([2,4,6,8,10], &10), Some(4));
+
+        assert_eq!(bsearch_elem([2,4,6,8], &1), None);
+        assert_eq!(bsearch_elem([2,4,6,8], &5), None);
+        assert_eq!(bsearch_elem([2,4,6,8], &4), Some(1));
+        assert_eq!(bsearch_elem([2,4,6,8], &8), Some(3));
+
+        assert_eq!(bsearch_elem([2,4,6], &1), None);
+        assert_eq!(bsearch_elem([2,4,6], &5), None);
+        assert_eq!(bsearch_elem([2,4,6], &4), Some(1));
+        assert_eq!(bsearch_elem([2,4,6], &6), Some(2));
+
+        assert_eq!(bsearch_elem([2,4], &1), None);
+        assert_eq!(bsearch_elem([2,4], &5), None);
+        assert_eq!(bsearch_elem([2,4], &2), Some(0));
+        assert_eq!(bsearch_elem([2,4], &4), Some(1));
+
+        assert_eq!(bsearch_elem([2], &1), None);
+        assert_eq!(bsearch_elem([2], &5), None);
+        assert_eq!(bsearch_elem([2], &2), Some(0));
+
+        assert_eq!(bsearch_elem([], &1), None);
+        assert_eq!(bsearch_elem([], &5), None);
+
+        assert!(bsearch_elem([1,1,1,1,1], &1) != None);
+        assert!(bsearch_elem([1,1,1,1,2], &1) != None);
+        assert!(bsearch_elem([1,1,1,2,2], &1) != None);
+        assert!(bsearch_elem([1,1,2,2,2], &1) != None);
+        assert_eq!(bsearch_elem([1,2,2,2,2], &1), Some(0));
+
+        assert_eq!(bsearch_elem([1,2,3,4,5], &6), None);
+        assert_eq!(bsearch_elem([1,2,3,4,5], &0), None);
+    }
+
+    #[test]
+    fn reverse_and_reversed() {
+        let mut v: ~[int] = ~[10, 20];
+        assert_eq!(v[0], 10);
+        assert_eq!(v[1], 20);
+        reverse(v);
+        assert_eq!(v[0], 20);
+        assert_eq!(v[1], 10);
+        let v2 = reversed::<int>(~[10, 20]);
+        assert_eq!(v2[0], 20);
+        assert_eq!(v2[1], 10);
+        v[0] = 30;
+        assert_eq!(v2[0], 20);
+        // Make sure they work with 0-length vectors too.
+
+        let v4 = reversed::<int>(~[]);
+        assert_eq!(v4, ~[]);
+        let mut v3: ~[int] = ~[];
+        reverse::<int>(v3);
+    }
+
+    #[test]
+    fn reversed_mut() {
+        let v2 = reversed::<int>(~[10, 20]);
+        assert_eq!(v2[0], 20);
+        assert_eq!(v2[1], 10);
+    }
+
+    #[test]
+    fn test_split() {
+        fn f(x: &int) -> bool { *x == 3 }
+
+        assert_eq!(split(~[], f), ~[]);
+        assert_eq!(split(~[1, 2], f), ~[~[1, 2]]);
+        assert_eq!(split(~[3, 1, 2], f), ~[~[], ~[1, 2]]);
+        assert_eq!(split(~[1, 2, 3], f), ~[~[1, 2], ~[]]);
+        assert_eq!(split(~[1, 2, 3, 4, 3, 5], f), ~[~[1, 2], ~[4], ~[5]]);
+    }
+
+    #[test]
+    fn test_splitn() {
+        fn f(x: &int) -> bool { *x == 3 }
+
+        assert_eq!(splitn(~[], 1u, f), ~[]);
+        assert_eq!(splitn(~[1, 2], 1u, f), ~[~[1, 2]]);
+        assert_eq!(splitn(~[3, 1, 2], 1u, f), ~[~[], ~[1, 2]]);
+        assert_eq!(splitn(~[1, 2, 3], 1u, f), ~[~[1, 2], ~[]]);
+        assert!(splitn(~[1, 2, 3, 4, 3, 5], 1u, f) ==
+                      ~[~[1, 2], ~[4, 3, 5]]);
+    }
+
+    #[test]
+    fn test_rsplit() {
+        fn f(x: &int) -> bool { *x == 3 }
+
+        assert_eq!(rsplit(~[], f), ~[]);
+        assert_eq!(rsplit(~[1, 2], f), ~[~[1, 2]]);
+        assert_eq!(rsplit(~[1, 2, 3], f), ~[~[1, 2], ~[]]);
+        assert!(rsplit(~[1, 2, 3, 4, 3, 5], f) ==
+            ~[~[1, 2], ~[4], ~[5]]);
+    }
+
+    #[test]
+    fn test_rsplitn() {
+        fn f(x: &int) -> bool { *x == 3 }
+
+        assert_eq!(rsplitn(~[], 1u, f), ~[]);
+        assert_eq!(rsplitn(~[1, 2], 1u, f), ~[~[1, 2]]);
+        assert_eq!(rsplitn(~[1, 2, 3], 1u, f), ~[~[1, 2], ~[]]);
+        assert!(rsplitn(~[1, 2, 3, 4, 3, 5], 1u, f) ==
+                       ~[~[1, 2, 3, 4], ~[5]]);
+    }
+
+    #[test]
+    fn test_partition() {
+        // FIXME (#4355 maybe): using v.partition here crashes
+        assert_eq!(partition(~[], |x: &int| *x < 3), (~[], ~[]));
+        assert!(partition(~[1, 2, 3], |x: &int| *x < 4) ==
+            (~[1, 2, 3], ~[]));
+        assert!(partition(~[1, 2, 3], |x: &int| *x < 2) ==
+            (~[1], ~[2, 3]));
+        assert!(partition(~[1, 2, 3], |x: &int| *x < 0) ==
+            (~[], ~[1, 2, 3]));
+    }
+
+    #[test]
+    fn test_partitioned() {
+        assert_eq!((~[]).partitioned(|x: &int| *x < 3), (~[], ~[]))
+        assert!((~[1, 2, 3]).partitioned(|x: &int| *x < 4) ==
+                     (~[1, 2, 3], ~[]));
+        assert!((~[1, 2, 3]).partitioned(|x: &int| *x < 2) ==
+                     (~[1], ~[2, 3]));
+        assert!((~[1, 2, 3]).partitioned(|x: &int| *x < 0) ==
+                     (~[], ~[1, 2, 3]));
+    }
+
+    #[test]
+    fn test_concat() {
+        assert_eq!(concat(~[~[1], ~[2,3]]), ~[1, 2, 3]);
+    }
+
+    #[test]
+    fn test_connect() {
+        assert_eq!(connect(~[], &0), ~[]);
+        assert_eq!(connect(~[~[1], ~[2, 3]], &0), ~[1, 0, 2, 3]);
+        assert_eq!(connect(~[~[1], ~[2], ~[3]], &0), ~[1, 0, 2, 0, 3]);
+    }
+
+    #[test]
+    fn test_windowed () {
+        fn t(n: uint, expected: &[&[int]]) {
+            let mut i = 0;
+            for windowed(n, ~[1,2,3,4,5,6]) |v| {
+                assert_eq!(v, expected[i]);
+                i += 1;
+            }
+
+            // check that we actually iterated the right number of times
+            assert_eq!(i, expected.len());
+        }
+        t(3, &[&[1,2,3],&[2,3,4],&[3,4,5],&[4,5,6]]);
+        t(4, &[&[1,2,3,4],&[2,3,4,5],&[3,4,5,6]]);
+        t(7, &[]);
+        t(8, &[]);
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_windowed_() {
+        for windowed (0u, ~[1u,2u,3u,4u,5u,6u]) |_v| {}
+    }
+
+    #[test]
+    fn test_unshift() {
+        let mut x = ~[1, 2, 3];
+        x.unshift(0);
+        assert_eq!(x, ~[0, 1, 2, 3]);
+    }
+
+    #[test]
+    fn test_insert() {
+        let mut a = ~[1, 2, 4];
+        a.insert(2, 3);
+        assert_eq!(a, ~[1, 2, 3, 4]);
+
+        let mut a = ~[1, 2, 3];
+        a.insert(0, 0);
+        assert_eq!(a, ~[0, 1, 2, 3]);
+
+        let mut a = ~[1, 2, 3];
+        a.insert(3, 4);
+        assert_eq!(a, ~[1, 2, 3, 4]);
+
+        let mut a = ~[];
+        a.insert(0, 1);
+        assert_eq!(a, ~[1]);
+    }
+
+    #[test]
+    #[ignore(cfg(windows))]
+    #[should_fail]
+    fn test_insert_oob() {
+        let mut a = ~[1, 2, 3];
+        a.insert(4, 5);
+    }
+
+    #[test]
+    fn test_remove() {
+        let mut a = ~[1, 2, 3, 4];
+        a.remove(2);
+        assert_eq!(a, ~[1, 2, 4]);
+
+        let mut a = ~[1, 2, 3];
+        a.remove(0);
+        assert_eq!(a, ~[2, 3]);
+
+        let mut a = ~[1];
+        a.remove(0);
+        assert_eq!(a, ~[]);
+    }
+
+    #[test]
+    #[ignore(cfg(windows))]
+    #[should_fail]
+    fn test_remove_oob() {
+        let mut a = ~[1, 2, 3];
+        a.remove(3);
+    }
+
+    #[test]
+    fn test_capacity() {
+        let mut v = ~[0u64];
+        reserve(&mut v, 10u);
+        assert_eq!(capacity(&v), 10u);
+        let mut v = ~[0u32];
+        reserve(&mut v, 10u);
+        assert_eq!(capacity(&v), 10u);
+    }
+
+    #[test]
+    fn test_slice_2() {
+        let v = ~[1, 2, 3, 4, 5];
+        let v = v.slice(1u, 3u);
+        assert_eq!(v.len(), 2u);
+        assert_eq!(v[0], 2);
+        assert_eq!(v[1], 3);
+    }
+
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_from_fn_fail() {
+        do from_fn(100) |v| {
+            if v == 50 { fail!() }
+            (~0, @0)
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_build_fail() {
+        do build |push| {
+            push((~0, @0));
+            push((~0, @0));
+            push((~0, @0));
+            push((~0, @0));
+            fail!();
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_split_fail_ret_true() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do split(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 1;
+
+            true
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_split_fail_ret_false() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do split(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 1;
+
+            false
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_splitn_fail_ret_true() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do splitn(v, 100) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 1;
+
+            true
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_splitn_fail_ret_false() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do split(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 1;
+
+            false
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_rsplit_fail_ret_true() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do rsplit(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 1;
+
+            true
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_rsplit_fail_ret_false() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do rsplit(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 1;
+
+            false
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_rsplitn_fail_ret_true() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do rsplitn(v, 100) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 1;
+
+            true
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_rsplitn_fail_ret_false() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do rsplitn(v, 100) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 1;
+
+            false
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_consume_fail() {
+        let v = ~[(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do consume(v) |_i, _elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 1;
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_grow_fn_fail() {
+        let mut v = ~[];
+        do v.grow_fn(100) |i| {
+            if i == 50 {
+                fail!()
+            }
+            (~0, @0)
+        }
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_map_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do map(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            ~[(~0, @0)]
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_map_consume_fail() {
+        let v = ~[(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do map_consume(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            ~[(~0, @0)]
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_mapi_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do mapi(v) |_i, _elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            ~[(~0, @0)]
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_flat_map_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do map(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            ~[(~0, @0)]
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_map_zip_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do map_zip(v, v) |_elt1, _elt2| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            ~[(~0, @0)]
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_filter_mapped_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do filter_mapped(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            Some((~0, @0))
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_filter_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do v.filtered |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            true
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_foldl_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do foldl((~0, @0), v) |_a, _b| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            (~0, @0)
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_foldr_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do foldr(v, (~0, @0)) |_a, _b| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            (~0, @0)
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_any_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do any(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            false
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_any2_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do any(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            false
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_all_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do all(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            true
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_alli_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do alli(v) |_i, _elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            true
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_all2_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do all2(v, v) |_elt1, _elt2| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            true
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_find_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do find(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            false
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_position_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do position(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            false
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_rposition_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do rposition(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            false
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_each_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do each(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            false
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_eachi_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        do eachi(v) |_i, _elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+            false
+        };
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    #[allow(non_implicitly_copyable_typarams)]
+    fn test_permute_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        let mut i = 0;
+        for each_permutation(v) |_elt| {
+            if i == 2 {
+                fail!()
+            }
+            i += 0;
+        }
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_as_imm_buf_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        do as_imm_buf(v) |_buf, _i| {
+            fail!()
+        }
+    }
+
+    #[test]
+    #[ignore(windows)]
+    #[should_fail]
+    fn test_as_const_buf_fail() {
+        let v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        do as_const_buf(v) |_buf, _i| {
+            fail!()
+        }
+    }
+
+    #[test]
+    #[ignore(cfg(windows))]
+    #[should_fail]
+    fn test_as_mut_buf_fail() {
+        let mut v = [(~0, @0), (~0, @0), (~0, @0), (~0, @0)];
+        do as_mut_buf(v) |_buf, _i| {
+            fail!()
+        }
+    }
+
+    #[test]
+    #[should_fail]
+    #[ignore(cfg(windows))]
+    fn test_copy_memory_oob() {
+        unsafe {
+            let mut a = [1, 2, 3, 4];
+            let b = [1, 2, 3, 4, 5];
+            raw::copy_memory(a, b, 5);
+        }
+    }
+
+    #[test]
+    fn test_total_ord() {
+        [1, 2, 3, 4].cmp(& &[1, 2, 3]) == Greater;
+        [1, 2, 3].cmp(& &[1, 2, 3, 4]) == Less;
+        [1, 2, 3, 4].cmp(& &[1, 2, 3, 4]) == Equal;
+        [1, 2, 3, 4, 5, 5, 5, 5].cmp(& &[1, 2, 3, 4, 5, 6]) == Less;
+        [2, 2].cmp(& &[1, 2, 3, 4]) == Greater;
+    }
+
+    #[test]
+    fn test_iterator() {
+        use iterator::*;
+        let xs = [1, 2, 5, 10, 11];
+        let ys = [1, 2, 5, 10, 11, 19];
+        let mut it = xs.iter();
+        let mut i = 0;
+        for it.advance |&x| {
+            assert_eq!(x, ys[i]);
+            i += 1;
+        }
+    }
+
+    #[test]
+    fn test_reverse_part() {
+        let mut values = [1,2,3,4,5];
+        reverse_part(values,1,4);
+        assert_eq!(values, [1,4,3,2,5]);
+    }
+
+    #[test]
+    fn test_permutations0() {
+        let values = [];
+        let mut v : ~[~[int]] = ~[];
+        for each_permutation(values) |p| {
+            v.push(p.to_owned());
+        }
+        assert_eq!(v, ~[~[]]);
+    }
+
+    #[test]
+    fn test_permutations1() {
+        let values = [1];
+        let mut v : ~[~[int]] = ~[];
+        for each_permutation(values) |p| {
+            v.push(p.to_owned());
+        }
+        assert_eq!(v, ~[~[1]]);
+    }
+
+    #[test]
+    fn test_permutations2() {
+        let values = [1,2];
+        let mut v : ~[~[int]] = ~[];
+        for each_permutation(values) |p| {
+            v.push(p.to_owned());
+        }
+        assert_eq!(v, ~[~[1,2],~[2,1]]);
+    }
+
+    #[test]
+    fn test_permutations3() {
+        let values = [1,2,3];
+        let mut v : ~[~[int]] = ~[];
+        for each_permutation(values) |p| {
+            v.push(p.to_owned());
+        }
+        assert_eq!(v, ~[~[1,2,3],~[1,3,2],~[2,1,3],~[2,3,1],~[3,1,2],~[3,2,1]]);
+    }
+
+    #[test]
+    fn test_each_val() {
+        use old_iter::CopyableNonstrictIter;
+        let mut i = 0;
+        for [1, 2, 3].each_val |v| {
+            i += v;
+        }
+        assert_eq!(i, 6);
+    }
+}
diff --git a/src/libstd/workcache.rs b/src/libstd/workcache.rs
deleted file mode 100644
index ee57bf2f3a1..00000000000
--- a/src/libstd/workcache.rs
+++ /dev/null
@@ -1,422 +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 json;
-use sha1;
-use serialize::{Encoder, Encodable, Decoder, Decodable};
-use sort;
-
-use core::cell::Cell;
-use core::cmp;
-use core::comm::{PortOne, oneshot, send_one, recv_one};
-use core::either::{Either, Left, Right};
-use core::hashmap::HashMap;
-use core::io;
-use core::run;
-use core::to_bytes;
-use core::util::replace;
-
-/**
-*
-* This is a loose clone of the [fbuild build system](https://github.com/felix-lang/fbuild),
-* made a touch more generic (not wired to special cases on files) and much
-* less metaprogram-y due to rust's comparative weakness there, relative to
-* python.
-*
-* It's based around _imperative builds_ that happen to have some function
-* calls cached. That is, it's _just_ a mechanism for describing cached
-* functions. This makes it much simpler and smaller than a "build system"
-* that produces an IR and evaluates it. The evaluation order is normal
-* function calls. Some of them just return really quickly.
-*
-* A cached function consumes and produces a set of _works_. A work has a
-* name, a kind (that determines how the value is to be checked for
-* freshness) and a value. Works must also be (de)serializable. Some
-* examples of works:
-*
-*    kind   name    value
-*   ------------------------
-*    cfg    os      linux
-*    file   foo.c   <sha1>
-*    url    foo.com <etag>
-*
-* Works are conceptually single units, but we store them most of the time
-* in maps of the form (type,name) => value. These are WorkMaps.
-*
-* A cached function divides the works it's interested in into inputs and
-* outputs, and subdivides those into declared (input) works and
-* discovered (input and output) works.
-*
-* A _declared_ input or is one that is given to the workcache before
-* any work actually happens, in the "prep" phase. Even when a function's
-* work-doing part (the "exec" phase) never gets called, it has declared
-* inputs, which can be checked for freshness (and potentially
-* used to determine that the function can be skipped).
-*
-* The workcache checks _all_ works for freshness, but uses the set of
-* discovered outputs from the _previous_ exec (which it will re-discover
-* and re-record each time the exec phase runs).
-*
-* Therefore the discovered works cached in the db might be a
-* mis-approximation of the current discoverable works, but this is ok for
-* the following reason: we assume that if an artifact A changed from
-* depending on B,C,D to depending on B,C,D,E, then A itself changed (as
-* part of the change-in-dependencies), so we will be ok.
-*
-* Each function has a single discriminated output work called its _result_.
-* This is only different from other works in that it is returned, by value,
-* from a call to the cacheable function; the other output works are used in
-* passing to invalidate dependencies elsewhere in the cache, but do not
-* otherwise escape from a function invocation. Most functions only have one
-* output work anyways.
-*
-* A database (the central store of a workcache) stores a mappings:
-*
-* (fn_name,{declared_input}) => ({discovered_input},
-*                                {discovered_output},result)
-*
-* (Note: fbuild, which workcache is based on, has the concept of a declared
-* output as separate from a discovered output. This distinction exists only
-* as an artifact of how fbuild works: via annotations on function types
-* and metaprogramming, with explicit dependency declaration as a fallback.
-* Workcache is more explicit about dependencies, and as such treats all
-* outputs the same, as discovered-during-the-last-run.)
-*
-*/
-
-#[deriving(Eq, Encodable, Decodable)]
-struct WorkKey {
-    kind: ~str,
-    name: ~str
-}
-
-impl to_bytes::IterBytes for WorkKey {
-    #[inline(always)]
-    fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
-        self.kind.iter_bytes(lsb0, f) && self.name.iter_bytes(lsb0, f)
-    }
-}
-
-impl cmp::Ord for WorkKey {
-    fn lt(&self, other: &WorkKey) -> bool {
-        self.kind < other.kind ||
-            (self.kind == other.kind &&
-             self.name < other.name)
-    }
-    fn le(&self, other: &WorkKey) -> bool {
-        self.lt(other) || self.eq(other)
-    }
-    fn ge(&self, other: &WorkKey) -> bool {
-        self.gt(other) || self.eq(other)
-    }
-    fn gt(&self, other: &WorkKey) -> bool {
-        ! self.le(other)
-    }
-}
-
-pub impl WorkKey {
-    fn new(kind: &str, name: &str) -> WorkKey {
-    WorkKey { kind: kind.to_owned(), name: name.to_owned() }
-    }
-}
-
-struct WorkMap(HashMap<WorkKey, ~str>);
-
-impl WorkMap {
-    fn new() -> WorkMap { WorkMap(HashMap::new()) }
-}
-
-impl<S:Encoder> Encodable<S> for WorkMap {
-    fn encode(&self, s: &mut S) {
-        let mut d = ~[];
-        for self.each |k, v| {
-            d.push((copy *k, copy *v))
-        }
-        sort::tim_sort(d);
-        d.encode(s)
-    }
-}
-
-impl<D:Decoder> Decodable<D> for WorkMap {
-    fn decode(d: &mut D) -> WorkMap {
-        let v : ~[(WorkKey,~str)] = Decodable::decode(d);
-        let mut w = WorkMap::new();
-        for v.each |&(k, v)| {
-            w.insert(copy k, copy v);
-        }
-        w
-    }
-}
-
-struct Database {
-    db_filename: Path,
-    db_cache: HashMap<~str, ~str>,
-    db_dirty: bool
-}
-
-pub impl Database {
-    fn prepare(&mut self,
-               fn_name: &str,
-               declared_inputs: &WorkMap)
-               -> Option<(WorkMap, WorkMap, ~str)> {
-        let k = json_encode(&(fn_name, declared_inputs));
-        match self.db_cache.find(&k) {
-            None => None,
-            Some(v) => Some(json_decode(*v))
-        }
-    }
-
-    fn cache(&mut self,
-             fn_name: &str,
-             declared_inputs: &WorkMap,
-             discovered_inputs: &WorkMap,
-             discovered_outputs: &WorkMap,
-             result: &str) {
-        let k = json_encode(&(fn_name, declared_inputs));
-        let v = json_encode(&(discovered_inputs,
-                              discovered_outputs,
-                              result));
-        self.db_cache.insert(k,v);
-        self.db_dirty = true
-    }
-}
-
-struct Logger {
-    // FIXME #4432: Fill in
-    a: ()
-}
-
-pub impl Logger {
-    fn info(&self, i: &str) {
-        io::println(~"workcache: " + i.to_owned());
-    }
-}
-
-struct Context {
-    db: @mut Database,
-    logger: @mut Logger,
-    cfg: @json::Object,
-    freshness: HashMap<~str,@fn(&str,&str)->bool>
-}
-
-struct Prep {
-    ctxt: @Context,
-    fn_name: ~str,
-    declared_inputs: WorkMap,
-}
-
-struct Exec {
-    discovered_inputs: WorkMap,
-    discovered_outputs: WorkMap
-}
-
-struct Work<T> {
-    prep: @mut Prep,
-    res: Option<Either<T,PortOne<(Exec,T)>>>
-}
-
-fn json_encode<T:Encodable<json::Encoder>>(t: &T) -> ~str {
-    do io::with_str_writer |wr| {
-        let mut encoder = json::Encoder(wr);
-        t.encode(&mut encoder);
-    }
-}
-
-// FIXME(#5121)
-fn json_decode<T:Decodable<json::Decoder>>(s: &str) -> T {
-    do io::with_str_reader(s) |rdr| {
-        let j = result::unwrap(json::from_reader(rdr));
-        let mut decoder = json::Decoder(j);
-        Decodable::decode(&mut decoder)
-    }
-}
-
-fn digest<T:Encodable<json::Encoder>>(t: &T) -> ~str {
-    let mut sha = sha1::sha1();
-    sha.input_str(json_encode(t));
-    sha.result_str()
-}
-
-fn digest_file(path: &Path) -> ~str {
-    let mut sha = sha1::sha1();
-    let s = io::read_whole_file_str(path);
-    sha.input_str(*s.get_ref());
-    sha.result_str()
-}
-
-pub impl Context {
-
-    fn new(db: @mut Database,
-                  lg: @mut Logger,
-                  cfg: @json::Object) -> Context {
-        Context {
-            db: db,
-            logger: lg,
-            cfg: cfg,
-            freshness: HashMap::new()
-        }
-    }
-
-    fn prep<T:Owned +
-              Encodable<json::Encoder> +
-              Decodable<json::Decoder>>( // FIXME(#5121)
-                  @self,
-                  fn_name:&str,
-                  blk: &fn(@mut Prep)->Work<T>) -> Work<T> {
-        let p = @mut Prep {
-            ctxt: self,
-            fn_name: fn_name.to_owned(),
-            declared_inputs: WorkMap::new()
-        };
-        blk(p)
-    }
-}
-
-
-trait TPrep {
-    fn declare_input(&mut self, kind:&str, name:&str, val:&str);
-    fn is_fresh(&self, cat:&str, kind:&str, name:&str, val:&str) -> bool;
-    fn all_fresh(&self, cat:&str, map:&WorkMap) -> bool;
-    fn exec<T:Owned +
-              Encodable<json::Encoder> +
-              Decodable<json::Decoder>>( // FIXME(#5121)
-        &self, blk: ~fn(&Exec) -> T) -> Work<T>;
-}
-
-impl TPrep for Prep {
-    fn declare_input(&mut self, kind:&str, name:&str, val:&str) {
-        self.declared_inputs.insert(WorkKey::new(kind, name),
-                                 val.to_owned());
-    }
-
-    fn is_fresh(&self, cat: &str, kind: &str,
-                name: &str, val: &str) -> bool {
-        let k = kind.to_owned();
-        let f = (*self.ctxt.freshness.get(&k))(name, val);
-        let lg = self.ctxt.logger;
-            if f {
-                lg.info(fmt!("%s %s:%s is fresh",
-                             cat, kind, name));
-            } else {
-                lg.info(fmt!("%s %s:%s is not fresh",
-                             cat, kind, name))
-            }
-        f
-    }
-
-    fn all_fresh(&self, cat: &str, map: &WorkMap) -> bool {
-        for map.each |k, v| {
-            if ! self.is_fresh(cat, k.kind, k.name, *v) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    fn exec<T:Owned +
-              Encodable<json::Encoder> +
-              Decodable<json::Decoder>>( // FIXME(#5121)
-            &self, blk: ~fn(&Exec) -> T) -> Work<T> {
-        let mut bo = Some(blk);
-
-        let cached = self.ctxt.db.prepare(self.fn_name, &self.declared_inputs);
-
-        match cached {
-            Some((ref disc_in, ref disc_out, ref res))
-            if self.all_fresh("declared input",
-                              &self.declared_inputs) &&
-            self.all_fresh("discovered input", disc_in) &&
-            self.all_fresh("discovered output", disc_out) => {
-                Work::new(@mut copy *self, Left(json_decode(*res)))
-            }
-
-            _ => {
-                let (port, chan) = oneshot();
-                let blk = replace(&mut bo, None).unwrap();
-                let chan = Cell(chan);
-
-                do task::spawn {
-                    let exe = Exec {
-                        discovered_inputs: WorkMap::new(),
-                        discovered_outputs: WorkMap::new(),
-                    };
-                    let chan = chan.take();
-                    let v = blk(&exe);
-                    send_one(chan, (exe, v));
-                }
-                Work::new(@mut copy *self, Right(port))
-            }
-        }
-    }
-}
-
-pub impl<T:Owned +
-         Encodable<json::Encoder> +
-         Decodable<json::Decoder>> Work<T> { // FIXME(#5121)
-    fn new(p: @mut Prep, e: Either<T,PortOne<(Exec,T)>>) -> Work<T> {
-        Work { prep: p, res: Some(e) }
-    }
-}
-
-// FIXME (#3724): movable self. This should be in impl Work.
-fn unwrap<T:Owned +
-            Encodable<json::Encoder> +
-            Decodable<json::Decoder>>( // FIXME(#5121)
-        w: Work<T>) -> T {
-    let mut ww = w;
-    let s = replace(&mut ww.res, None);
-
-    match s {
-        None => fail!(),
-        Some(Left(v)) => v,
-        Some(Right(port)) => {
-            let (exe, v) = recv_one(port);
-
-            let s = json_encode(&v);
-
-            let p = &*ww.prep;
-            let db = p.ctxt.db;
-            db.cache(p.fn_name,
-                 &p.declared_inputs,
-                 &exe.discovered_inputs,
-                 &exe.discovered_outputs,
-                 s);
-            v
-        }
-    }
-}
-
-//#[test]
-fn test() {
-    use core::io::WriterUtil;
-
-    let db = @mut Database { db_filename: Path("db.json"),
-                             db_cache: HashMap::new(),
-                             db_dirty: false };
-    let lg = @mut Logger { a: () };
-    let cfg = @HashMap::new();
-    let cx = @Context::new(db, lg, cfg);
-    let w:Work<~str> = do cx.prep("test1") |prep| {
-        let pth = Path("foo.c");
-        {
-            let file = io::file_writer(&pth, [io::Create]).get();
-            file.write_str("int main() { return 0; }");
-        }
-
-        prep.declare_input("file", pth.to_str(), digest_file(&pth));
-        do prep.exec |_exe| {
-            let out = Path("foo.o");
-            run::run_program("gcc", [~"foo.c", ~"-o", out.to_str()]);
-            out.to_str()
-        }
-    };
-    let s = unwrap(w);
-    io::println(s);
-}