<commit_before>#[doc = "
Communication between tasks

Communication between tasks is facilitated by ports (in the receiving
task), and channels (in the sending task). Any number of channels may
feed into a single port.  Ports and channels may only transmit values
of unique types; that is, values that are statically guaranteed to be
accessed by a single 'owner' at a time.  Unique types include scalars,
vectors, strings, and records, tags, tuples and unique boxes (`~T`)
thereof. Most notably, shared boxes (`@T`) may not be transmitted
across channels.

# Example

~~~
let po = comm::port();
let ch = comm::chan(po);

task::spawn {||
    comm::send(ch, \"Hello, World\");
});

io::println(comm::recv(p));
~~~
"];

import either::either;
import libc::size_t;

export port::{};
export chan::{};
export send;
export recv;
export peek;
export recv_chan;
export select2;
export methods;
export listen;

#[doc = "
A communication endpoint that can receive messages

Each port has a unique per-task identity and may not be replicated or
transmitted. If a port value is copied, both copies refer to the same
port.  Ports may be associated with multiple `chan`s.
"]
enum port<T: send> {
    port_t(@port_ptr<T>)
}

// It's critical that this only have one variant, so it has a record
// layout, and will work in the rust_task structure in task.rs.
#[doc = "
A communication endpoint that can send messages

Each channel is bound to a port when the channel is constructed, so
the destination port for a channel must exist before the channel
itself.  Channels are weak: a channel does not keep the port it is
bound to alive. If a channel attempts to send data to a dead port that
data will be silently dropped.  Channels may be duplicated and
themselves transmitted over other channels.
"]
enum chan<T: send> {
    chan_t(port_id)
}

#[doc = "Constructs a port"]
fn port<T: send>() -> port<T> {
    port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>() as size_t)))
}

impl methods<T: send> for port<T> {

    fn chan() -> chan<T> { chan(self) }
    fn send(+v: T) { self.chan().send(v) }
    fn recv() -> T { recv(self) }
    fn peek() -> bool { peek(self) }

}

impl methods<T: send> for chan<T> {

    fn chan() -> chan<T> { self }
    fn send(+v: T) { send(self, v) }
    fn recv() -> T { recv_chan(self) }
    fn peek() -> bool { peek_chan(self) }

}

#[doc = "Open a new receiving channel for the duration of a function"]
fn listen<T: send, U>(f: fn(chan<T>) -> U) -> U {
    let po = port();
    f(po.chan())
}

resource port_ptr<T: send>(po: *rust_port) unsafe {
    task::unkillable {||
        // Once the port is detached it's guaranteed not to receive further
        // messages
        let yield = 0u;
        let yieldp = ptr::addr_of(yield);
        rustrt::rust_port_begin_detach(po, yieldp);
        if yield != 0u {
            // Need to wait for the port to be detached
            // FIXME: If this fails then we're going to leave our port
            // in a bogus state. (Issue #1988)
            task::yield();
        }
        rustrt::rust_port_end_detach(po);

        // Drain the port so that all the still-enqueued items get dropped
        while rustrt::rust_port_size(po) > 0u as size_t {
            recv_::<T>(po);
        }
        rustrt::del_port(po);
    }
}

#[doc = "
Internal function for converting from a channel to a port

# Failure

Fails if the port is detached or dead. Fails if the port
is owned by a different task.
"]
fn as_raw_port<T: send, U>(ch: comm::chan<T>, f: fn(*rust_port) -> U) -> U {
    resource portref(p: *rust_port) {
        if !ptr::is_null(p) {
            rustrt::rust_port_drop(p);
        }
    }

    let p = portref(rustrt::rust_port_take(*ch));

    if ptr::is_null(*p) {
        fail "unable to locate port for channel"
    } else if rustrt::get_task_id() != rustrt::rust_port_task(*p) {
        fail "unable to access unowned port"
    }

    f(*p)
}

#[doc = "
Constructs a channel. The channel is bound to the port used to
construct it.
"]
fn chan<T: send>(p: port<T>) -> chan<T> {
    chan_t(rustrt::get_port_id(***p))
}

#[doc = "
Sends data over a channel. The sent data is moved into the channel,
whereupon the caller loses access to it.
"]
fn send<T: send>(ch: chan<T>, -data: T) {
    let chan_t(p) = ch;
    let data_ptr = ptr::addr_of(data) as *();
    let res = rustrt::rust_port_id_send(p, data_ptr);
    if res != 0u unsafe {
        // Data sent successfully
        unsafe::forget(data);
    }
    task::yield();
}

#[doc = "
Receive from a port.  If no data is available on the port then the
task will block until data becomes available.
"]
fn recv<T: send>(p: port<T>) -> T { recv_(***p) }

#[doc = "Returns true if there are messages available"]
fn peek<T: send>(p: port<T>) -> bool { peek_(***p) }

#[doc(hidden)]
fn recv_chan<T: send>(ch: comm::chan<T>) -> T {
    as_raw_port(ch, {|x|recv_(x)})
}

fn peek_chan<T: send>(ch: comm::chan<T>) -> bool {
    as_raw_port(ch, {|x|peek_(x)})
}

#[doc = "Receive on a raw port pointer"]
fn recv_<T: send>(p: *rust_port) -> T {
    let yield = 0u;
    let yieldp = ptr::addr_of(yield);
    let mut res;
    res = rusti::init::<T>();
    rustrt::port_recv(ptr::addr_of(res) as *uint, p, yieldp);

    if yield != 0u {
        // Data isn't available yet, so res has not been initialized.
        task::yield();
    } else {
        // In the absense of compiler-generated preemption points
        // this is a good place to yield
        task::yield();
    }
    ret res;
}

fn peek_(p: *rust_port) -> bool unsafe {
    rustrt::rust_port_size(p) != 0u as libc::size_t
}

#[doc = "Receive on one of two ports"]
fn select2<A: send, B: send>(p_a: port<A>, p_b: port<B>)
    -> either<A, B> unsafe {
    let ports = [***p_a, ***p_b];
    let n_ports = 2 as libc::size_t;
    let yield = 0u, yieldp = ptr::addr_of(yield);

    let mut resport: *rust_port;
    resport = rusti::init::<*rust_port>();
    vec::as_buf(ports) {|ports|
        rustrt::rust_port_select(ptr::addr_of(resport), ports, n_ports,
                                 yieldp);
    }

    if yield != 0u {
        // Wait for data
        task::yield();
    } else {
        // As in recv, this is a good place to yield anyway until
        // the compiler generates yield calls
        task::yield();
    }

    // Now we know the port we're supposed to receive from
    assert resport != ptr::null();

    if resport == ***p_a {
        either::left(recv(p_a))
    } else if resport == ***p_b {
        either::right(recv(p_b))
    } else {
        fail "unexpected result from rust_port_select";
    }
}

/* Implementation details */

enum rust_port {}

type port_id = int;

#[abi = "cdecl"]
native mod rustrt {
    fn rust_port_id_send(target_port: port_id, data: *()) -> libc::uintptr_t;

    fn new_port(unit_sz: libc::size_t) -> *rust_port;
    fn del_port(po: *rust_port);
    fn rust_port_begin_detach(po: *rust_port,
                              yield: *libc::uintptr_t);
    fn rust_port_end_detach(po: *rust_port);
    fn get_port_id(po: *rust_port) -> port_id;
    fn rust_port_size(po: *rust_port) -> libc::size_t;
    fn port_recv(dptr: *uint, po: *rust_port,
                 yield: *libc::uintptr_t);
    fn rust_port_select(dptr: **rust_port, ports: **rust_port,
                        n_ports: libc::size_t,
                        yield: *libc::uintptr_t);
    fn rust_port_take(port_id: port_id) -> *rust_port;
    fn rust_port_drop(p: *rust_port);
    fn rust_port_task(p: *rust_port) -> libc::uintptr_t;
    fn get_task_id() -> libc::uintptr_t;
}

#[abi = "rust-intrinsic"]
native mod rusti {
    fn init<T>() -> T;
}

/* Tests */

#[test]
fn create_port_and_chan() { let p = port::<int>(); chan(p); }

#[test]
fn send_int() {
    let p = port::<int>();
    let c = chan(p);
    send(c, 22);
}

