]> git.lizzy.rs Git - rust.git/commitdiff
Merge remote-tracking branch 'brson/rt'
authorBrian Anderson <banderson@mozilla.com>
Sun, 24 Mar 2013 22:37:59 +0000 (15:37 -0700)
committerBrian Anderson <banderson@mozilla.com>
Mon, 25 Mar 2013 19:28:54 +0000 (12:28 -0700)
Conflicts:
src/libcore/rt/context.rs
src/libcore/rt/sched.rs
src/libcore/rt/thread.rs
src/libcore/rt/uv.rs

16 files changed:
1  2 
src/compiletest/common.rs
src/compiletest/runtest.rs
src/libcore/rt/context.rs
src/libcore/rt/io/file.rs
src/libcore/rt/rtio.rs
src/libcore/rt/sched.rs
src/libcore/rt/stack.rs
src/libcore/rt/thread.rs
src/libcore/rt/uv/file.rs
src/libcore/rt/uv/mod.rs
src/libcore/rt/uv/net.rs
src/libcore/rt/uvio.rs
src/libcore/rt/uvll.rs
src/libcore/unstable.rs
src/libcore/unstable/lang.rs
src/libstd/uv_ll.rs

Simple merge
Simple merge
index 4798399d5e9489756292f959f736b7da08c1b306,55ea2eb3f50976946a75765f254cda1a502e69b5..527acd4d1b1ba70d1d2cd3a93650a944732bda9f
@@@ -16,17 -17,30 +17,30 @@@ use cast::{transmute, transmute_mut_uns
  // 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.
- pub struct Context(~Registers);
+ // 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 {
 -    static fn empty() -> Context {
 +    fn empty() -> Context {
-         Context(new_regs())
+         Context {
+             start: None,
+             regs: new_regs()
+         }
      }
  
      /// Create a new context that will resume execution by running ~fn()
-     /// # Safety Note
-     /// The `start` closure must remain valid for the life of the Task
-     fn new(start: &~fn(), stack: &mut StackSegment) -> Context {
 -    static fn new(start: ~fn(), stack: &mut StackSegment) -> Context {
++    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)() }
  
          initialize_call_frame(&mut *regs, fp, argp, sp);
  
-         return Context(regs);
+         return Context {
+             start: Some(start),
+             regs: regs
+         }
      }
  
 -    static fn swap(out_context: &mut Context, in_context: &Context) {
+     /* 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(~ref mut r) => r
+             &Context { regs: ~ref mut r, _ } => r
          };
          let in_regs: &Registers = match in_context {
-             &Context(~ref r) => r
+             &Context { regs: ~ref r, _ } => r
          };
  
          unsafe { swap_registers(out_regs, in_regs) };
@@@ -108,14 -129,13 +129,13 @@@ type Registers = [uint * 22]
  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) {
+ fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
  
      // Redefinitions from regs.h
 -    const RUSTRT_ARG0: uint = 3;
 -    const RUSTRT_RSP: uint = 1;
 -    const RUSTRT_IP: uint = 8;
 -    const RUSTRT_RBP: uint = 2;
 +    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);
index 0000000000000000000000000000000000000000,621cdca89e8f428947cdba715984bda0b014e732..9f1f200d8e466bd5ecfdedf9856a02d680db8ada
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,45 +1,45 @@@
 -    static fn new(_path: Path) -> FileStream {
+ // 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::sched::*;
+ use super::super::rtio::*;
+ use super::Stream;
+ pub struct FileStream;
+ pub impl FileStream {
++    fn new(_path: Path) -> FileStream {
+         fail!()
+     }
+ }
+ impl Stream for FileStream {
+     fn read(&mut self, _buf: &mut [u8]) -> uint {
+         fail!()
+     }
+     fn eof(&mut self) -> bool {
+         fail!()
+     }
+     fn write(&mut self, _v: &const [u8]) {
+         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::new(filename);
+     outstream.write(message.to_bytes());
+ }
index 0000000000000000000000000000000000000000,3a94c01e0a4196443073609e02b0d14f11b883a5..55e062de85b06054783f6104a14d538e5c662e77
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,45 +1,45 @@@
 -    fn io(&mut self) -> Option<&self/mut IoFactoryObject>;
+ // 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::*;
+ // XXX: ~object doesn't work currently so these are some placeholder
+ // types to use instead
+ pub type EventLoopObject = super::uvio::UvEventLoop;
+ pub type IoFactoryObject = super::uvio::UvIoFactory;
+ pub type StreamObject = super::uvio::UvStream;
+ pub type TcpListenerObject = super::uvio::UvTcpListener;
+ pub trait EventLoop {
+     fn run(&mut self);
+     fn callback(&mut self, ~fn());
+     /// The asynchronous I/O services. Not all event loops may provide one
++    fn io(&mut self) -> Option<&'self mut IoFactoryObject>;
+ }
+ pub trait IoFactory {
+     fn connect(&mut self, addr: IpAddr) -> Option<~StreamObject>;
+     fn bind(&mut self, addr: IpAddr) -> Option<~TcpListenerObject>;
+ }
+ pub trait TcpListener {
+     fn listen(&mut self) -> Option<~StreamObject>;
+ }
+ pub trait Stream {
+     fn read(&mut self, buf: &mut [u8]) -> Result<uint, ()>;
+     fn write(&mut self, buf: &[u8]) -> Result<(), ()>;
+ }
+ pub enum IpAddr {
+     Ipv4(u8, u8, u8, u8, u16),
+     Ipv6
+ }
index 0beadb30d42c6534c80aecf8f9f557020d9db53b,312c6655f55f378a5013b9eb6dc397c48a933a86..5034ffa3c6045ad99bf6146f2db9ffdf5e6ecc23
@@@ -70,7 -70,14 +70,14 @@@ enum CleanupJob 
  
  pub impl Scheduler {
  
-     pub fn new(event_loop: ~EventLoopObject) -> Scheduler {
 -    static fn new(event_loop: ~EventLoopObject) -> Scheduler {
++    fn new(event_loop: ~EventLoopObject) -> Scheduler {
+         // Lazily initialize the global state, currently the scheduler TLS key
+         unsafe { rust_initialize_global_state(); }
+         extern {
+             fn rust_initialize_global_state();
+         }
          Scheduler {
              event_loop: event_loop,
              task_queue: WorkQueue::new(),
      }
  }
  
 -const TASK_MIN_STACK_SIZE: uint = 10000000; // XXX: Too much stack
 +static TASK_MIN_STACK_SIZE: uint = 10000000; // XXX: Too much stack
  
  pub struct Task {
-     /// The task entry point, saved here for later destruction
-     priv start: ~~fn(),
      /// The segment of stack on which the task is currently running or,
      /// if the task is blocked, on which the task will resume execution
      priv current_stack_segment: StackSegment,
      priv saved_context: Context,
  }
  
--impl Task {
-     pub fn new(stack_pool: &mut StackPool, start: ~fn()) -> Task {
-         // XXX: Putting main into a ~ so it's a thin pointer and can
-         // be passed to the spawn function.  Another unfortunate
-         // allocation
-         let start = ~Task::build_start_wrapper(start);
 -    static fn new(stack_pool: &mut StackPool, start: ~fn()) -> Task {
++pub impl Task {
++    fn new(stack_pool: &mut StackPool, start: ~fn()) -> Task {
+         let start = Task::build_start_wrapper(start);
          let mut stack = stack_pool.take_segment(TASK_MIN_STACK_SIZE);
          // NB: Context holds a pointer to that ~fn
-         let initial_context = Context::new(&*start, &mut stack);
+         let initial_context = Context::new(start, &mut stack);
          return Task {
-             start: start,
              current_stack_segment: stack,
              saved_context: initial_context,
          };
Simple merge
index c45e4295ab144d5209d02c5a96cd3f8d844f02ad,5eb951be7848c1df63ca1422f13f216b9b597582..910e445f47b049716b5f2d7cb0e6545b9e74acb1
@@@ -19,8 -19,8 +19,8 @@@ pub struct Thread 
      raw_thread: *raw_thread
  }
  
- impl Thread {
-     pub fn start(main: ~fn()) -> Thread {
+ pub impl Thread {
 -    static fn start(main: ~fn()) -> Thread {
++    fn start(main: ~fn()) -> Thread {
          fn substart(main: &fn()) -> *raw_thread {
              unsafe { rust_raw_thread_start(&main) }
          }
index 0000000000000000000000000000000000000000,3a7b7f135d5862c56cc58a409798f61ad9808e9b..7df06f87dfe41b11710e20ad2910a4409eefdd64
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,52 +1,52 @@@
 -    static fn new() -> FsRequest {
+ // 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 super::{UvError, Callback, Request, NativeHandle, Loop};
+ use super::super::uvll;
+ use super::super::uvll::*;
+ pub type FsCallback = ~fn(FsRequest, Option<UvError>);
+ impl Callback for FsCallback { }
+ pub struct FsRequest(*uvll::uv_fs_t);
+ impl Request for FsRequest;
+ impl FsRequest {
 -    static fn from_native_handle(handle: *uvll:: uv_fs_t) -> FsRequest {
++    fn new() -> FsRequest {
+         let fs_req = unsafe { malloc_req(UV_FS) };
+         fail_unless!(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 }
+     }
+ }
index 0000000000000000000000000000000000000000,c44998532ebaaf60b04884bc63aa71d3716aacd8..28d695273e7c7b8e392dc63da47efa6f70633413
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,456 +1,456 @@@
 -    static pub fn from_native_handle(T) -> Self;
+ // 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.
+ 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 option::*;
+ use str::raw::from_c_str;
+ use to_str::ToStr;
+ use vec;
+ use ptr;
+ use libc::{c_void, c_int, size_t, malloc, free, ssize_t};
+ use cast::{transmute, transmute_mut_region};
+ use ptr::null;
+ use sys::size_of;
+ use super::uvll;
+ use super::uvll::*;
+ use unstable::finally::Finally;
+ #[cfg(test)] use unstable::run_in_bare_thread;
+ #[cfg(test)] use super::thread::Thread;
+ #[cfg(test)] use cell::Cell;
+ pub use self::file::{FsRequest, FsCallback};
+ pub use self::net::{StreamWatcher, TcpWatcher};
+ pub use self::net::{ReadCallback, AllocCallback, ConnectionCallback, ConnectCallback};
+ pub mod file;
+ pub mod net;
+ /// A trait for callbacks to implement. Provides a little extra type safety
+ /// for generic, unsafe interop functions like `set_watcher_callback`.
+ pub trait Callback { }
+ pub trait Request { }
+ /// 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 {
+     fn event_loop(&self) -> Loop;
+ }
+ pub type NullCallback = ~fn();
+ impl Callback for NullCallback { }
+ /// A type that wraps a native handle
+ pub trait NativeHandle<T> {
 -    static fn new() -> Loop {
++    pub fn from_native_handle(T) -> Self;
+     pub fn native_handle(&self) -> T;
+ }
+ /// 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
+ }
+ pub impl Loop {
 -    static fn from_native_handle(handle: *uvll::uv_loop_t) -> Loop {
++    fn new() -> Loop {
+         let handle = unsafe { uvll::loop_new() };
+         fail_unless!(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 {
 -    static fn new(loop_: &mut Loop) -> IdleWatcher {
++    fn from_native_handle(handle: *uvll::uv_loop_t) -> Loop {
+         Loop { handle: handle }
+     }
+     fn native_handle(&self) -> *uvll::uv_loop_t {
+         self.handle
+     }
+ }
+ pub struct IdleWatcher(*uvll::uv_idle_t);
+ impl Watcher for IdleWatcher {
+     fn event_loop(&self) -> Loop {
+         loop_from_watcher(self)
+     }
+ }
+ pub type IdleCallback = ~fn(IdleWatcher, Option<UvError>);
+ impl Callback for IdleCallback { }
+ pub impl IdleWatcher {
 -    static fn from_native_handle(handle: *uvll::uv_idle_t) -> IdleWatcher {
++    fn new(loop_: &mut Loop) -> IdleWatcher {
+         unsafe {
+             let handle = uvll::idle_new();
+             fail_unless!(handle.is_not_null());
+             fail_unless!(0 == uvll::idle_init(loop_.native_handle(), handle));
+             uvll::set_data_for_uv_handle(handle, null::<()>());
+             NativeHandle::from_native_handle(handle)
+         }
+     }
+     fn start(&mut self, cb: IdleCallback) {
+         set_watcher_callback(self, cb);
+         unsafe {
+             fail_unless!(0 == uvll::idle_start(self.native_handle(), idle_cb))
+         };
+         extern fn idle_cb(handle: *uvll::uv_idle_t, status: c_int) {
+             let idle_watcher: IdleWatcher = NativeHandle::from_native_handle(handle);
+             let cb: &IdleCallback = borrow_callback_from_watcher(&idle_watcher);
+             let status = status_to_maybe_uv_error(handle, status);
+             (*cb)(idle_watcher, status);
+         }
+     }
+     fn stop(&mut self) {
+         unsafe { fail_unless!(0 == uvll::idle_stop(self.native_handle())); }
+     }
+     fn close(self) {
+         unsafe { uvll::close(self.native_handle(), close_cb) };
+         extern fn close_cb(handle: *uvll::uv_idle_t) {
+             let mut idle_watcher = NativeHandle::from_native_handle(handle);
+             drop_watcher_callback::<uvll::uv_idle_t, IdleWatcher, IdleCallback>(&mut idle_watcher);
+             unsafe { uvll::idle_delete(handle) };
+         }
+     }
+ }
+ impl NativeHandle<*uvll::uv_idle_t> for IdleWatcher {
 -    pure fn name(&self) -> ~str {
++    fn from_native_handle(handle: *uvll::uv_idle_t) -> IdleWatcher {
+         IdleWatcher(handle)
+     }
+     fn native_handle(&self) -> *uvll::uv_idle_t {
+         match self { &IdleWatcher(ptr) => ptr }
+     }
+ }
+ // 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 {
 -    pure fn desc(&self) -> ~str {
++    fn name(&self) -> ~str {
+         unsafe {
+             let inner = match self { &UvError(ref a) => a };
+             let name_str = uvll::err_name(inner);
+             fail_unless!(name_str.is_not_null());
+             from_c_str(name_str)
+         }
+     }
 -    pure fn to_str(&self) -> ~str {
++    fn desc(&self) -> ~str {
+         unsafe {
+             let inner = match self { &UvError(ref a) => a };
+             let desc_str = uvll::strerror(inner);
+             fail_unless!(desc_str.is_not_null());
+             from_c_str(desc_str)
+         }
+     }
+ }
+ impl ToStr for UvError {
 -    watcher: &r/mut W) -> &r/mut WatcherData {
++    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);
+     fail_unless!(err.to_str() == ~"EOF: end of file");
+ }
+ /// 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))
+         }
+     }
+ }
+ /// Get the uv event loop from a Watcher
+ pub fn loop_from_watcher<H, W: Watcher + NativeHandle<*H>>(
+     watcher: &W) -> Loop {
+     let handle = watcher.native_handle();
+     let loop_ = unsafe { uvll::get_loop_for_uv_handle(handle) };
+     NativeHandle::from_native_handle(loop_)
+ }
+ /// Set the custom data on a handle to a callback Note: This is only
+ /// suitable for watchers that make just one type of callback.  For
+ /// others use WatcherData
+ pub fn set_watcher_callback<H, W: Watcher + NativeHandle<*H>, CB: Callback>(
+     watcher: &mut W, cb: CB) {
+     drop_watcher_callback::<H, W, CB>(watcher);
+     // XXX: Boxing the callback so it fits into a
+     // pointer. Unfortunate extra allocation
+     let boxed_cb = ~cb;
+     let data = unsafe { transmute::<~CB, *c_void>(boxed_cb) };
+     unsafe { uvll::set_data_for_uv_handle(watcher.native_handle(), data) };
+ }
+ /// Delete a callback from a handle's custom data
+ pub fn drop_watcher_callback<H, W: Watcher + NativeHandle<*H>, CB: Callback>(
+     watcher: &mut W) {
+     unsafe {
+         let handle = watcher.native_handle();
+         let handle_data: *c_void = uvll::get_data_for_uv_handle(handle);
+         if handle_data.is_not_null() {
+             // Take ownership of the callback and drop it
+             let _cb = transmute::<*c_void, ~CB>(handle_data);
+             // Make sure the pointer is zeroed
+             uvll::set_data_for_uv_handle(watcher.native_handle(), null::<()>());
+         }
+     }
+ }
+ /// Take a pointer to the callback installed as custom data
+ pub fn borrow_callback_from_watcher<H, W: Watcher + NativeHandle<*H>,
+                                 CB: Callback>(watcher: &W) -> &CB {
+     unsafe {
+         let handle = watcher.native_handle();
+         let handle_data: *c_void = uvll::get_data_for_uv_handle(handle);
+         fail_unless!(handle_data.is_not_null());
+         let cb = transmute::<&*c_void, &~CB>(&handle_data);
+         return &**cb;
+     }
+ }
+ /// Take ownership of the callback installed as custom data
+ pub fn take_callback_from_watcher<H, W: Watcher + NativeHandle<*H>, CB: Callback>(
+     watcher: &mut W) -> CB {
+     unsafe {
+         let handle = watcher.native_handle();
+         let handle_data: *c_void = uvll::get_data_for_uv_handle(handle);
+         fail_unless!(handle_data.is_not_null());
+         uvll::set_data_for_uv_handle(handle, null::<()>());
+         let cb: ~CB = transmute::<*c_void, ~CB>(handle_data);
+         let cb = match cb { ~cb => cb };
+         return cb;
+     }
+ }
+ /// 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>
+ }
+ pub fn install_watcher_data<H, W: Watcher + NativeHandle<*H>>(watcher: &mut W) {
+     unsafe {
+         let data = ~WatcherData {
+             read_cb: None,
+             write_cb: None,
+             connect_cb: None,
+             close_cb: None,
+             alloc_cb: None
+         };
+         let data = transmute::<~WatcherData, *c_void>(data);
+         uvll::set_data_for_uv_handle(watcher.native_handle(), data);
+     }
+ }
+ pub fn get_watcher_data<H, W: Watcher + NativeHandle<*H>>(
++    watcher: &'r mut W) -> &'r mut WatcherData {
+     unsafe {
+         let data = uvll::get_data_for_uv_handle(watcher.native_handle());
+         let data = transmute::<&*c_void, &mut ~WatcherData>(&data);
+         return &mut **data;
+     }
+ }
+ pub fn drop_watcher_data<H, W: Watcher + NativeHandle<*H>>(watcher: &mut W) {
+     unsafe {
+         let data = uvll::get_data_for_uv_handle(watcher.native_handle());
+         let _data = transmute::<*c_void, ~WatcherData>(data);
+         uvll::set_data_for_uv_handle(watcher.native_handle(), null::<()>());
+     }
+ }
+ #[test]
+ fn test_slice_to_uv_buf() {
+     let slice = [0, .. 20];
+     let buf = slice_to_uv_buf(slice);
+     fail_unless!(buf.len == 20);
+     unsafe {
+         let base = transmute::<*u8, *mut u8>(buf.base);
+         (*base) = 1;
+         (*ptr::mut_offset(base, 1)) = 2;
+     }
+     fail_unless!(slice[0] == 1);
+     fail_unless!(slice[1] == 2);
+ }
+ /// 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 = unsafe { 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 {
+     let data = unsafe { malloc(v.len() as size_t) } as *u8;
+     fail_unless!(data.is_not_null());
+     do vec::as_imm_buf(v) |b, l| {
+         let data = data as *mut u8;
+         unsafe { ptr::copy_memory(data, b, l) }
+     }
+     let buf = unsafe { uvll::buf_init(data, v.len()) };
+     return buf;
+ }
+ /// 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
+         return None;
+     }
+ }
+ #[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 mut 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;
+             fail_unless!(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();
+         fail_unless!(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;
+             fail_unless!(status.is_none());
+             idle_watcher.stop();
+             do idle_watcher.start |idle_watcher, status| {
+                 fail_unless!(status.is_none());
+                 let mut idle_watcher = idle_watcher;
+                 idle_watcher.stop();
+                 idle_watcher.close();
+             }
+         }
+         loop_.run();
+         loop_.close();
+     }
+ }
index 0000000000000000000000000000000000000000,bcbb1b2d02e4212bf24e43b97fd7eab5e59ceb72..8f0e8c3edd50d166a3f4621b105f5caa82810c96
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,483 +1,483 @@@
 -    static fn from_native_handle(
+ // 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 cast::{transmute, transmute_mut_region};
+ use super::super::uvll;
+ use super::super::uvll::*;
+ use super::{Loop, Watcher, Request, UvError, Buf, Callback, NativeHandle, NullCallback,
+             loop_from_watcher, status_to_maybe_uv_error,
+             install_watcher_data, get_watcher_data, drop_watcher_data,
+             vec_to_uv_buf, vec_from_uv_buf};
+ use super::super::rtio::{IpAddr, Ipv4, Ipv6};
+ #[cfg(test)]
+ use unstable::run_in_bare_thread;
+ #[cfg(test)]
+ use super::super::thread::Thread;
+ #[cfg(test)]
+ use cell::Cell;
+ fn ip4_as_uv_ip4(addr: IpAddr, f: &fn(*sockaddr_in)) {
+     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 {
+     fn event_loop(&self) -> Loop {
+         loop_from_watcher(self)
+     }
+ }
+ pub type ReadCallback = ~fn(StreamWatcher, int, Buf, Option<UvError>);
+ impl Callback for ReadCallback { }
+ // XXX: The uv alloc callback also has a *uv_handle_t arg
+ pub type AllocCallback = ~fn(uint) -> Buf;
+ impl Callback for AllocCallback { }
+ pub impl StreamWatcher {
+     fn read_start(&mut self, alloc: AllocCallback, cb: ReadCallback) {
+         // XXX: Borrowchk problems
+         let data = get_watcher_data(unsafe { transmute_mut_region(self) });
+         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 = get_watcher_data(&mut stream_watcher);
+             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 = get_watcher_data(&mut stream_watcher);
+             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); }
+     }
+     // XXX: Needs to take &[u8], not ~[u8]
+     fn write(&mut self, msg: ~[u8], cb: ConnectionCallback) {
+         // XXX: Borrowck
+         let data = get_watcher_data(unsafe { transmute_mut_region(self) });
+         fail_unless!(data.write_cb.is_none());
+         data.write_cb = Some(cb);
+         let req = WriteRequest::new();
+         let buf = vec_to_uv_buf(msg);
+         // XXX: Allocation
+         let bufs = ~[buf];
+         unsafe {
+             fail_unless!(0 == uvll::write(req.native_handle(),
+                                           self.native_handle(),
+                                           &bufs, write_cb));
+         }
+         // XXX: Freeing immediately after write. Is this ok?
+         let _v = vec_from_uv_buf(buf);
+         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 = get_watcher_data(&mut stream_watcher).write_cb.swap_unwrap();
+             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 {
+             fail_unless!(0 == uvll::accept(self_handle, stream_handle));
+         }
+     }
+     fn close(self, cb: NullCallback) {
+         {
+             let mut self = self;
+             let data = get_watcher_data(&mut self);
+             fail_unless!(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 mut data = get_watcher_data(&mut stream_watcher);
+                 data.close_cb.swap_unwrap()();
+             }
+             drop_watcher_data(&mut stream_watcher);
+             unsafe { free_handle(handle as *c_void) }
+         }
+     }
+ }
+ impl NativeHandle<*uvll::uv_stream_t> for StreamWatcher {
 -    static fn new(loop_: &mut Loop) -> TcpWatcher {
++    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 {
+     fn event_loop(&self) -> Loop {
+         loop_from_watcher(self)
+     }
+ }
+ pub type ConnectionCallback = ~fn(StreamWatcher, Option<UvError>);
+ impl Callback for ConnectionCallback { }
+ pub impl TcpWatcher {
 -            const BACKLOG: c_int = 128; // XXX should be configurable
++    fn new(loop_: &mut Loop) -> TcpWatcher {
+         unsafe {
+             let handle = malloc_handle(UV_TCP);
+             fail_unless!(handle.is_not_null());
+             fail_unless!(0 == uvll::tcp_init(loop_.native_handle(), handle));
+             let mut watcher = NativeHandle::from_native_handle(handle);
+             install_watcher_data(&mut watcher);
+             return watcher;
+         }
+     }
+     fn bind(&mut self, address: IpAddr) {
+         match address {
+             Ipv4(*) => {
+                 do ip4_as_uv_ip4(address) |addr| {
+                     let result = unsafe {
+                         uvll::tcp_bind(self.native_handle(), addr)
+                     };
+                     // XXX: bind is likely to fail. need real error handling
+                     fail_unless!(result == 0);
+                 }
+             }
+             _ => fail!()
+         }
+     }
+     fn connect(&mut self, address: IpAddr, cb: ConnectionCallback) {
+         unsafe {
+             fail_unless!(get_watcher_data(self).connect_cb.is_none());
+             get_watcher_data(self).connect_cb = Some(cb);
+             let mut connect_watcher = ConnectRequest::new();
+             let connect_handle = connect_watcher.native_handle();
+             match address {
+                 Ipv4(*) => {
+                     do ip4_as_uv_ip4(address) |addr| {
+                         rtdebug!("connect_t: %x", connect_handle as uint);
+                         fail_unless!(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 = get_watcher_data(&mut stream_watcher);
+                     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) {
+         // XXX: Borrowck
+         let data = get_watcher_data(unsafe { transmute_mut_region(self) });
+         fail_unless!(data.connect_cb.is_none());
+         data.connect_cb = Some(cb);
+         unsafe {
 -    static fn from_native_handle(handle: *uvll::uv_tcp_t) -> TcpWatcher {
++            static BACKLOG: c_int = 128; // XXX should be configurable
+             // XXX: This can probably fail
+             fail_unless!(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 cb = get_watcher_data(&mut stream_watcher).connect_cb.swap_unwrap();
+             let status = status_to_maybe_uv_error(stream_watcher.native_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 {
 -    static fn new() -> ConnectRequest {
++    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 }
+     }
+ }
+ pub type ConnectCallback = ~fn(ConnectRequest, Option<UvError>);
+ impl Callback for ConnectCallback { }
+ // uv_connect_t is a subclass of uv_req_t
+ struct ConnectRequest(*uvll::uv_connect_t);
+ impl Request for ConnectRequest { }
+ impl ConnectRequest {
 -    static fn from_native_handle(
++    fn new() -> ConnectRequest {
+         let connect_handle = unsafe {
+             malloc_req(UV_CONNECT)
+         };
+         fail_unless!(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 {
 -    static fn new() -> WriteRequest {
++    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 {
 -    static fn from_native_handle(handle: *uvll:: uv_write_t) -> WriteRequest {
++    fn new() -> WriteRequest {
+         let write_handle = unsafe {
+             malloc_req(UV_WRITE)
+         };
+         fail_unless!(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 {
 -        const MAX: int = 10;
++    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 }
+     }
+ }
+ #[test]
+ #[ignore(reason = "ffi struct issues")]
+ 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 = Ipv4(127, 0, 0, 1, 2923);
+         do tcp_watcher.connect(addr) |stream_watcher, status| {
+             rtdebug!("tcp_watcher.connect!");
+             fail_unless!(status.is_some());
+             fail_unless!(status.get().name() == ~"ECONNREFUSED");
+             stream_watcher.close(||());
+         }
+         loop_.run();
+         loop_.close();
+     }
+ }
+ #[test]
+ #[ignore(reason = "need a server to connect to")]
+ fn connect_read() {
+     do run_in_bare_thread() {
+         let mut loop_ = Loop::new();
+         let mut tcp_watcher = { TcpWatcher::new(&mut loop_) };
+         let addr = Ipv4(127, 0, 0, 1, 2924);
+         do tcp_watcher.connect(addr) |stream_watcher, status| {
+             let mut stream_watcher = stream_watcher;
+             rtdebug!("tcp_watcher.connect!");
+             fail_unless!(status.is_none());
+             let alloc: AllocCallback = |size| {
+                 vec_to_uv_buf(vec::from_elem(size, 0))
+             };
+             do stream_watcher.read_start(alloc)
+                 |stream_watcher, nread, buf, status| {
+                 let buf = vec_from_uv_buf(buf);
+                 rtdebug!("read cb!");
+                 if status.is_none() {
+                     let bytes = buf.unwrap();
+                     rtdebug!("%s", bytes.slice(0, nread as uint).to_str());
+                 } else {
+                     rtdebug!("status after read: %s", status.get().to_str());
+                     rtdebug!("closing");
+                     stream_watcher.close(||());
+                 }
+             }
+         }
+         loop_.run();
+         loop_.close();
+     }
+ }
+ #[test]
+ #[ignore(reason = "ffi struct issues")]
+ fn listen() {
+     do run_in_bare_thread() {
 -                    for buf.view(0, nread as uint).each |byte| {
++        static MAX: int = 10;
+         let mut loop_ = Loop::new();
+         let mut server_tcp_watcher = { TcpWatcher::new(&mut loop_) };
+         let addr = Ipv4(127, 0, 0, 1, 2925);
+         server_tcp_watcher.bind(addr);
+         let loop_ = loop_;
+         rtdebug!("listening");
+         do server_tcp_watcher.listen |server_stream_watcher, status| {
+             rtdebug!("listened!");
+             fail_unless!(status.is_none());
+             let mut server_stream_watcher = server_stream_watcher;
+             let mut loop_ = loop_;
+             let mut 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| {
+                         fail_unless!(*byte == count as u8);
+                         rtdebug!("%u", *byte as uint);
+                         count += 1;
+                     }
+                 } else {
+                     fail_unless!(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");
+                 fail_unless!(status.is_none());
+                 let mut stream_watcher = stream_watcher;
+                 let msg = ~[0, 1, 2, 3, 4, 5, 6 ,7 ,8, 9];
+                 do stream_watcher.write(msg) |stream_watcher, status| {
+                     rtdebug!("writing");
+                     fail_unless!(status.is_none());
+                     stream_watcher.close(||());
+                 }
+             }
+             loop_.run();
+             loop_.close();
+         };
+         let mut loop_ = loop_;
+         loop_.run();
+         loop_.close();
+     }
+ }
Simple merge
index 0000000000000000000000000000000000000000,a91e37d92e4cdc3217a8005603eda59140c2e6b9..5111b2bdc1d2226801cb3db31ccc32a9b93a0553
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,442 +1,442 @@@
 -#[deriving_eq]
+ // 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::*;
+ use ptr::to_unsafe_ptr;
+ 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]
++#[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 {
+     fail_unless!(handle != UV_UNKNOWN_HANDLE && handle != UV_HANDLE_TYPE_MAX);
+     let size = unsafe { rust_uv_handle_size(handle as uint) };
+     let p = malloc(size);
+     fail_unless!(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 {
+     fail_unless!(req != UV_UNKNOWN_REQ && req != UV_REQ_TYPE_MAX);
+     let size = unsafe { rust_uv_req_size(req as uint) };
+     let p = malloc(size);
+     fail_unless!(p.is_not_null());
+     return p;
+ }
+ pub unsafe fn free_req(v: *c_void) {
+     free(v)
+ }
+ #[test]
+ fn handle_sanity_check() {
+     unsafe {
+         fail_unless!(UV_HANDLE_TYPE_MAX as uint == rust_uv_handle_type_max());
+     }
+ }
+ #[test]
+ fn request_sanity_check() {
+     unsafe {
+         fail_unless!(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 = vec::len(*buf_in) 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::addr_of(&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::addr_of(&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::addr_of(&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;
+ }
Simple merge
Simple merge
index 0000000000000000000000000000000000000000,b89441d055d77c71a4cd7ea5739a558d5d6d6095..57d769d707e677fce24c9626ffab2f169e4372b3
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1921 +1,1919 @@@
 -    use prelude::*;
+ // 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::prelude::*;
+ 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 becuse 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 becuse 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_tcp_t_32bit_unix_riders,
+         uv_timer_t_32bit_unix_riders,
+         uv_write_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 mod rustrt {
+     // 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::c_uint,
+         repeat: libc::c_uint) -> 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 rustrt::rust_uv_loop_new();
+ }
+ pub unsafe fn loop_delete(loop_handle: *libc::c_void) {
+     rustrt::rust_uv_loop_delete(loop_handle);
+ }
+ pub unsafe fn run(loop_handle: *libc::c_void) {
+     rustrt::rust_uv_run(loop_handle);
+ }
+ pub unsafe fn close<T>(handle: *T, cb: *u8) {
+     rustrt::rust_uv_close(handle as *libc::c_void, cb);
+ }
+ pub unsafe fn walk(loop_handle: *libc::c_void, cb: *u8, arg: *libc::c_void) {
+     rustrt::rust_uv_walk(loop_handle, cb, arg);
+ }
+ pub unsafe fn idle_new() -> *uv_idle_t {
+     rustrt::rust_uv_idle_new()
+ }
+ pub unsafe fn idle_delete(handle: *uv_idle_t) {
+     rustrt::rust_uv_idle_delete(handle)
+ }
+ pub unsafe fn idle_init(loop_handle: *uv_loop_t,
+                         handle: *uv_idle_t) -> libc::c_int {
+     rustrt::rust_uv_idle_init(loop_handle, handle)
+ }
+ pub unsafe fn idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> libc::c_int {
+     rustrt::rust_uv_idle_start(handle, cb)
+ }
+ pub unsafe fn idle_stop(handle: *uv_idle_t) -> libc::c_int {
+     rustrt::rust_uv_idle_stop(handle)
+ }
+ pub unsafe fn tcp_init(loop_handle: *libc::c_void, handle: *uv_tcp_t)
+     -> libc::c_int {
+     return rustrt::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 rustrt::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 rustrt::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 rustrt::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 rustrt::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 rustrt::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 rustrt::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 rustrt::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 rustrt::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 rustrt::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 rustrt::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 rustrt::rust_uv_read_stop(stream as *libc::c_void);
+ }
+ pub unsafe fn last_error(loop_handle: *libc::c_void) -> uv_err_t {
+     return rustrt::rust_uv_last_error(loop_handle);
+ }
+ pub unsafe fn strerror(err: *uv_err_t) -> *libc::c_char {
+     return rustrt::rust_uv_strerror(err);
+ }
+ pub unsafe fn err_name(err: *uv_err_t) -> *libc::c_char {
+     return rustrt::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 rustrt::rust_uv_async_init(loop_handle,
+                                    async_handle,
+                                    cb);
+ }
+ pub unsafe fn async_send(async_handle: *uv_async_t) {
+     return rustrt::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 = ptr::addr_of(&out_buf);
+     rustrt::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| {
+         rustrt::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| {
+         rustrt::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| {
+         rustrt::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 = rustrt::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 {
+     rustrt::rust_uv_ip4_port(to_unsafe_ptr(src)) as uint
+ }
+ pub unsafe fn ip6_port(src: &sockaddr_in6) -> uint {
+     rustrt::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 rustrt::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 rustrt::rust_uv_timer_start(timer_ptr, cb, timeout as libc::c_uint,
+                                     repeat as libc::c_uint);
+ }
+ pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> libc::c_int {
+     return rustrt::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 {
+     rustrt::rust_uv_getaddrinfo(loop_ptr,
+                            handle,
+                            cb,
+                            node_name_ptr,
+                            service_name_ptr,
+                            hints)
+ }
+ pub unsafe fn freeaddrinfo(res: *addrinfo) {
+     rustrt::rust_uv_freeaddrinfo(res);
+ }
+ // libuv struct initializers
+ pub unsafe fn tcp_t() -> uv_tcp_t {
+     return uv_ll_struct_stubgen::gen_stub_uv_tcp_t();
+ }
+ pub unsafe fn connect_t() -> uv_connect_t {
+     return uv_ll_struct_stubgen::gen_stub_uv_connect_t();
+ }
+ pub unsafe fn write_t() -> uv_write_t {
+     return uv_ll_struct_stubgen::gen_stub_uv_write_t();
+ }
+ pub unsafe fn async_t() -> uv_async_t {
+     return uv_ll_struct_stubgen::gen_stub_uv_async_t();
+ }
+ pub unsafe fn timer_t() -> uv_timer_t {
+     return uv_ll_struct_stubgen::gen_stub_uv_timer_t();
+ }
+ pub unsafe 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 rustrt::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 rustrt::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 rustrt::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 {
+     rustrt::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) {
+     rustrt::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 rustrt::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) {
+     rustrt::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 rustrt::rust_uv_get_data_for_req(req as *libc::c_void);
+ }
+ pub unsafe fn set_data_for_req<T, U>(req: *T,
+                     data: *U) {
+     rustrt::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 rustrt::rust_uv_get_base_from_buf(buf);
+ }
+ pub unsafe fn get_len_from_buf(buf: uv_buf_t) -> libc::size_t {
+     return rustrt::rust_uv_get_len_from_buf(buf);
+ }
+ pub unsafe fn malloc_buf_base_of(suggested_size: libc::size_t)
+     -> *u8 {
+     return rustrt::rust_uv_malloc_buf_base_of(suggested_size);
+ }
+ pub unsafe fn free_base_of_buf(buf: uv_buf_t) {
+     rustrt::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 = ptr::addr_of(&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 = ptr::addr_of(&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 {
+     rustrt::rust_uv_is_ipv4_addrinfo(input)
+ }
+ pub unsafe fn is_ipv6_addrinfo(input: *addrinfo) -> bool {
+     rustrt::rust_uv_is_ipv6_addrinfo(input)
+ }
+ pub unsafe fn get_INADDR_NONE() -> u32 {
+     rustrt::rust_uv_helper_get_INADDR_NONE()
+ }
+ pub unsafe fn get_next_addrinfo(input: *addrinfo) -> *addrinfo {
+     rustrt::rust_uv_get_next_addrinfo(input)
+ }
+ pub unsafe fn addrinfo_as_sockaddr_in(input: *addrinfo) -> *sockaddr_in {
+     rustrt::rust_uv_addrinfo_as_sockaddr_in(input)
+ }
+ pub unsafe fn addrinfo_as_sockaddr_in6(input: *addrinfo) -> *sockaddr_in6 {
+     rustrt::rust_uv_addrinfo_as_sockaddr_in6(input)
+ }
+ #[cfg(test)]
+ pub mod test {
 -    use comm::{SharedChan, stream, GenericChan, GenericPort};
++    use core::prelude::*;
++    use core::comm::{SharedChan, stream, GenericChan, GenericPort};
+     use super::*;
 -        log(debug, fmt!("after uv_close! handle ptr: %?",
 -                        handle));
+     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) {
 -            log(debug, ~"on_alloc_cb!");
++        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 {
 -            log(debug, fmt!("on_alloc_cb h: %? char_ptr: %u sugsize: %u",
++            debug!(~"on_alloc_cb!");
+             let char_ptr = malloc_buf_base_of(suggested_size);
 -                             suggested_size as uint));
++            debug!("on_alloc_cb h: %? char_ptr: %u sugsize: %u",
+                              handle,
+                              char_ptr as uint,
 -            log(debug, fmt!("CLIENT entering on_read_cb nred: %d",
 -                            nread));
++                             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;
 -                log(debug, fmt!("CLIENT read: data! nread: %d", nread));
++            debug!("CLIENT entering on_read_cb nred: %d",
++                            nread);
+             if (nread > 0) {
+                 // we have data
 -                log(debug, ~"read: eof!");
++                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
 -                log(debug, ~"read: do nothing!");
++                debug!(~"read: eof!");
+             }
+             else {
+                 // nread == 0 .. do nothing, just free buf as below
 -            log(debug, ~"CLIENT exiting on_read_cb");
++                debug!(~"read: do nothing!");
+             }
+             // when we're done
+             free_base_of_buf(buf);
 -            log(debug,
 -                fmt!("CLIENT beginning on_write_complete_cb status: %d",
 -                     status as int));
++            debug!(~"CLIENT exiting on_read_cb");
+         }
+     }
+     extern fn on_write_complete_cb(write_req: *uv_write_t,
+                                   status: libc::c_int) {
+         unsafe {
 -            log(debug,
 -                fmt!("CLIENT on_write_complete_cb: tcp:%d write_handle:%d",
 -                stream as int, write_req as int));
++            debug!(
++                "CLIENT beginning on_write_complete_cb status: %d",
++                     status as int);
+             let stream = get_stream_handle_from_write_req(write_req);
 -            log(debug,
 -                fmt!("CLIENT ending on_write_complete_cb .. status: %d",
 -                     result as int));
++            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);
 -            log(debug, fmt!("beginning on_connect_cb .. status: %d",
 -                             status as int));
++            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 {
 -                log(debug, ~"on_connect_cb: in status=0 if..");
++            debug!("beginning on_connect_cb .. status: %d",
++                             status as int);
+             let stream =
+                 get_stream_handle_from_connect_req(connect_req_ptr);
+             if (status == 0i32) {
 -                log(debug, fmt!("on_connect_cb: tcp: %d write_hdl: %d",
 -                                stream as int, write_handle as int));
++                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;
 -                log(debug, fmt!("on_connect_cb: write() status: %d",
 -                                 write_result as int));
++                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);
 -                log(debug, err_msg);
++                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);
 -            log(debug, ~"finishing on_connect_cb");
++                debug!(err_msg);
+                 fail_unless!(false);
+             }
 -            log(debug, fmt!("req_msg ptr: %u", req_msg_ptr as uint));
++            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 = ptr::addr_of(&tcp_handle);
+             let connect_handle = connect_t();
+             let connect_req_ptr = ptr::addr_of(&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);
 -            log(debug, fmt!("tcp req: tcp stream: %d write_handle: %d",
++            debug!("req_msg ptr: %u", req_msg_ptr as uint);
+             let req_msg = ~[
+                 buf_init(req_msg_ptr, vec::len(req_str_bytes))
+             ];
+             // this is the enclosing record, we'll pass a ptr to
+             // this to C..
+             let write_handle = write_t();
+             let write_handle_ptr = ptr::addr_of(&write_handle);
 -                             write_handle_ptr as int));
++            debug!("tcp req: tcp stream: %d write_handle: %d",
+                              tcp_handle_ptr as int,
 -                log(debug, ~"sucessful tcp_init_result");
++                             write_handle_ptr as int);
+             let client_data = request_wrapper {
+                 write_req: write_handle_ptr,
+                 req_buf: ptr::addr_of(&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 == 0i32) {
 -                log(debug, ~"building addr...");
++                debug!(~"sucessful tcp_init_result");
 -                log(debug, fmt!("after build addr in rust. port: %u",
 -                                 addr.sin_port as uint));
++                debug!(~"building addr...");
+                 let addr = ip4_addr(ip, port);
+                 // FIXME ref #2064
+                 let addr_ptr = ptr::addr_of(&addr);
 -                log(debug, fmt!("b4 call tcp_connect connect cb: %u ",
 -                                on_connect_cb as uint));
++                debug!("after build addr in rust. port: %u",
++                                 addr.sin_port as uint);
+                 // this should set up the connection request..
 -                    log(debug, ~"before run tcp req loop");
++                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 == 0i32) {
+                     // not set the data on the connect_req
+                     // until its initialized
+                     set_data_for_req(
+                         connect_req_ptr as *libc::c_void,
+                         ptr::addr_of(&client_data) as *libc::c_void);
+                     set_data_for_uv_handle(
+                         tcp_handle_ptr as *libc::c_void,
+                         ptr::addr_of(&client_data) as *libc::c_void);
 -                    log(debug, ~"after run tcp req loop");
++                    debug!(~"before run tcp req loop");
+                     run(test_loop);
 -                   log(debug, ~"tcp_connect() failure");
++                    debug!(~"after run tcp req loop");
+                 }
+                 else {
 -                log(debug, ~"tcp_init() failure");
++                   debug!(~"tcp_connect() failure");
+                    fail_unless!(false);
+                 }
+             }
+             else {
 -            log(debug, fmt!("SERVER server stream closed, should exit. h: %?",
 -                       handle));
++                debug!(~"tcp_init() failure");
+                 fail_unless!(false);
+             }
+             loop_delete(test_loop);
+         }
+     }
+     extern fn server_after_close_cb(handle: *libc::c_void) {
+         unsafe {
 -            log(debug,
 -                ~"SERVER: closed client stream, now closing server stream");
++            debug!("SERVER server stream closed, should exit. h: %?",
++                       handle);
+         }
+     }
+     extern fn client_stream_after_close_cb(handle: *libc::c_void) {
+         unsafe {
 -            log(debug, ~"SERVER: resp sent... closing client stream");
++            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);
 -                log(debug, fmt!("SERVER read: data! nread: %d", nread));
++            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
 -                log(debug, fmt!("SERVER buf base: %u, len: %u, nread: %d",
++                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;
 -                                nread));
++                debug!("SERVER buf base: %u, len: %u, nread: %d",
+                                 buf_base as uint,
+                                 buf_len as uint,
 -                    log(debug, ~"SERVER: client req contains kill_msg!");
 -                    log(debug, ~"SERVER: sending response to client");
++                                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) {
 -                    log(debug, fmt!("SERVER: resp write result: %d",
 -                                write_result as int));
++                    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);
 -                        log(debug, ~"bad result for server resp write()");
 -                        log(debug, get_last_err_info(
++                    debug!("SERVER: resp write result: %d",
++                                write_result as int);
+                     if (write_result != 0i32) {
 -                    log(debug, ~"SERVER: client req !contain kill_msg!");
++                        debug!(~"bad result for server resp write()");
++                        debug!(get_last_err_info(
+                             get_loop_for_uv_handle(client_stream_ptr
+                                 as *libc::c_void)));
+                         fail_unless!(false);
+                     }
+                 }
+                 else {
 -                log(debug, ~"read: eof!");
++                    debug!(~"SERVER: client req !contain kill_msg!");
+                 }
+             }
+             else if (nread == -1) {
+                 // err .. possibly EOF
 -                log(debug, ~"read: do nothing!");
++                debug!(~"read: eof!");
+             }
+             else {
+                 // nread == 0 .. do nothing, just free buf as below
 -            log(debug, ~"SERVER exiting on_read_cb");
++                debug!(~"read: do nothing!");
+             }
+             // when we're done
+             free_base_of_buf(buf);
 -            log(debug, ~"client connecting!");
++            debug!(~"SERVER exiting on_read_cb");
+         }
+     }
+     extern fn server_connection_cb(server_stream_ptr:
+                                     *uv_stream_t,
+                                   status: libc::c_int) {
+         unsafe {
 -                log(debug, fmt!("server_connect_cb: non-zero status: %?",
 -                             err_msg));
++            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);
 -                log(debug, ~"successfully initialized client stream");
++                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) {
 -                        log(debug, ~"successful server read start");
++                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) {
 -                        log(debug, fmt!("server_connection_cb: bad read:%d",
 -                                        read_result as int));
++                        debug!(~"successful server read start");
+                     }
+                     else {
 -                    log(debug, fmt!("server_connection_cb: bad accept: %d",
 -                                accept_result as int));
++                        debug!("server_connection_cb: bad read:%d",
++                                        read_result as int);
+                         fail_unless!(false);
+                     }
+                 }
+                 else {
 -                log(debug, fmt!("server_connection_cb: bad client init: %d",
 -                            client_init_result as int));
++                    debug!("server_connection_cb: bad accept: %d",
++                                accept_result as int);
+                     fail_unless!(false);
+                 }
+             }
+             else {
 -        log(debug, fmt!("SERVER: closing async cb... h: %?",
 -                   handle));
++                debug!("server_connection_cb: bad client init: %d",
++                            client_init_result as int);
+                 fail_unless!(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) {
 -            log(debug, fmt!("resp_msg ptr: %u", resp_msg_ptr as uint));
++        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 = ptr::addr_of(&tcp_server);
+             let tcp_client = tcp_t();
+             let tcp_client_ptr = ptr::addr_of(&tcp_client);
+             let server_write_req = write_t();
+             let server_write_req_ptr = ptr::addr_of(&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);
 -                    log(debug, ~"successful uv_tcp_bind, listening");
++            debug!("resp_msg ptr: %u", resp_msg_ptr as uint);
+             let resp_msg = ~[
+                 buf_init(resp_msg_ptr, vec::len(resp_str_bytes))
+             ];
+             let continue_async_handle = async_t();
+             let continue_async_handle_ptr =
+                 ptr::addr_of(&continue_async_handle);
+             let async_data =
+                 async_handle_data { continue_chan: continue_chan };
+             let async_data_ptr = ptr::addr_of(&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: ptr::addr_of(&resp_msg),
+                 server_chan: server_chan,
+                 server_write_req: server_write_req_ptr
+             };
+             let server_data_ptr = ptr::addr_of(&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 = ptr::addr_of(&server_addr);
+                 // uv_tcp_bind()
+                 let bind_result = tcp_bind(tcp_server_ptr,
+                                                    server_addr_ptr);
+                 if (bind_result == 0i32) {
 -                            log(debug, ~"server uv::run() has returned");
++                    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);
 -                            log(debug, fmt!("uv_async_init failure: %d",
 -                                    async_result as int));
++                            debug!(~"server uv::run() has returned");
+                         }
+                         else {
 -                        log(debug, fmt!("non-zero result on uv_listen: %d",
 -                                    listen_result as int));
++                            debug!("uv_async_init failure: %d",
++                                    async_result as int);
+                             fail_unless!(false);
+                         }
+                     }
+                     else {
 -                    log(debug, fmt!("non-zero result on uv_tcp_bind: %d",
 -                                bind_result as int));
++                        debug!("non-zero result on uv_listen: %d",
++                                    listen_result as int);
+                         fail_unless!(false);
+                     }
+                 }
+                 else {
 -                log(debug, fmt!("non-zero result on uv_tcp_init: %d",
 -                            tcp_init_result as int));
++                    debug!("non-zero result on uv_tcp_bind: %d",
++                                bind_result as int);
+                     fail_unless!(false);
+                 }
+             }
+             else {
 -            log(debug, ~"before receiving on server continue_port");
++                debug!("non-zero result on uv_tcp_init: %d",
++                            tcp_init_result as int);
+                 fail_unless!(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() {
+         unsafe {
+             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(client_chan);
+             let (server_port, server_chan) = stream::<~str>();
+             let server_chan = SharedChan(server_chan);
+             let (continue_port, continue_chan) = stream::<bool>();
+             let continue_chan = SharedChan(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?
 -            log(debug, ~"received on continue port, set up tcp client");
++            debug!(~"before receiving on server continue_port");
+             continue_port.recv();
 -                log(debug, output);
++            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();
+             fail_unless!(str::contains(msg_from_client, kill_server_msg));
+             fail_unless!(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")]
+     pub mod tcp_and_server_client_test {
+         #[cfg(target_arch="x86_64")]
+         pub mod impl64 {
+             #[test]
+             pub 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")]
+         pub mod impl32 {
+             #[test]
+             #[ignore(cfg(target_os = "linux"))]
+             pub 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) {
+         unsafe {
+             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);
 -            log(debug, output);
++                debug!(output);
+             }
+             fail_unless!(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::rustrt::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::rustrt::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::rustrt::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::rustrt::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::rustrt::rust_uv_helper_sockaddr_in_size()
+             );
+         }
+     }
+     #[test]
+     fn test_uv_ll_struct_size_sockaddr_in6() {
+         unsafe {
+             let foreign_handle_size =
+                 super::rustrt::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);
 -            log(debug, output);
++            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
+             fail_unless!((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::rustrt::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
+             fail_unless!((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::rustrt::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::rustrt::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::rustrt::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::rustrt::rust_uv_helper_uv_timer_t_size()
+             );
+         }
+     }
+ }