#[test]
fn send_recv_fn() {
    let p = port::<int>();
    let c = chan::<int>(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn send_recv_fn_infer() {
    let p = port();
    let c = chan(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn chan_chan_infer() {
    let p = port(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

#[test]
fn chan_chan() {
    let p = port::<chan<int>>(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

#[test]
fn test_peek() {
    let po = port();
    let ch = chan(po);
    assert !peek(po);
    send(ch, ());
    assert peek(po);
    recv(po);
    assert !peek(po);
}

#[test]
fn test_select2_available() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    send(ch_a, "a");

    assert select2(po_a, po_b) == either::left("a");

    send(ch_b, "b");

    assert select2(po_a, po_b) == either::right("b");
}

#[test]
fn test_select2_rendezvous() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    iter::repeat(10u) {||
        task::spawn {||
            iter::repeat(10u) {|| task::yield() }
            send(ch_a, "a");
        };

        assert select2(po_a, po_b) == either::left("a");

        task::spawn {||
            iter::repeat(10u) {|| task::yield() }
            send(ch_b, "b");
        };

        assert select2(po_a, po_b) == either::right("b");
    }
}

#[test]
fn test_select2_stress() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    let msgs = 100u;
    let times = 4u;

    iter::repeat(times) {||
        task::spawn {||
            iter::repeat(msgs) {||
                send(ch_a, "a")
            }
        };
        task::spawn {||
            iter::repeat(msgs) {||
                send(ch_b, "b")
            }
        };
    }

    let mut as = 0;
    let mut bs = 0;
    iter::repeat(msgs * times * 2u) {||
        alt check select2(po_a, po_b) {
          either::left("a") { as += 1 }
          either::right("b") { bs += 1 }
        }
    }

    assert as == 400;
    assert bs == 400;
}

#[test]
fn test_recv_chan() {
    let po = port();
    let ch = chan(po);
    send(ch, "flower");
    assert recv_chan(ch) == "flower";
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_recv_chan_dead() {
    let ch = chan(port());
    send(ch, "flower");
    recv_chan(ch);
}

#[test]
#[ignore(cfg(windows))]
fn test_recv_chan_wrong_task() {
    let po = port();
    let ch = chan(po);
    send(ch, "flower");
    assert result::is_failure(task::try {||
        recv_chan(ch)
    })
}

#[test]
fn test_port_send() {
    let po = port();
    po.send(());
    po.recv();
}

#[test]
fn test_chan_peek() {
    let po = port();
    let ch = po.chan();
    ch.send(());
    assert ch.peek();
}

#[test]
fn test_listen() {
    listen {|parent|
        task::spawn {||
            parent.send("oatmeal-salad");
        }
        assert parent.recv() == "oatmeal-salad";
    }
}

#[test]
#[ignore(cfg(windows))]
fn test_port_detach_fail() {
    iter::repeat(100u) {||
        let builder = task::builder();
        task::unsupervise(builder);
        task::run(builder) {||
            let po = port();
            let ch = po.chan();

            task::spawn {||
                fail;
            }

            task::spawn {||
                ch.send(());
            }
        }
    }
}<commit_msg>Change core::comm to use classes instead of resources<commit_after>#[doc = "
Communication between tasks

Communication between tasks is facilitated by ports (in the receiving
task), and channels (in the sending task). Any number of channels may
feed into a single port.  Ports and channels may only transmit values
of unique types; that is, values that are statically guaranteed to be
accessed by a single 'owner' at a time.  Unique types include scalars,
vectors, strings, and records, tags, tuples and unique boxes (`~T`)
thereof. Most notably, shared boxes (`@T`) may not be transmitted
across channels.

# Example

~~~
let po = comm::port();
let ch = comm::chan(po);

task::spawn {||
    comm::send(ch, \"Hello, World\");
});

io::println(comm::recv(p));
~~~
"];

import either::either;
import libc::size_t;

export port::{};
export chan::{};
export send;
export recv;
export peek;
export recv_chan;
export select2;
export methods;
export listen;

#[doc = "
A communication endpoint that can receive messages

Each port has a unique per-task identity and may not be replicated or
transmitted. If a port value is copied, both copies refer to the same
port.  Ports may be associated with multiple `chan`s.
"]
enum port<T: send> {
    port_t(@port_ptr<T>)
}

// It's critical that this only have one variant, so it has a record
// layout, and will work in the rust_task structure in task.rs.
#[doc = "
A communication endpoint that can send messages

Each channel is bound to a port when the channel is constructed, so
the destination port for a channel must exist before the channel
itself.  Channels are weak: a channel does not keep the port it is
bound to alive. If a channel attempts to send data to a dead port that
data will be silently dropped.  Channels may be duplicated and
themselves transmitted over other channels.
"]
enum chan<T: send> {
    chan_t(port_id)
}

#[doc = "Constructs a port"]
fn port<T: send>() -> port<T> {
    port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>() as size_t)))
}

impl methods<T: send> for port<T> {

    fn chan() -> chan<T> { chan(self) }
    fn send(+v: T) { self.chan().send(v) }
    fn recv() -> T { recv(self) }
    fn peek() -> bool { peek(self) }

}

impl methods<T: send> for chan<T> {

    fn chan() -> chan<T> { self }
    fn send(+v: T) { send(self, v) }
    fn recv() -> T { recv_chan(self) }
    fn peek() -> bool { peek_chan(self) }

}

#[doc = "Open a new receiving channel for the duration of a function"]
fn listen<T: send, U>(f: fn(chan<T>) -> U) -> U {
    let po = port();
    f(po.chan())
}

class port_ptr<T:send> {
  let po: *rust_port;
  new(po: *rust_port) { self.po = po; }
  drop unsafe {
    task::unkillable {||
        // Once the port is detached it's guaranteed not to receive further
        // messages
        let yield = 0u;
        let yieldp = ptr::addr_of(yield);
        rustrt::rust_port_begin_detach(self.po, yieldp);
        if yield != 0u {
            // Need to wait for the port to be detached
            // FIXME: If this fails then we're going to leave our port
            // in a bogus state. (Issue #1988)
            task::yield();
        }
        rustrt::rust_port_end_detach(self.po);

        // Drain the port so that all the still-enqueued items get dropped
        while rustrt::rust_port_size(self.po) > 0u as size_t {
            recv_::<T>(self.po);
        }
        rustrt::del_port(self.po);
    }
  }
}

#[doc = "
Internal function for converting from a channel to a port

# Failure

Fails if the port is detached or dead. Fails if the port
is owned by a different task.
"]
fn as_raw_port<T: send, U>(ch: comm::chan<T>, f: fn(*rust_port) -> U) -> U {

    class portref {
       let p: *rust_port;
       new(p: *rust_port) { self.p = p; }
       drop {
         if !ptr::is_null(self.p) {
           rustrt::rust_port_drop(self.p);
         }
       }
    }

    let p = portref(rustrt::rust_port_take(*ch));

    if ptr::is_null(p.p) {
        fail "unable to locate port for channel"
    } else if rustrt::get_task_id() != rustrt::rust_port_task(p.p) {
        fail "unable to access unowned port"
    }

    f(p.p)
}

#[doc = "
Constructs a channel. The channel is bound to the port used to
construct it.
"]
fn chan<T: send>(p: port<T>) -> chan<T> {
    chan_t(rustrt::get_port_id((**p).po))
}

#[doc = "
Sends data over a channel. The sent data is moved into the channel,
whereupon the caller loses access to it.
"]
fn send<T: send>(ch: chan<T>, -data: T) {
    let chan_t(p) = ch;
    let data_ptr = ptr::addr_of(data) as *();
    let res = rustrt::rust_port_id_send(p, data_ptr);
    if res != 0u unsafe {
        // Data sent successfully
        unsafe::forget(data);
    }
    task::yield();
}

#[doc = "
Receive from a port.  If no data is available on the port then the
task will block until data becomes available.
"]
fn recv<T: send>(p: port<T>) -> T { recv_((**p).po) }

#[doc = "Returns true if there are messages available"]
fn peek<T: send>(p: port<T>) -> bool { peek_((**p).po) }

#[doc(hidden)]
fn recv_chan<T: send>(ch: comm::chan<T>) -> T {
    as_raw_port(ch, {|x|recv_(x)})
}

fn peek_chan<T: send>(ch: comm::chan<T>) -> bool {
    as_raw_port(ch, {|x|peek_(x)})
}

#[doc = "Receive on a raw port pointer"]
fn recv_<T: send>(p: *rust_port) -> T {
    let yield = 0u;
    let yieldp = ptr::addr_of(yield);
    let mut res;
    res = rusti::init::<T>();
    rustrt::port_recv(ptr::addr_of(res) as *uint, p, yieldp);

    if yield != 0u {
        // Data isn't available yet, so res has not been initialized.
        task::yield();
    } else {
        // In the absence of compiler-generated preemption points
        // this is a good place to yield
        task::yield();
    }
    ret res;
}

fn peek_(p: *rust_port) -> bool unsafe {
    rustrt::rust_port_size(p) != 0u as libc::size_t
}

#[doc = "Receive on one of two ports"]
fn select2<A: send, B: send>(p_a: port<A>, p_b: port<B>)
    -> either<A, B> unsafe {
    let ports = [(**p_a).po, (**p_b).po];
    let n_ports = 2 as libc::size_t;
    let yield = 0u, yieldp = ptr::addr_of(yield);

    let mut resport: *rust_port;
    resport = rusti::init::<*rust_port>();
    vec::as_buf(ports) {|ports|
        rustrt::rust_port_select(ptr::addr_of(resport), ports, n_ports,
                                 yieldp);
    }

    if yield != 0u {
        // Wait for data
        task::yield();
    } else {
        // As in recv, this is a good place to yield anyway until
        // the compiler generates yield calls
        task::yield();
    }

    // Now we know the port we're supposed to receive from
    assert resport != ptr::null();

    if resport == (**p_a).po {
        either::left(recv(p_a))
    } else if resport == (**p_b).po {
        either::right(recv(p_b))
    } else {
        fail "unexpected result from rust_port_select";
    }
}

/* Implementation details */

enum rust_port {}

type port_id = int;

#[abi = "cdecl"]
native mod rustrt {
    fn rust_port_id_send(target_port: port_id, data: *()) -> libc::uintptr_t;

    fn new_port(unit_sz: libc::size_t) -> *rust_port;
    fn del_port(po: *rust_port);
    fn rust_port_begin_detach(po: *rust_port,
                              yield: *libc::uintptr_t);
    fn rust_port_end_detach(po: *rust_port);
    fn get_port_id(po: *rust_port) -> port_id;
    fn rust_port_size(po: *rust_port) -> libc::size_t;
    fn port_recv(dptr: *uint, po: *rust_port,
                 yield: *libc::uintptr_t);
    fn rust_port_select(dptr: **rust_port, ports: **rust_port,
                        n_ports: libc::size_t,
                        yield: *libc::uintptr_t);
    fn rust_port_take(port_id: port_id) -> *rust_port;
    fn rust_port_drop(p: *rust_port);
    fn rust_port_task(p: *rust_port) -> libc::uintptr_t;
    fn get_task_id() -> libc::uintptr_t;
}

#[abi = "rust-intrinsic"]
native mod rusti {
    fn init<T>() -> T;
}

/* Tests */

#[test]
fn create_port_and_chan() { let p = port::<int>(); chan(p); }

#[test]
fn send_int() {
    let p = port::<int>();
    let c = chan(p);
    send(c, 22);
}

#[test]
fn send_recv_fn() {
    let p = port::<int>();
    let c = chan::<int>(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn send_recv_fn_infer() {
    let p = port();
    let c = chan(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn chan_chan_infer() {
    let p = port(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

#[test]
fn chan_chan() {
    let p = port::<chan<int>>(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

#[test]
fn test_peek() {
    let po = port();
    let ch = chan(po);
    assert !peek(po);
    send(ch, ());
    assert peek(po);
    recv(po);
    assert !peek(po);
}

#[test]
fn test_select2_available() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    send(ch_a, "a");

    assert select2(po_a, po_b) == either::left("a");

    send(ch_b, "b");

    assert select2(po_a, po_b) == either::right("b");
}

#[test]
fn test_select2_rendezvous() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    iter::repeat(10u) {||
        task::spawn {||
            iter::repeat(10u) {|| task::yield() }
            send(ch_a, "a");
        };

        assert select2(po_a, po_b) == either::left("a");

        task::spawn {||
            iter::repeat(10u) {|| task::yield() }
            send(ch_b, "b");
        };

        assert select2(po_a, po_b) == either::right("b");
    }
}

#[test]
fn test_select2_stress() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    let msgs = 100u;
    let times = 4u;

    iter::repeat(times) {||
        task::spawn {||
            iter::repeat(msgs) {||
                send(ch_a, "a")
            }
        };
        task::spawn {||
            iter::repeat(msgs) {||
                send(ch_b, "b")
            }
        };
    }

    let mut as = 0;
    let mut bs = 0;
    iter::repeat(msgs * times * 2u) {||
        alt check select2(po_a, po_b) {
          either::left("a") { as += 1 }
          either::right("b") { bs += 1 }
        }
    }

    assert as == 400;
    assert bs == 400;
}

#[test]
fn test_recv_chan() {
    let po = port();
    let ch = chan(po);
    send(ch, "flower");
    assert recv_chan(ch) == "flower";
}

#[test]
#[should_fail]
#[ignore(cfg(windows))]
fn test_recv_chan_dead() {
    let ch = chan(port());
    send(ch, "flower");
    recv_chan(ch);
}

#[test]
#[ignore(cfg(windows))]
fn test_recv_chan_wrong_task() {
    let po = port();
    let ch = chan(po);
    send(ch, "flower");
    assert result::is_failure(task::try {||
        recv_chan(ch)
    })
}

#[test]
fn test_port_send() {
    let po = port();
    po.send(());
    po.recv();
}

#[test]
fn test_chan_peek() {
    let po = port();
    let ch = po.chan();
    ch.send(());
    assert ch.peek();
}

#[test]
fn test_listen() {
    listen {|parent|
        task::spawn {||
            parent.send("oatmeal-salad");
        }
        assert parent.recv() == "oatmeal-salad";
    }
}

#[test]
#[ignore(cfg(windows))]
fn test_port_detach_fail() {
    iter::repeat(100u) {||
        let builder = task::builder();
        task::unsupervise(builder);
        task::run(builder) {||
            let po = port();
            let ch = po.chan();

            task::spawn {||
                fail;
            }

            task::spawn {||
                ch.send(());
            }
        }
    }
}
<|endoftext|>


<commit_before>// Dynamic Vector
//
// A growable vector that makes use of unique pointers so that the
// result can be sent between tasks and so forth.
//
// Note that recursive use is not permitted.

import dvec_iter::extensions;
import unsafe::reinterpret_cast;
import ptr::{null, extensions};

export dvec;
export from_vec;
export extensions;
export unwrap;

#[doc = "

A growable, modifiable vector type that accumulates elements into a
unique vector.

# Limitations on recursive use

This class works by swapping the unique vector out of the data
structure whenever it is to be used.  Therefore, recursive use is not
permitted.  That is, while iterating through a vector, you cannot
access the vector in any other way or else the program will fail.  If
you wish, you can use the `swap()` method to gain access to the raw
vector and transform it or use it any way you like.  Eventually, we
may permit read-only access during iteration or other use.

# WARNING

For maximum performance, this type is implemented using some rather
unsafe code.  In particular, this innocent looking `[mut A]` pointer
*may be null!*  Therefore, it is important you not reach into the
data structure manually but instead use the provided extensions.

The reason that I did not use an unsafe pointer in the structure
itself is that I wanted to ensure that the vector would be freed when
the dvec is dropped.  The reason that I did not use an `option<T>`
instead of a nullable pointer is that I found experimentally that it
becomes approximately 50% slower. This can probably be improved
through optimization.  You can run your own experiments using
`src/test/bench/vec-append.rs`. My own tests found that using null
pointers achieved about 103 million pushes/second.  Using an option
type could only produce 47 million pushes/second.

"]
type dvec<A> = {

    mut data: [mut A]
};

#[doc = "Creates a new, empty dvec"]
fn dvec<A>() -> dvec<A> {
    {mut data: [mut]}
}

#[doc = "Creates a new dvec with a single element"]
fn from_elt<A>(+e: A) -> dvec<A> {
    {mut data: [mut e]}
}

#[doc = "Creates a new dvec with the contents of a vector"]
fn from_vec<A>(+v: [mut A]) -> dvec<A> {
    {mut data: v}
}

#[doc = "Consumes the vector and returns its contents"]
fn unwrap<A>(-d: dvec<A>) -> [mut A] {
    let {data: v} <- d;
    ret v;
}

impl private_methods<A> for dvec<A> {
    fn check_not_borrowed() {
        unsafe {
            let data: *() = unsafe::reinterpret_cast(self.data);
            if data.is_null() {
                fail "Recursive use of dvec";
            }
        }
    }

    #[inline(always)]
    fn borrow<B>(f: fn(-[mut A]) -> B) -> B {
        unsafe {
            let mut data = unsafe::reinterpret_cast(null::<()>());
            data <-> self.data;
            let data_ptr: *() = unsafe::reinterpret_cast(data);
            if data_ptr.is_null() { fail "Recursive use of dvec"; }
            ret f(data);
        }
    }

    #[inline(always)]
    fn return(-data: [mut A]) {
        unsafe {
            self.data <- data;
        }
    }
}

// In theory, most everything should work with any A, but in practice
// almost nothing works without the copy bound due to limitations
// around closures.
impl extensions<A> for dvec<A> {
    #[doc = "

    Swaps out the current vector and hands it off to a user-provided
    function `f`.  The function should transform it however is desired
    and return a new vector to replace it with.

    "]
    fn swap(f: fn(-[mut A]) -> [mut A]) {
        self.borrow { |v| self.return(f(v)) }
    }

    #[doc = "Returns the number of elements currently in the dvec"]
    fn len() -> uint {
        self.borrow { |v|
            let l = v.len();
            self.return(v);
            l
        }
    }

    #[doc = "Overwrite the current contents"]
    fn set(+w: [mut A]) {
        self.check_not_borrowed();
        self.data <- w; //FIXME check for recursive use
    }
}

impl extensions<A:copy> for dvec<A> {
    #[doc = "Append a single item to the end of the list"]
    fn push(t: A) {
        self.swap { |v|
            let mut v <- v; v += [t]; v // more efficient than v + [t]
        }
    }

    #[doc = "Remove and return the last element"]
    fn pop() -> A {
        self.borrow { |v|
            let mut v <- v;
            let result = vec::pop(v);
            self.return(v);
            result
        }
    }

    #[doc = "
        Append all elements of a vector to the end of the list

        Equivalent to `append_iter()` but potentially more efficient.
    "]
    fn push_all(ts: [const A]/&) {
        self.push_slice(ts, 0u, vec::len(ts));
    }

    #[doc = "
        Appends elements from `from_idx` to `to_idx` (exclusive)
    "]
    fn push_slice(ts: [const A]/&, from_idx: uint, to_idx: uint) {
        self.swap { |v|
            let mut v <- v;
            let new_len = vec::len(v) + to_idx - from_idx;
            vec::reserve(v, new_len);
            let mut i = from_idx;
            while i < to_idx {
                v += [ts[i]];
                i += 1u;
            }
            v
        }
    }

    //FIXME--
    //#[doc = "
    //    Append all elements of an iterable.
    //
    //    Failure will occur if the iterable's `each()` method
    //    attempts to access this vector.
    //"]
    //fn append_iter<I:iter::base<A>>(ts: I) {
    //    self.data.swap { |v|
    //        alt ts.size_hint() {
    //          none {}
    //          some(h) { vec::reserve(v, len(v) + h) }
    //        }
    //
    //        for ts.each { |t| v = v + [t] };
    //
    //        v
    //    }
    //}

    #[doc = "
        Gets a copy of the current contents.

        See `unwrap()` if you do not wish to copy the contents.
    "]
    fn get() -> [A] {
        self.borrow { |v|
            let w = vec::from_mut(copy v);
            self.return(v);
            w
        }
    }

    #[doc = "Remove and return the first element"]
    fn shift() -> A {
        self.borrow { |v|
            let mut v = vec::from_mut(v);
            let result = vec::shift(v);
            self.return(vec::to_mut(v));
            result
        }
    }

    #[doc = "Copy out an individual element"]
    #[inline(always)]
    fn [](idx: uint) -> A {
        self.get_elt(idx)
    }

    #[doc = "Copy out an individual element"]
    #[inline(always)]
    fn get_elt(idx: uint) -> A {
        self.check_not_borrowed();
        ret self.data[idx];
    }

    #[doc = "Overwrites the contents of the element at `idx` with `a`"]
    fn set_elt(idx: uint, a: A) {
        self.check_not_borrowed();
        self.data[idx] = a;
    }

    #[doc = "Overwrites the contents of the element at `idx` with `a`,
    growing the vector if necessary.  New elements will be initialized
    with `initval`"]
    fn grow_set_elt(idx: uint, initval: A, val: A) {
        self.swap { |v|
            let mut v <- v;
            vec::grow_set(v, idx, initval, val);
            v
        }
    }

    #[doc = "Returns the last element, failing if the vector is empty"]
    fn last() -> A {
        self.get_elt(self.len() - 1u)
    }
}<commit_msg>In dvec, annotate a FIXME and uncomment append_iter<commit_after>// Dynamic Vector
//
// A growable vector that makes use of unique pointers so that the
// result can be sent between tasks and so forth.
//
// Note that recursive use is not permitted.

import dvec_iter::extensions;
import unsafe::reinterpret_cast;
import ptr::{null, extensions};

export dvec;
export from_vec;
export extensions;
export unwrap;

#[doc = "

A growable, modifiable vector type that accumulates elements into a
unique vector.

# Limitations on recursive use

This class works by swapping the unique vector out of the data
structure whenever it is to be used.  Therefore, recursive use is not
permitted.  That is, while iterating through a vector, you cannot
access the vector in any other way or else the program will fail.  If
you wish, you can use the `swap()` method to gain access to the raw
vector and transform it or use it any way you like.  Eventually, we
may permit read-only access during iteration or other use.

# WARNING

For maximum performance, this type is implemented using some rather
unsafe code.  In particular, this innocent looking `[mut A]` pointer
*may be null!*  Therefore, it is important you not reach into the
data structure manually but instead use the provided extensions.

The reason that I did not use an unsafe pointer in the structure
itself is that I wanted to ensure that the vector would be freed when
the dvec is dropped.  The reason that I did not use an `option<T>`
instead of a nullable pointer is that I found experimentally that it
becomes approximately 50% slower. This can probably be improved
through optimization.  You can run your own experiments using
`src/test/bench/vec-append.rs`. My own tests found that using null
pointers achieved about 103 million pushes/second.  Using an option
type could only produce 47 million pushes/second.

"]
type dvec<A> = {

    mut data: [mut A]
};

#[doc = "Creates a new, empty dvec"]
fn dvec<A>() -> dvec<A> {
    {mut data: [mut]}
}

#[doc = "Creates a new dvec with a single element"]
fn from_elt<A>(+e: A) -> dvec<A> {
    {mut data: [mut e]}
}

#[doc = "Creates a new dvec with the contents of a vector"]
fn from_vec<A>(+v: [mut A]) -> dvec<A> {
    {mut data: v}
}

#[doc = "Consumes the vector and returns its contents"]
fn unwrap<A>(-d: dvec<A>) -> [mut A] {
    let {data: v} <- d;
    ret v;
}

impl private_methods<A> for dvec<A> {
    fn check_not_borrowed() {
        unsafe {
            let data: *() = unsafe::reinterpret_cast(self.data);
            if data.is_null() {
                fail "Recursive use of dvec";
            }
        }
    }

    #[inline(always)]
    fn borrow<B>(f: fn(-[mut A]) -> B) -> B {
        unsafe {
            let mut data = unsafe::reinterpret_cast(null::<()>());
            data <-> self.data;
            let data_ptr: *() = unsafe::reinterpret_cast(data);
            if data_ptr.is_null() { fail "Recursive use of dvec"; }
            ret f(data);
        }
    }

    #[inline(always)]
    fn return(-data: [mut A]) {
        unsafe {
            self.data <- data;
        }
    }
}

// In theory, most everything should work with any A, but in practice
// almost nothing works without the copy bound due to limitations
// around closures.
impl extensions<A> for dvec<A> {
    #[doc = "

    Swaps out the current vector and hands it off to a user-provided
    function `f`.  The function should transform it however is desired
    and return a new vector to replace it with.

    "]
    fn swap(f: fn(-[mut A]) -> [mut A]) {
        self.borrow { |v| self.return(f(v)) }
    }

    #[doc = "Returns the number of elements currently in the dvec"]
    fn len() -> uint {
        self.borrow { |v|
            let l = v.len();
            self.return(v);
            l
        }
    }

    #[doc = "Overwrite the current contents"]
    fn set(+w: [mut A]) {
        self.check_not_borrowed();
        self.data <- w; //FIXME check for recursive use (#2607)
    }
}

impl extensions<A:copy> for dvec<A> {
    #[doc = "Append a single item to the end of the list"]
    fn push(t: A) {
        self.swap { |v|
            let mut v <- v; v += [t]; v // more efficient than v + [t]
        }
    }

    #[doc = "Remove and return the last element"]
    fn pop() -> A {
        self.borrow { |v|
            let mut v <- v;
            let result = vec::pop(v);
            self.return(v);
            result
        }
    }

    #[doc = "
        Append all elements of a vector to the end of the list

        Equivalent to `append_iter()` but potentially more efficient.
    "]
    fn push_all(ts: [const A]/&) {
        self.push_slice(ts, 0u, vec::len(ts));
    }

    #[doc = "
        Appends elements from `from_idx` to `to_idx` (exclusive)
    "]
    fn push_slice(ts: [const A]/&, from_idx: uint, to_idx: uint) {
        self.swap { |v|
            let mut v <- v;
            let new_len = vec::len(v) + to_idx - from_idx;
            vec::reserve(v, new_len);
            let mut i = from_idx;
            while i < to_idx {
                v += [ts[i]];
                i += 1u;
            }
            v
        }
    }

    #[doc = "
        Append all elements of an iterable.

        Failure will occur if the iterable's `each()` method
        attempts to access this vector.
    "]
    fn append_iter<A, I:iter::base_iter<A>>(ts: I) {
       self.swap { |v|
           let mut v = alt ts.size_hint() {
             none { v }
             some(h) {
               let len = v.len() + h;
               let mut v <- v;
               vec::reserve(v, len);
               v
            }
           };

           for ts.each { |t| v += [t] };
           v
        }
    }

    #[doc = "
        Gets a copy of the current contents.

        See `unwrap()` if you do not wish to copy the contents.
    "]
    fn get() -> [A] {
        self.borrow { |v|
            let w = vec::from_mut(copy v);
            self.return(v);
            w
        }
    }

    #[doc = "Remove and return the first element"]
    fn shift() -> A {
        self.borrow { |v|
            let mut v = vec::from_mut(v);
            let result = vec::shift(v);
            self.return(vec::to_mut(v));
            result
        }
    }

    #[doc = "Copy out an individual element"]
    #[inline(always)]
    fn [](idx: uint) -> A {
        self.get_elt(idx)
    }

    #[doc = "Copy out an individual element"]
    #[inline(always)]
    fn get_elt(idx: uint) -> A {
        self.check_not_borrowed();
        ret self.data[idx];
    }

    #[doc = "Overwrites the contents of the element at `idx` with `a`"]
    fn set_elt(idx: uint, a: A) {
        self.check_not_borrowed();
        self.data[idx] = a;
    }

    #[doc = "Overwrites the contents of the element at `idx` with `a`,
    growing the vector if necessary.  New elements will be initialized
    with `initval`"]
    fn grow_set_elt(idx: uint, initval: A, val: A) {
        self.swap { |v|
            let mut v <- v;
            vec::grow_set(v, idx, initval, val);
            v
        }
    }

    #[doc = "Returns the last element, failing if the vector is empty"]
    fn last() -> A {
        self.get_elt(self.len() - 1u)
    }
}<|endoftext|>


<commit_before>#[doc = "Path data type and helper functions"];

export path;
export consts;
export path_is_absolute;
export path_sep;
export dirname;
export basename;
export connect;
export connect_many;
export split;
export splitext;
export normalize;

// FIXME: This type should probably be constrained
#[doc = "A path or fragment of a filesystem path"]
type path = str;

#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "linux")]
mod consts {
    #[doc = "
    The primary path seperator character for the platform

    On all platforms it is '/'
    "]
    const path_sep: char = '/';
    #[doc = "
    The secondary path seperator character for the platform

    On Unixes it is '/'. On Windows it is '\\'.
    "]
    const alt_path_sep: char = '/';
}

#[cfg(target_os = "win32")]
mod consts {
    const path_sep: char = '/';
    const alt_path_sep: char = '\\';
}

#[doc = "
Indicates whether a path is absolute.

A path is considered absolute if it begins at the filesystem root (\"/\") or,
on Windows, begins with a drive letter.
"]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "linux")]
fn path_is_absolute(p: path) -> bool {
    str::char_at(p, 0u) == '/'
}

#[cfg(target_os = "win32")]
fn path_is_absolute(p: str) -> bool {
    ret str::char_at(p, 0u) == '/' ||
        str::char_at(p, 1u) == ':'
        && (str::char_at(p, 2u) == consts::path_sep
            || str::char_at(p, 2u) == consts::alt_path_sep);
}

#[doc = "Get the default path separator for the host platform"]
fn path_sep() -> str { ret str::from_char(consts::path_sep); }

fn split_dirname_basename (pp: path) -> {dirname: str, basename: str} {
    alt str::rfind(pp, {|ch|
        ch == consts::path_sep || ch == consts::alt_path_sep
    }) {
      some(i) {
        {dirname: str::slice(pp, 0u, i),
         basename: str::slice(pp, i + 1u, str::len(pp))}
      }
      none { {dirname: ".", basename: pp} }
    }
}

#[doc = "
Get the directory portion of a path

Returns all of the path up to, but excluding, the final path separator.
The dirname of \"/usr/share\" will be \"/usr\", but the dirname of
\"/usr/share/\" is \"/usr/share\".

If the path is not prefixed with a directory, then \".\" is returned.
"]
fn dirname(pp: path) -> path {
    ret split_dirname_basename(pp).dirname;
}

#[doc = "
Get the file name portion of a path

Returns the portion of the path after the final path separator.
The basename of \"/usr/share\" will be \"share\". If there are no
path separators in the path then the returned path is identical to
the provided path. If an empty path is provided or the path ends
with a path separator then an empty path is returned.
"]
fn basename(pp: path) -> path {
    ret split_dirname_basename(pp).basename;
}

// FIXME: Need some typestate to avoid bounds check when len(pre) == 0
#[doc = "
Connects to path segments

Given paths `pre` and `post, removes any trailing path separator on `pre` and
any leading path separator on `post`, and returns the concatenation of the two
with a single path separator between them.
"]
fn connect(pre: path, post: path) -> path unsafe {
    let mut pre_ = pre;
    let mut post_ = post;
    let sep = consts::path_sep as u8;
    let pre_len  = str::len(pre);
    let post_len = str::len(post);
    if pre_len > 1u && pre[pre_len-1u] == sep { str::unsafe::pop_byte(pre_); }
    if post_len > 1u && post[0] == sep { str::unsafe::shift_byte(post_); }
    ret pre_ + path_sep() + post_;
}

#[doc = "
Connects a vector of path segments into a single path.

Inserts path separators as needed.
"]
fn connect_many(paths: [path]) -> path {
    ret if vec::len(paths) == 1u {
        paths[0]
    } else {
        let rest = vec::slice(paths, 1u, vec::len(paths));
        connect(paths[0], connect_many(rest))
    }
}

#[doc = "
Split a path into it's individual components

Splits a given path by path separators and returns a vector containing
each piece of the path. On Windows, if the path is absolute then
the first element of the returned vector will be the drive letter
followed by a colon.
"]
fn split(p: path) -> [path] {
    str::split_nonempty(p, {|c|
        c == consts::path_sep || c == consts::alt_path_sep
    })
}

#[doc = "
Split a path into the part before the extension and the extension

Split a path into a pair of strings with the first element being the filename
without the extension and the second being either empty or the file extension
including the period. Leading periods in the basename are ignored.  If the
path includes directory components then they are included in the filename part
of the result pair.
"]
fn splitext(p: path) -> (str, str) {
    if str::is_empty(p) { ("", "") }
    else {
        let parts = str::split_char(p, '.');
        if vec::len(parts) > 1u {
            let base = str::connect(vec::init(parts), ".");
            // We just checked that parts is non-empty, so this is safe
            let ext = "." + vec::last(parts);

            fn is_dotfile(base: str) -> bool {
                str::is_empty(base)
                    || str::ends_with(
                        base, str::from_char(consts::path_sep))
                    || str::ends_with(
                        base, str::from_char(consts::alt_path_sep))
            }

            fn ext_contains_sep(ext: str) -> bool {
                vec::len(split(ext)) > 1u
            }

            fn no_basename(ext: str) -> bool {
                str::ends_with(
                    ext, str::from_char(consts::path_sep))
                    || str::ends_with(
                        ext, str::from_char(consts::alt_path_sep))
            }

            if is_dotfile(base)
                || ext_contains_sep(ext)
                || no_basename(ext) {
                (p, "")
            } else {
                (base, ext)
            }
        } else {
            (p, "")
        }
    }
}

#[doc = "
Removes extra '.' and '..' entries from paths

Does not follow symbolic links.
"]
fn normalize(p: path) -> path {
    let s = split(p);
    let s = strip_dots(s);
    let s = rollup_doubledots(s);

    let s = if check vec::is_not_empty(s) {
        connect_many(s)
    } else {
        ""
    };
    let s = reabsolute(p, s);
    let s = reterminate(p, s);

    let s = if str::len(s) == 0u {
        "."
    } else {
        s
    };

    ret s;

    fn strip_dots(s: [path]) -> [path] {
        vec::filter_map(s, { |elem|
            if elem == "." {
                option::none
            } else {
                option::some(elem)
            }
        })
    }

    fn rollup_doubledots(s: [path]) -> [path] {
        if vec::is_empty(s) {
            ret [];
        }

        let mut t = [];
        let mut i = vec::len(s);
        let mut skip = 0;
        do {
            i -= 1u;
            if s[i] == ".." {
                skip += 1;
            } else {
                if skip == 0 {
                    t += [s[i]];
                } else {
                    skip -= 1;
                }
            }
        } while i != 0u;
        let mut t = vec::reversed(t);
        while skip > 0 {
            t += [".."];
            skip -= 1;
        }
        ret t;
    }

    #[cfg(target_os = "linux")]
    #[cfg(target_os = "macos")]
    #[cfg(target_os = "freebsd")]
    fn reabsolute(orig: path, n: path) -> path {
        if path_is_absolute(orig) {
            path_sep() + n
        } else {
            n
        }
    }

    #[cfg(target_os = "win32")]
    fn reabsolute(orig: path, newp: path) -> path {
       if path_is_absolute(orig) && orig[0] == consts::path_sep as u8 {
           str::from_char(consts::path_sep) + newp
       } else {
           newp
       }
    }

    fn reterminate(orig: path, newp: path) -> path {
        let last = orig[str::len(orig) - 1u];
        if last == consts::path_sep as u8
            || last == consts::path_sep as u8 {
            ret newp + path_sep();
        } else {
            ret newp;
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_connect() {
        let slash = path_sep();
        log(error, connect("a", "b"));
        assert (connect("a", "b") == "a" + slash + "b");
        assert (connect("a" + slash, "b") == "a" + slash + "b");
    }

    fn ps() -> str {
        path_sep()
    }

    fn aps() -> str {
        "/"
    }

    #[test]
    fn split1() {
        let actual = split("a" + ps() + "b");
        let expected = ["a", "b"];
        assert actual == expected;
    }

    #[test]
    fn split2() {
        let actual = split("a" + aps() + "b");
        let expected = ["a", "b"];
        assert actual == expected;
    }

    #[test]
    fn split3() {
        let actual = split(ps() + "a" + ps() + "b");
        let expected = ["a", "b"];
        assert actual == expected;
    }

    #[test]
    fn split4() {
        let actual = split("a" + ps() + "b" + aps() + "c");
        let expected = ["a", "b", "c"];
        assert actual == expected;
    }

    #[test]
    fn normalize1() {
        let actual = normalize("a/b/..");
        let expected = "a";
        assert actual == expected;
    }

    #[test]
    fn normalize2() {
        let actual = normalize("/a/b/..");
        let expected = "/a";
        assert actual == expected;
    }

    #[test]
    fn normalize3() {
        let actual = normalize("a/../b");
        let expected = "b";
        assert actual == expected;
    }

    #[test]
    fn normalize4() {
        let actual = normalize("/a/../b");
        let expected = "/b";
        assert actual == expected;
    }

    #[test]
    fn normalize5() {
        let actual = normalize("a/.");
        let expected = "a";
        assert actual == expected;
    }

    #[test]
    fn normalize6() {
        let actual = normalize("a/./b/");
        let expected = "a/b/";
        assert actual == expected;
    }

    #[test]
    fn normalize7() {
        let actual = normalize("a/..");
        let expected = ".";
        assert actual == expected;
    }

    #[test]
    fn normalize8() {
        let actual = normalize("../../..");
        let expected = "../../..";
        assert actual == expected;
    }

    #[test]
    fn normalize9() {
        let actual = normalize("a/b/../../..");
        let expected = "..";
        assert actual == expected;
    }

    #[test]
    fn normalize10() {
        let actual = normalize("/a/b/c/../d/./../../e/");
        let expected = "/a/e/";
        log(error, actual);
        assert actual == expected;
    }

    #[test]
    fn normalize11() {
        let actual = normalize("/a/..");
        let expected = "/";
        assert actual == expected;
    }

    #[test]
    #[cfg(target_os = "win32")]
    fn normalize12() {
        let actual = normalize("C:/whatever");
        let expected = "C:/whatever";
        log(error, actual);
        assert actual == expected;
    }

    #[test]
    #[cfg(target_os = "win32")]
    fn path_is_absolute_win32() {
        assert path_is_absolute("C:/whatever");
    }

    #[test]
    fn splitext_empty() {
        let (base, ext) = splitext("");
        assert base == "";
        assert ext == "";
    }

    #[test]
    fn splitext_ext() {
        let (base, ext) = splitext("grum.exe");
        assert base == "grum";
        assert ext == ".exe";
    }

    #[test]
    fn splitext_noext() {
        let (base, ext) = splitext("grum");
        assert base == "grum";
        assert ext == "";
    }

    #[test]
    fn splitext_dotfile() {
        let (base, ext) = splitext(".grum");
        assert base == ".grum";
        assert ext == "";
    }

    #[test]
    fn splitext_path_ext() {
        let (base, ext) = splitext("oh/grum.exe");
        assert base == "oh/grum";
        assert ext == ".exe";
    }

    #[test]
    fn splitext_path_noext() {
        let (base, ext) = splitext("oh/grum");
        assert base == "oh/grum";
        assert ext == "";
    }

    #[test]
    fn splitext_dot_in_path() {
        let (base, ext) = splitext("oh.my/grum");
        assert base == "oh.my/grum";
        assert ext == "";
    }

    #[test]
    fn splitext_nobasename() {
        let (base, ext) = splitext("oh.my/");
        assert base == "oh.my/";
        assert ext == "";
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Clarify docs for path::normalize. Closes #2362<commit_after>#[doc = "Path data type and helper functions"];

export path;
export consts;
export path_is_absolute;
export path_sep;
export dirname;
export basename;
export connect;
export connect_many;
export split;
export splitext;
export normalize;

// FIXME: This type should probably be constrained
#[doc = "A path or fragment of a filesystem path"]
type path = str;

#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "linux")]
mod consts {
    #[doc = "
    The primary path seperator character for the platform

    On all platforms it is '/'
    "]
    const path_sep: char = '/';
    #[doc = "
    The secondary path seperator character for the platform

    On Unixes it is '/'. On Windows it is '\\'.
    "]
    const alt_path_sep: char = '/';
}

#[cfg(target_os = "win32")]
mod consts {
    const path_sep: char = '/';
    const alt_path_sep: char = '\\';
}

#[doc = "
Indicates whether a path is absolute.

A path is considered absolute if it begins at the filesystem root (\"/\") or,
on Windows, begins with a drive letter.
"]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "linux")]
fn path_is_absolute(p: path) -> bool {
    str::char_at(p, 0u) == '/'
}

#[cfg(target_os = "win32")]
fn path_is_absolute(p: str) -> bool {
    ret str::char_at(p, 0u) == '/' ||
        str::char_at(p, 1u) == ':'
        && (str::char_at(p, 2u) == consts::path_sep
            || str::char_at(p, 2u) == consts::alt_path_sep);
}

#[doc = "Get the default path separator for the host platform"]
fn path_sep() -> str { ret str::from_char(consts::path_sep); }

fn split_dirname_basename (pp: path) -> {dirname: str, basename: str} {
    alt str::rfind(pp, {|ch|
        ch == consts::path_sep || ch == consts::alt_path_sep
    }) {
      some(i) {
        {dirname: str::slice(pp, 0u, i),
         basename: str::slice(pp, i + 1u, str::len(pp))}
      }
      none { {dirname: ".", basename: pp} }
    }
}

#[doc = "
Get the directory portion of a path

Returns all of the path up to, but excluding, the final path separator.
The dirname of \"/usr/share\" will be \"/usr\", but the dirname of
\"/usr/share/\" is \"/usr/share\".

If the path is not prefixed with a directory, then \".\" is returned.
"]
fn dirname(pp: path) -> path {
    ret split_dirname_basename(pp).dirname;
}

#[doc = "
Get the file name portion of a path

Returns the portion of the path after the final path separator.
The basename of \"/usr/share\" will be \"share\". If there are no
path separators in the path then the returned path is identical to
the provided path. If an empty path is provided or the path ends
with a path separator then an empty path is returned.
"]
fn basename(pp: path) -> path {
    ret split_dirname_basename(pp).basename;
}

// FIXME: Need some typestate to avoid bounds check when len(pre) == 0
#[doc = "
Connects to path segments

Given paths `pre` and `post, removes any trailing path separator on `pre` and
any leading path separator on `post`, and returns the concatenation of the two
with a single path separator between them.
"]
fn connect(pre: path, post: path) -> path unsafe {
    let mut pre_ = pre;
    let mut post_ = post;
    let sep = consts::path_sep as u8;
    let pre_len  = str::len(pre);
    let post_len = str::len(post);
    if pre_len > 1u && pre[pre_len-1u] == sep { str::unsafe::pop_byte(pre_); }
    if post_len > 1u && post[0] == sep { str::unsafe::shift_byte(post_); }
    ret pre_ + path_sep() + post_;
}

#[doc = "
Connects a vector of path segments into a single path.

Inserts path separators as needed.
"]
fn connect_many(paths: [path]) -> path {
    ret if vec::len(paths) == 1u {
        paths[0]
    } else {
        let rest = vec::slice(paths, 1u, vec::len(paths));
        connect(paths[0], connect_many(rest))
    }
}

#[doc = "
Split a path into it's individual components

Splits a given path by path separators and returns a vector containing
each piece of the path. On Windows, if the path is absolute then
the first element of the returned vector will be the drive letter
followed by a colon.
"]
fn split(p: path) -> [path] {
    str::split_nonempty(p, {|c|
        c == consts::path_sep || c == consts::alt_path_sep
    })
}

#[doc = "
Split a path into the part before the extension and the extension

Split a path into a pair of strings with the first element being the filename
without the extension and the second being either empty or the file extension
including the period. Leading periods in the basename are ignored.  If the
path includes directory components then they are included in the filename part
of the result pair.
"]
fn splitext(p: path) -> (str, str) {
    if str::is_empty(p) { ("", "") }
    else {
        let parts = str::split_char(p, '.');
        if vec::len(parts) > 1u {
            let base = str::connect(vec::init(parts), ".");
            // We just checked that parts is non-empty, so this is safe
            let ext = "." + vec::last(parts);

            fn is_dotfile(base: str) -> bool {
                str::is_empty(base)
                    || str::ends_with(
                        base, str::from_char(consts::path_sep))
                    || str::ends_with(
                        base, str::from_char(consts::alt_path_sep))
            }

            fn ext_contains_sep(ext: str) -> bool {
                vec::len(split(ext)) > 1u
            }

            fn no_basename(ext: str) -> bool {
                str::ends_with(
                    ext, str::from_char(consts::path_sep))
                    || str::ends_with(
                        ext, str::from_char(consts::alt_path_sep))
            }

            if is_dotfile(base)
                || ext_contains_sep(ext)
                || no_basename(ext) {
                (p, "")
            } else {
                (base, ext)
            }
        } else {
            (p, "")
        }
    }
}

#[doc = "
Collapses redundant path separators.

Does not follow symbolic links.

# Examples

* '/a/../b' becomes '/b'
* 'a/./b/' becomes 'a/b/'
* 'a/b/../../../' becomes '..'
* '/a/b/c/../d/./../../e/' becomes '/a/e/'

"]
fn normalize(p: path) -> path {
    let s = split(p);
    let s = strip_dots(s);
    let s = rollup_doubledots(s);

    let s = if check vec::is_not_empty(s) {
        connect_many(s)
    } else {
        ""
    };
    let s = reabsolute(p, s);
    let s = reterminate(p, s);

    let s = if str::len(s) == 0u {
        "."
    } else {
        s
    };

    ret s;

    fn strip_dots(s: [path]) -> [path] {
        vec::filter_map(s, { |elem|
            if elem == "." {
                option::none
            } else {
                option::some(elem)
            }
        })
    }

    fn rollup_doubledots(s: [path]) -> [path] {
        if vec::is_empty(s) {
            ret [];
        }

        let mut t = [];
        let mut i = vec::len(s);
        let mut skip = 0;
        do {
            i -= 1u;
            if s[i] == ".." {
                skip += 1;
            } else {
                if skip == 0 {
                    t += [s[i]];
                } else {
                    skip -= 1;
                }
            }
        } while i != 0u;
        let mut t = vec::reversed(t);
        while skip > 0 {
            t += [".."];
            skip -= 1;
        }
        ret t;
    }

    #[cfg(target_os = "linux")]
    #[cfg(target_os = "macos")]
    #[cfg(target_os = "freebsd")]
    fn reabsolute(orig: path, n: path) -> path {
        if path_is_absolute(orig) {
            path_sep() + n
        } else {
            n
        }
    }

    #[cfg(target_os = "win32")]
    fn reabsolute(orig: path, newp: path) -> path {
       if path_is_absolute(orig) && orig[0] == consts::path_sep as u8 {
           str::from_char(consts::path_sep) + newp
       } else {
           newp
       }
    }

    fn reterminate(orig: path, newp: path) -> path {
        let last = orig[str::len(orig) - 1u];
        if last == consts::path_sep as u8
            || last == consts::path_sep as u8 {
            ret newp + path_sep();
        } else {
            ret newp;
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_connect() {
        let slash = path_sep();
        log(error, connect("a", "b"));
        assert (connect("a", "b") == "a" + slash + "b");
        assert (connect("a" + slash, "b") == "a" + slash + "b");
    }

    fn ps() -> str {
        path_sep()
    }

    fn aps() -> str {
        "/"
    }

    #[test]
    fn split1() {
        let actual = split("a" + ps() + "b");
        let expected = ["a", "b"];
        assert actual == expected;
    }

    #[test]
    fn split2() {
        let actual = split("a" + aps() + "b");
        let expected = ["a", "b"];
        assert actual == expected;
    }

    #[test]
    fn split3() {
        let actual = split(ps() + "a" + ps() + "b");
        let expected = ["a", "b"];
        assert actual == expected;
    }

    #[test]
    fn split4() {
        let actual = split("a" + ps() + "b" + aps() + "c");
        let expected = ["a", "b", "c"];
        assert actual == expected;
    }

    #[test]
    fn normalize1() {
        let actual = normalize("a/b/..");
        let expected = "a";
        assert actual == expected;
    }

    #[test]
    fn normalize2() {
        let actual = normalize("/a/b/..");
        let expected = "/a";
        assert actual == expected;
    }

    #[test]
    fn normalize3() {
        let actual = normalize("a/../b");
        let expected = "b";
        assert actual == expected;
    }

    #[test]
    fn normalize4() {
        let actual = normalize("/a/../b");
        let expected = "/b";
        assert actual == expected;
    }

    #[test]
    fn normalize5() {
        let actual = normalize("a/.");
        let expected = "a";
        assert actual == expected;
    }

    #[test]
    fn normalize6() {
        let actual = normalize("a/./b/");
        let expected = "a/b/";
        assert actual == expected;
    }

    #[test]
    fn normalize7() {
        let actual = normalize("a/..");
        let expected = ".";
        assert actual == expected;
    }

    #[test]
    fn normalize8() {
        let actual = normalize("../../..");
        let expected = "../../..";
        assert actual == expected;
    }

    #[test]
    fn normalize9() {
        let actual = normalize("a/b/../../..");
        let expected = "..";
        assert actual == expected;
    }

    #[test]
    fn normalize10() {
        let actual = normalize("/a/b/c/../d/./../../e/");
        let expected = "/a/e/";
        log(error, actual);
        assert actual == expected;
    }

    #[test]
    fn normalize11() {
        let actual = normalize("/a/..");
        let expected = "/";
        assert actual == expected;
    }

    #[test]
    #[cfg(target_os = "win32")]
    fn normalize12() {
        let actual = normalize("C:/whatever");
        let expected = "C:/whatever";
        log(error, actual);
        assert actual == expected;
    }

    #[test]
    #[cfg(target_os = "win32")]
    fn path_is_absolute_win32() {
        assert path_is_absolute("C:/whatever");
    }

    #[test]
    fn splitext_empty() {
        let (base, ext) = splitext("");
        assert base == "";
        assert ext == "";
    }

    #[test]
    fn splitext_ext() {
        let (base, ext) = splitext("grum.exe");
        assert base == "grum";
        assert ext == ".exe";
    }

    #[test]
    fn splitext_noext() {
        let (base, ext) = splitext("grum");
        assert base == "grum";
        assert ext == "";
    }

    #[test]
    fn splitext_dotfile() {
        let (base, ext) = splitext(".grum");
        assert base == ".grum";
        assert ext == "";
    }

    #[test]
    fn splitext_path_ext() {
        let (base, ext) = splitext("oh/grum.exe");
        assert base == "oh/grum";
        assert ext == ".exe";
    }

    #[test]
    fn splitext_path_noext() {
        let (base, ext) = splitext("oh/grum");
        assert base == "oh/grum";
        assert ext == "";
    }

    #[test]
    fn splitext_dot_in_path() {
        let (base, ext) = splitext("oh.my/grum");
        assert base == "oh.my/grum";
        assert ext == "";
    }

    #[test]
    fn splitext_nobasename() {
        let (base, ext) = splitext("oh.my/");
        assert base == "oh.my/";
        assert ext == "";
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>use bindings::*;
use compile::Compile;
use function::ABI;
use libc::c_uint;
use std::kinds::marker::{
    ContravariantLifetime,
    Managed
};
use std::mem::transmute;
use std::str::raw::from_c_str;
use std::c_str::ToCStr;
use util::NativeRef;
#[repr(i32)]
#[deriving(Show)]
pub enum TypeKind {
    Void         = 0,
    SByte        = 1,
    UByte        = 2,
    Short        = 3,
    UShort       = 4,
    Int          = 5,
    UInt         = 6,
    NInt         = 7,
    NUInt        = 8,
    Long         = 9,
    ULong        = 10,
    Float32      = 11,
    Float64      = 12,
    NFloat       = 13,
    Struct       = 14,
    Union        = 15,
    Signature    = 16,
    Pointer      = 17,
    FirstTagged  = 32,
    SysBool      = 10009,
    SysChar      = 10010
}
/// A single field of a struct
pub struct Field<'a> {
    /// The index of the field
    pub index: c_uint,
    _type: jit_type_t,
    marker: ContravariantLifetime<'a>
}
impl<'a> Field<'a> {
    #[inline]
    /// Get the field's name or none if it lacks one
    pub fn get_name(&self) -> Option<String> {
        unsafe {
            let c_name = jit_type_get_name(self._type, self.index);
            if c_name.is_null() {
                None
            } else {
                Some(from_c_str(c_name))
            }
        }
    }
    #[inline]
    /// Get the type of the field
    pub fn get_type(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_get_field(self._type, self.index))
        }
    }
    #[inline]
    /// Get the offset of the field
    pub fn get_offset(&self) -> uint {
        unsafe {
            jit_type_get_offset(self._type, self.index) as uint
        }
    }
}
/// A type field iterator
pub struct Fields<'a> {
    _type: jit_type_t,
    index: c_uint,
    length: c_uint,
    marker: ContravariantLifetime<'a>
}
impl<'a> Fields<'a> {
    #[inline(always)]
    fn new(ty:Type) -> Fields<'a> {
        unsafe {
            Fields {
                _type: ty.as_ptr(),
                index: 0 as c_uint,
                length: jit_type_num_fields(ty.as_ptr()),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<Field<'a>> for Fields<'a> {
    fn next(&mut self) -> Option<Field<'a>> {
        let index = self.index;
        self.index += 1;
        if index < self.length {
            Some(Field {
                _type: self._type.clone(),
                index: index,
                marker: ContravariantLifetime::<'a>
            })
        } else {
            None
        }
    }
    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        ((self.length - self.index) as uint, None)
    }
    #[inline]
    fn count(&mut self) -> uint {
        let count = self.length - self.index;
        self.index = self.length;
        count as uint
    }
    #[inline]
    fn nth(&mut self, n:uint) -> Option<Field<'a>> {
        self.index += n as c_uint;
        self.next()
    }
}
pub struct Params<'a> {
    _type: jit_type_t,
    index: c_uint,
    length: c_uint,
    marker: ContravariantLifetime<'a>
}
impl<'a> Params<'a> {
    #[inline(always)]
    fn new(ty:Type) -> Params<'a> {
        unsafe {
            Params {
                _type: ty.as_ptr(),
                index: 0 as c_uint,
                length: jit_type_num_params(ty.as_ptr()),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<Type> for Params<'a> {
    fn next(&mut self) -> Option<Type> {
        let index = self.index;
        self.index += 1;
        if index < self.length {
            Some(unsafe {
                NativeRef::from_ptr(jit_type_get_param(self._type, index))
            })
        } else {
            None
        }
    }
    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        ((self.length - self.index) as uint, None)
    }
    #[inline]
    fn count(&mut self) -> uint {
        let count = self.length - self.index;
        self.index = self.length;
        count as uint
    }
    #[inline]
    fn nth(&mut self, n:uint) -> Option<Type> {
        self.index += n as c_uint;
        self.next()
    }
}
/// An object that represents a native system type.
/// Each `Type` represents a basic system type, be it a primitive, a struct, a
/// union, a pointer, or a function signature. The library uses this information
/// to lay out values in memory.
#[deriving(PartialEq)]
pub struct Type {
    _type: jit_type_t,
    marker: Managed
}
impl NativeRef for Type {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> jit_type_t {
        self._type
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:jit_type_t) -> Type {
        Type {
            _type: ptr,
            marker: Managed
        }
    }
}
impl Clone for Type {
    #[inline]
    /// Make a copy of the type descriptor by increasing its reference count.
    fn clone(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_copy(self.as_ptr()))
        }
    }
}
#[unsafe_destructor]
impl Drop for Type {
    #[inline]
    /// Free a type descriptor by decreasing its reference count.
    /// This function is safe to use on pre-defined types, which are never
    /// actually freed.
    fn drop(&mut self) {
        unsafe {
            jit_type_free(self.as_ptr());
        }
    }
}
impl Type {
    /// Create a type descriptor for a function signature.
    pub fn create_signature(abi: ABI, return_type: Type, params: &mut [Type]) -> Type {
        unsafe {
            let mut native_params:Vec<jit_type_t> = params.iter().map(|param| param.as_ptr()).collect();
            let signature = jit_type_create_signature(abi as jit_abi_t, return_type.as_ptr(), native_params.as_mut_ptr(), params.len() as c_uint, 1);
            NativeRef::from_ptr(signature)
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a structure.
    pub fn create_struct(fields: &mut [Type]) -> Type {
        unsafe {
            let mut native_fields:Vec<_> = fields.iter().map(|field| field.as_ptr()).collect();
            NativeRef::from_ptr(jit_type_create_struct(native_fields.as_mut_ptr(), fields.len() as c_uint, 1))
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a union.
    pub fn create_union(fields: &mut [Type]) -> Type {
        unsafe {
            let mut native_fields:Vec<_> = fields.iter().map(|field| field.as_ptr()).collect();
            NativeRef::from_ptr(jit_type_create_union(native_fields.as_mut_ptr(), fields.len() as c_uint, 1))
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a pointer to another type.
    pub fn create_pointer(pointee: Type) -> Type {
        unsafe {
            let ptr = jit_type_create_pointer(pointee.as_ptr(), 1);
            NativeRef::from_ptr(ptr)
        }
    }
    #[inline]
    /// Get the size of this type in bytes.
    pub fn get_size(&self) -> uint {
        unsafe {
            jit_type_get_size(self.as_ptr()) as uint
        }
    }
    #[inline]
    /// Get a value that indicates the kind of this type. This allows
    /// callers to quickly classify a type to determine how it should
    /// be handled further.
    pub fn get_kind(&self) -> TypeKind {
        unsafe {
            transmute(jit_type_get_kind(self.as_ptr()))
        }
    }
    #[inline]
    /// Get the type that is referred to by this pointer type.
    pub fn get_ref(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_get_ref(self.as_ptr()))
        }
    }
    /// Set the field or parameter names of this type.
    pub fn set_names<T:ToCStr>(&self, names:&[T]) -> bool {
        unsafe {
            let native_names : Vec<*const i8> = names.iter().map(|name| name.to_c_str().unwrap()).collect();
            jit_type_set_names(self.as_ptr(), native_names.as_ptr() as *mut *mut i8, names.len() as u32) != 0
        }
    }
    #[inline(always)]
    /// Iterator over the type's fields
    pub fn fields<'a>(&'a self) -> Fields<'a> {
        Fields::new(self.clone())
    }
    #[inline(always)]
    /// Iterator over the function signature's parameters
    pub fn params<'a>(&'a self) -> Params<'a> {
        Params::new(self.clone())
    }
    #[inline]
    /// Find the field/parameter index for a particular name.
    pub fn find_name<'b, T:ToCStr>(&'b self, name:T) -> Field<'b> {
        name.with_c_str(|c_name| unsafe {
            Field {
                index: jit_type_find_name(self.as_ptr(), c_name),
                _type: self.as_ptr(),
                marker: ContravariantLifetime::<'b>
            }
        })
    }
    #[inline(always)]
    /// Check if this is a pointer
    pub fn is_pointer(&self) -> bool {
        unsafe {
            jit_type_is_pointer(self.as_ptr()) != 0
        }
    }
}
#[inline(always)]
/// Get the Rust type given as a type descriptor
pub fn get<T:Compile>() -> Type {
    Compile::jit_type(None::<T>)
}<commit_msg>Always inline simple Type methods<commit_after>use bindings::*;
use compile::Compile;
use function::ABI;
use libc::c_uint;
use std::kinds::marker::{
    ContravariantLifetime,
    Managed
};
use std::mem::transmute;
use std::str::raw::from_c_str;
use std::c_str::ToCStr;
use util::NativeRef;
#[repr(i32)]
#[deriving(Show)]
pub enum TypeKind {
    Void         = 0,
    SByte        = 1,
    UByte        = 2,
    Short        = 3,
    UShort       = 4,
    Int          = 5,
    UInt         = 6,
    NInt         = 7,
    NUInt        = 8,
    Long         = 9,
    ULong        = 10,
    Float32      = 11,
    Float64      = 12,
    NFloat       = 13,
    Struct       = 14,
    Union        = 15,
    Signature    = 16,
    Pointer      = 17,
    FirstTagged  = 32,
    SysBool      = 10009,
    SysChar      = 10010
}
/// A single field of a struct
pub struct Field<'a> {
    /// The index of the field
    pub index: c_uint,
    _type: jit_type_t,
    marker: ContravariantLifetime<'a>
}
impl<'a> Field<'a> {
    #[inline]
    /// Get the field's name or none if it lacks one
    pub fn get_name(&self) -> Option<String> {
        unsafe {
            let c_name = jit_type_get_name(self._type, self.index);
            if c_name.is_null() {
                None
            } else {
                Some(from_c_str(c_name))
            }
        }
    }
    #[inline(always)]
    /// Get the type of the field
    pub fn get_type(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_get_field(self._type, self.index))
        }
    }
    #[inline(always)]
    /// Get the offset of the field
    pub fn get_offset(&self) -> uint {
        unsafe {
            jit_type_get_offset(self._type, self.index) as uint
        }
    }
}
/// A type field iterator
pub struct Fields<'a> {
    _type: jit_type_t,
    index: c_uint,
    length: c_uint,
    marker: ContravariantLifetime<'a>
}
impl<'a> Fields<'a> {
    #[inline(always)]
    fn new(ty:Type) -> Fields<'a> {
        unsafe {
            Fields {
                _type: ty.as_ptr(),
                index: 0 as c_uint,
                length: jit_type_num_fields(ty.as_ptr()),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<Field<'a>> for Fields<'a> {
    fn next(&mut self) -> Option<Field<'a>> {
        let index = self.index;
        self.index += 1;
        if index < self.length {
            Some(Field {
                _type: self._type.clone(),
                index: index,
                marker: ContravariantLifetime::<'a>
            })
        } else {
            None
        }
    }
    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        ((self.length - self.index) as uint, None)
    }
    #[inline]
    fn count(&mut self) -> uint {
        let count = self.length - self.index;
        self.index = self.length;
        count as uint
    }
    #[inline]
    fn nth(&mut self, n:uint) -> Option<Field<'a>> {
        self.index += n as c_uint;
        self.next()
    }
}
pub struct Params<'a> {
    _type: jit_type_t,
    index: c_uint,
    length: c_uint,
    marker: ContravariantLifetime<'a>
}
impl<'a> Params<'a> {
    #[inline(always)]
    fn new(ty:Type) -> Params<'a> {
        unsafe {
            Params {
                _type: ty.as_ptr(),
                index: 0 as c_uint,
                length: jit_type_num_params(ty.as_ptr()),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<Type> for Params<'a> {
    fn next(&mut self) -> Option<Type> {
        let index = self.index;
        self.index += 1;
        if index < self.length {
            Some(unsafe {
                NativeRef::from_ptr(jit_type_get_param(self._type, index))
            })
        } else {
            None
        }
    }
    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        ((self.length - self.index) as uint, None)
    }
    #[inline]
    fn count(&mut self) -> uint {
        let count = self.length - self.index;
        self.index = self.length;
        count as uint
    }
    #[inline]
    fn nth(&mut self, n:uint) -> Option<Type> {
        self.index += n as c_uint;
        self.next()
    }
}
/// An object that represents a native system type.
/// Each `Type` represents a basic system type, be it a primitive, a struct, a
/// union, a pointer, or a function signature. The library uses this information
/// to lay out values in memory.
#[deriving(PartialEq)]
pub struct Type {
    _type: jit_type_t,
    marker: Managed
}
impl NativeRef for Type {
    #[inline(always)]
    unsafe fn as_ptr(&self) -> jit_type_t {
        self._type
    }
    #[inline(always)]
    unsafe fn from_ptr(ptr:jit_type_t) -> Type {
        Type {
            _type: ptr,
            marker: Managed
        }
    }
}
impl Clone for Type {
    #[inline]
    /// Make a copy of the type descriptor by increasing its reference count.
    fn clone(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_copy(self.as_ptr()))
        }
    }
}
#[unsafe_destructor]
impl Drop for Type {
    #[inline(always)]
    /// Free a type descriptor by decreasing its reference count.
    /// This function is safe to use on pre-defined types, which are never
    /// actually freed.
    fn drop(&mut self) {
        unsafe {
            jit_type_free(self.as_ptr());
        }
    }
}
impl Type {
    /// Create a type descriptor for a function signature.
    pub fn create_signature(abi: ABI, return_type: Type, params: &mut [Type]) -> Type {
        unsafe {
            let mut native_params:Vec<jit_type_t> = params.iter().map(|param| param.as_ptr()).collect();
            let signature = jit_type_create_signature(abi as jit_abi_t, return_type.as_ptr(), native_params.as_mut_ptr(), params.len() as c_uint, 1);
            NativeRef::from_ptr(signature)
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a structure.
    pub fn create_struct(fields: &mut [Type]) -> Type {
        unsafe {
            let mut native_fields:Vec<_> = fields.iter().map(|field| field.as_ptr()).collect();
            NativeRef::from_ptr(jit_type_create_struct(native_fields.as_mut_ptr(), fields.len() as c_uint, 1))
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a union.
    pub fn create_union(fields: &mut [Type]) -> Type {
        unsafe {
            let mut native_fields:Vec<_> = fields.iter().map(|field| field.as_ptr()).collect();
            NativeRef::from_ptr(jit_type_create_union(native_fields.as_mut_ptr(), fields.len() as c_uint, 1))
        }
    }
    #[inline(always)]
    /// Create a type descriptor for a pointer to another type.
    pub fn create_pointer(pointee: Type) -> Type {
        unsafe {
            let ptr = jit_type_create_pointer(pointee.as_ptr(), 1);
            NativeRef::from_ptr(ptr)
        }
    }
    #[inline(always)]
    /// Get the size of this type in bytes.
    pub fn get_size(&self) -> uint {
        unsafe {
            jit_type_get_size(self.as_ptr()) as uint
        }
    }
    #[inline]
    /// Get a value that indicates the kind of this type. This allows
    /// callers to quickly classify a type to determine how it should
    /// be handled further.
    pub fn get_kind(&self) -> TypeKind {
        unsafe {
            transmute(jit_type_get_kind(self.as_ptr()))
        }
    }
    #[inline(always)]
    /// Get the type that is referred to by this pointer type.
    pub fn get_ref(&self) -> Type {
        unsafe {
            NativeRef::from_ptr(jit_type_get_ref(self.as_ptr()))
        }
    }
    /// Set the field or parameter names of this type.
    pub fn set_names<T:ToCStr>(&self, names:&[T]) -> bool {
        unsafe {
            let native_names : Vec<*const i8> = names.iter().map(|name| name.to_c_str().unwrap()).collect();
            jit_type_set_names(self.as_ptr(), native_names.as_ptr() as *mut *mut i8, names.len() as u32) != 0
        }
    }
    #[inline(always)]
    /// Iterator over the type's fields
    pub fn fields<'a>(&'a self) -> Fields<'a> {
        Fields::new(self.clone())
    }
    #[inline(always)]
    /// Iterator over the function signature's parameters
    pub fn params<'a>(&'a self) -> Params<'a> {
        Params::new(self.clone())
    }
    #[inline]
    /// Find the field/parameter index for a particular name.
    pub fn find_name<'b, T:ToCStr>(&'b self, name:T) -> Field<'b> {
        name.with_c_str(|c_name| unsafe {
            Field {
                index: jit_type_find_name(self.as_ptr(), c_name),
                _type: self.as_ptr(),
                marker: ContravariantLifetime::<'b>
            }
        })
    }
    #[inline(always)]
    /// Check if this is a pointer
    pub fn is_pointer(&self) -> bool {
        unsafe {
            jit_type_is_pointer(self.as_ptr()) != 0
        }
    }
}
#[inline(always)]
/// Get the Rust type given as a type descriptor
pub fn get<T:Compile>() -> Type {
    Compile::jit_type(None::<T>)
}<|endoftext|>


<commit_before>use request::ToParams;
use errors::*;

use std::str::FromStr;

#[derive(Debug)]
pub struct AppId(String);
#[derive(Debug)]
pub struct AppKey(String);
#[derive(Debug)]
pub struct UserKey(String);
#[derive(Debug)]
pub struct OAuthToken(String);

// These trait impls provide a way to reference our types as &str
impl AsRef<str> for AppId {
    fn as_ref(&self) -> &str {
        self.0.as_str()
    }
}

impl AsRef<str> for AppKey {
    fn as_ref(&self) -> &str {
        self.0.as_str()
    }
}

impl AsRef<str> for UserKey {
    fn as_ref(&self) -> &str {
        self.0.as_str()
    }
}

impl AsRef<str> for OAuthToken {
    fn as_ref(&self) -> &str {
        self.0.as_str()
    }
}

// These trait impls provide a way to &str#parse() our Application type
impl FromStr for AppId {
    type Err = Error;

    fn from_str(s: &str) -> Result<AppId> {
        Ok(AppId(s.to_owned()))
    }
}

impl FromStr for AppKey {
    type Err = Error;

    fn from_str(s: &str) -> Result<AppKey> {
        Ok(AppKey(s.to_owned()))
    }
}

impl FromStr for UserKey {
    type Err = Error;

    fn from_str(s: &str) -> Result<UserKey> {
        Ok(UserKey(s.to_owned()))
    }
}

impl FromStr for OAuthToken {
    type Err = Error;

    fn from_str(s: &str) -> Result<OAuthToken> {
        Ok(OAuthToken(s.to_owned()))
    }
}

// These trait impls are similar to FromStr (but are infallible)
impl<'a> From<&'a str> for AppId where Self: FromStr {
    fn from(s: &'a str) -> AppId {
        s.parse().unwrap()
    }
}

impl<'a> From<&'a str> for AppKey where Self: FromStr {
    fn from(s: &'a str) -> AppKey {
        s.parse().unwrap()
    }
}

impl<'a> From<&'a str> for UserKey where Self: FromStr {
    fn from(s: &'a str) -> UserKey {
        s.parse().unwrap()
    }
}

impl<'a> From<&'a str> for OAuthToken where Self: FromStr {
    fn from(s: &'a str) -> OAuthToken {
        s.parse().unwrap()
    }
}

// These trait impls take ownership of a given String and also provide Into<AppId> for String
impl From<String> for AppId {
    fn from(s: String) -> AppId {
        AppId(s)
    }
}

impl From<String> for AppKey {
    fn from(s: String) -> AppKey {
        AppKey(s)
    }
}

impl From<String> for UserKey {
    fn from(s: String) -> UserKey {
        UserKey(s)
    }
}

impl From<String> for OAuthToken {
    fn from(s: String) -> OAuthToken {
        OAuthToken(s)
    }
}

#[derive(Debug)]
pub enum Application {
    AppId(AppId, Option<AppKey>),
    UserKey(UserKey),
    OAuthToken(OAuthToken)
}

// These trait impls build an Application variant out of its required types
impl Into<Application> for AppId {
    fn into(self) -> Application {
        Application::AppId(self, None)
    }
}

impl Into<Application> for (AppId, AppKey) {
    fn into(self) -> Application {
        Application::AppId(self.0, Some(self.1))
    }
}

impl Into<Application> for UserKey {
    fn into(self) -> Application {
        Application::UserKey(self)
    }
}

impl Into<Application> for OAuthToken {
    fn into(self) -> Application {
        Application::OAuthToken(self)
    }
}

impl Application {
    pub fn from_app_id<T: Into<AppId>>(app_id: T) -> Self {
        Application::AppId(app_id.into(), None)
    }

    pub fn from_app_id_and_key<T: Into<AppId>, U: Into<AppKey>>(app_id: T, app_key: U) -> Self {
        Application::AppId(app_id.into(), Some(app_key.into()))
    }

    pub fn from_user_key<T: Into<UserKey>>(user_key: T) -> Self {
        Application::UserKey(user_key.into())
    }

    pub fn from_oauth_token<T: Into<OAuthToken>>(token: T) -> Self {
        Application::OAuthToken(token.into())
    }
}

impl ToParams for Application {
    fn to_params(&self) -> Vec<(&str, &str)>{
        use self::Application::*;

        let mut v = Vec::<(&str, &str)>::with_capacity(2);
        match *self {
            AppId(ref app_id, None) => {
                v.push(("app_id", app_id.as_ref()));
            },
            AppId(ref app_id, Some(ref app_key)) => {
                v.push(("app_id", app_id.as_ref()));
                v.push(("app_key", app_key.as_ref()));
            },
            UserKey(ref user_key) => v.push(("user_key", user_key.as_ref())),
            OAuthToken(ref token) => v.push(("access_token", token.as_ref())),
        };

        v
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn transforms_app_id_into_params() {
        let app_id = "my_app_id";
        let app = Application::from_app_id(app_id.to_owned());

        let result = app.to_params();

        let expected = vec![("app_id", app_id)];
        assert_eq!(expected, result);
    }

    #[test]
    fn transforms_app_id_and_key_into_params() {
        let app_id = "my_app_id";
        let key = "my_key";
        let app = Application::from_app_id_and_key(app_id.to_owned(),
                                                   key.to_owned());

        let result = app.to_params();

        let expected = vec![("app_id", app_id), ("app_key", key)];
        assert_eq!(expected, result);
    }

    #[test]
    fn transforms_user_key_into_params() {
        let user_key = "my_user_key";
        let app = Application::from_user_key(user_key.to_owned());

        let result = app.to_params();

        let expected = vec![("user_key", user_key)];
        assert_eq!(expected, result);
    }

    #[test]
    fn transforms_oauth_token_into_params() {
        let oauth_token = "my_token";
        let app = Application::from_oauth_token(oauth_token.to_owned());

        let result = app.to_params();

        let expected = vec![("access_token", oauth_token)];
        assert_eq!(expected, result);
    }
}
<commit_msg>application: add docs<commit_after>use request::ToParams;
use errors::*;

use std::str::FromStr;

#[derive(Debug)]
pub struct AppId(String);
#[derive(Debug)]
pub struct AppKey(String);
#[derive(Debug)]
pub struct UserKey(String);
#[derive(Debug)]
pub struct OAuthToken(String);

// These trait impls provide a way to reference our types as &str
impl AsRef<str> for AppId {
    fn as_ref(&self) -> &str {
        self.0.as_str()
    }
}

impl AsRef<str> for AppKey {
    fn as_ref(&self) -> &str {
        self.0.as_str()
    }
}

impl AsRef<str> for UserKey {
    fn as_ref(&self) -> &str {
        self.0.as_str()
    }
}

impl AsRef<str> for OAuthToken {
    fn as_ref(&self) -> &str {
        self.0.as_str()
    }
}

// These trait impls provide a way to &str#parse() our Application type
impl FromStr for AppId {
    type Err = Error;

    fn from_str(s: &str) -> Result<AppId> {
        Ok(AppId(s.to_owned()))
    }
}

impl FromStr for AppKey {
    type Err = Error;

    fn from_str(s: &str) -> Result<AppKey> {
        Ok(AppKey(s.to_owned()))
    }
}

impl FromStr for UserKey {
    type Err = Error;

    fn from_str(s: &str) -> Result<UserKey> {
        Ok(UserKey(s.to_owned()))
    }
}

impl FromStr for OAuthToken {
    type Err = Error;

    fn from_str(s: &str) -> Result<OAuthToken> {
        Ok(OAuthToken(s.to_owned()))
    }
}

// These trait impls are similar to FromStr (but are infallible)
impl<'a> From<&'a str> for AppId where Self: FromStr {
    fn from(s: &'a str) -> AppId {
        s.parse().unwrap()
    }
}

impl<'a> From<&'a str> for AppKey where Self: FromStr {
    fn from(s: &'a str) -> AppKey {
        s.parse().unwrap()
    }
}

impl<'a> From<&'a str> for UserKey where Self: FromStr {
    fn from(s: &'a str) -> UserKey {
        s.parse().unwrap()
    }
}

impl<'a> From<&'a str> for OAuthToken where Self: FromStr {
    fn from(s: &'a str) -> OAuthToken {
        s.parse().unwrap()
    }
}

// These trait impls take ownership of a given String and also provide Into<AppId> for String
impl From<String> for AppId {
    fn from(s: String) -> AppId {
        AppId(s)
    }
}

impl From<String> for AppKey {
    fn from(s: String) -> AppKey {
        AppKey(s)
    }
}

impl From<String> for UserKey {
    fn from(s: String) -> UserKey {
        UserKey(s)
    }
}

impl From<String> for OAuthToken {
    fn from(s: String) -> OAuthToken {
        OAuthToken(s)
    }
}

#[derive(Debug)]
pub enum Application {
    AppId(AppId, Option<AppKey>),
    UserKey(UserKey),
    OAuthToken(OAuthToken)
}

// These trait impls build an Application variant out of its required types
impl Into<Application> for AppId {
    fn into(self) -> Application {
        Application::AppId(self, None)
    }
}

impl Into<Application> for (AppId, AppKey) {
    fn into(self) -> Application {
        Application::AppId(self.0, Some(self.1))
    }
}

impl Into<Application> for UserKey {
    fn into(self) -> Application {
        Application::UserKey(self)
    }
}

impl Into<Application> for OAuthToken {
    fn into(self) -> Application {
        Application::OAuthToken(self)
    }
}

impl Application {
    /// Creates a new `Application` from an `AppId`.
    ///
    /// # Examples
    ///
    /// ```
    /// use threescalers::application::*;
    ///
    /// let app = Application::from_app_id("my_app_id");
    /// ```
    pub fn from_app_id<T: Into<AppId>>(app_id: T) -> Self {
        Application::AppId(app_id.into(), None)
    }

    /// Creates a new `Application` from an `AppId` and an `AppKey`.
    ///
    /// # Examples
    ///
    /// ```
    /// use threescalers::application::*;
    ///
    /// let app = Application::from_app_id_and_key("my_app_id", "my_app_key");
    /// ```
    pub fn from_app_id_and_key<T: Into<AppId>, U: Into<AppKey>>(app_id: T, app_key: U) -> Self {
        Application::AppId(app_id.into(), Some(app_key.into()))
    }

    /// Creates a new `Application` from a `UserKey`.
    ///
    /// # Examples
    ///
    /// ```
    /// use threescalers::application::*;
    ///
    /// let app = Application::from_user_key("my_user_key");
    /// ```
    pub fn from_user_key<T: Into<UserKey>>(user_key: T) -> Self {
        Application::UserKey(user_key.into())
    }

    /// Creates a new `Application` from an `AppId`.
    ///
    /// # Examples
    ///
    /// ```
    /// use threescalers::application::*;
    ///
    /// let app = Application::from_oauth_token("my_token");
    /// ```
    pub fn from_oauth_token<T: Into<OAuthToken>>(token: T) -> Self {
        Application::OAuthToken(token.into())
    }
}

impl ToParams for Application {
    fn to_params(&self) -> Vec<(&str, &str)>{
        use self::Application::*;

        let mut v = Vec::<(&str, &str)>::with_capacity(2);
        match *self {
            AppId(ref app_id, None) => {
                v.push(("app_id", app_id.as_ref()));
            },
            AppId(ref app_id, Some(ref app_key)) => {
                v.push(("app_id", app_id.as_ref()));
                v.push(("app_key", app_key.as_ref()));
            },
            UserKey(ref user_key) => v.push(("user_key", user_key.as_ref())),
            OAuthToken(ref token) => v.push(("access_token", token.as_ref())),
        };

        v
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn transforms_app_id_into_params() {
        let app_id = "my_app_id";
        let app = Application::from_app_id(app_id.to_owned());

        let result = app.to_params();

        let expected = vec![("app_id", app_id)];
        assert_eq!(expected, result);
    }

    #[test]
    fn transforms_app_id_and_key_into_params() {
        let app_id = "my_app_id";
        let key = "my_key";
        let app = Application::from_app_id_and_key(app_id.to_owned(),
                                                   key.to_owned());

        let result = app.to_params();

        let expected = vec![("app_id", app_id), ("app_key", key)];
        assert_eq!(expected, result);
    }

    #[test]
    fn transforms_user_key_into_params() {
        let user_key = "my_user_key";
        let app = Application::from_user_key(user_key.to_owned());

        let result = app.to_params();

        let expected = vec![("user_key", user_key)];
        assert_eq!(expected, result);
    }

    #[test]
    fn transforms_oauth_token_into_params() {
        let oauth_token = "my_token";
        let app = Application::from_oauth_token(oauth_token.to_owned());

        let result = app.to_params();

        let expected = vec![("access_token", oauth_token)];
        assert_eq!(expected, result);
    }
}
<|endoftext|>