<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;

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

#[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>())))
}

#[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 res = rustrt::rust_port_id_send(p, data);
    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 {
    rustrt::rust_port_size(***p) != 0u as libc::size_t
}

resource port_ptr<T: send>(po: *rust_port) {
    // 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 {
       recv_::<T>(po);
    }
    rustrt::del_port(po);
}

#[doc(hidden)]
fn recv_chan<T: send>(ch: comm::chan<T>) -> T {
    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 "attempting to receive on unowned channel"
    }

    recv_(*p)
}

#[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;
}

#[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<T: send>(target_port: port_id,
                                  data: T) -> 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(target_os = "win32"))]
fn test_recv_chan_dead() {
    let ch = chan(port());
    send(ch, "flower");
    recv_chan(ch);
}

#[test]
#[ignore(cfg(target_os = "win32"))]
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)
    })
}
<commit_msg>core: Add send/recv/peek methods for both ports and chans<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;

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

#[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>())))
}

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) }

}

resource port_ptr<T: send>(po: *rust_port) {
    // 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 {
       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 res = rustrt::rust_port_id_send(p, data);
    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, recv_(_))
}

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

#[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<T: send>(target_port: port_id,
                                  data: T) -> 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(target_os = "win32"))]
fn test_recv_chan_dead() {
    let ch = chan(port());
    send(ch, "flower");
    recv_chan(ch);
}

#[test]
#[ignore(cfg(target_os = "win32"))]
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();
}<|endoftext|>


<commit_before>/*!

The iteration traits and common implementation

*/

use cmp::{Eq, Ord};

/// A function used to initialize the elements of a sequence
type InitOp<T> = &fn(uint) -> T;

trait BaseIter<A> {
    pure fn each(blk: fn(v: &A) -> bool);
    pure fn size_hint() -> Option<uint>;
}

trait ExtendedIter<A> {
    pure fn eachi(blk: fn(uint, v: &A) -> bool);
    pure fn all(blk: fn(&A) -> bool) -> bool;
    pure fn any(blk: fn(&A) -> bool) -> bool;
    pure fn foldl<B>(+b0: B, blk: fn(&B, &A) -> B) -> B;
    pure fn position(f: fn(A) -> bool) -> Option<uint>;
}

trait EqIter<A:Eq> {
    pure fn contains(x: &A) -> bool;
    pure fn count(x: &A) -> uint;
}

trait Times {
    pure fn times(it: fn() -> bool);
}
trait TimesIx{
    pure fn timesi(it: fn(uint) -> bool);
}

trait CopyableIter<A:Copy> {
    pure fn filter_to_vec(pred: fn(+a: A) -> bool) -> ~[A];
    pure fn map_to_vec<B>(op: fn(+v: A) -> B) -> ~[B];
    pure fn to_vec() -> ~[A];
    pure fn find(p: fn(A) -> bool) -> Option<A>;
}

trait CopyableOrderedIter<A:Copy Ord> {
    pure fn min() -> A;
    pure fn max() -> A;
}

// A trait for sequences that can be by imperatively pushing elements
// onto them.
trait Buildable<A> {
    /**
     * Builds a buildable sequence by calling a provided function with
     * an argument function that pushes an element onto the back of
     * the sequence.
     * This version takes an initial size for the sequence.
     *
     * # Arguments
     *
     * * size - A hint for an initial size of the sequence
     * * builder - A function that will construct the sequence. It recieves
     *             as an argument a function that will push an element
     *             onto the sequence being constructed.
     */
     static pure fn build_sized(size: uint,
                                builder: fn(push: pure fn(+v: A))) -> self;
}

pure fn eachi<A,IA:BaseIter<A>>(self: &IA, blk: fn(uint, v: &A) -> bool) {
    let mut i = 0;
    for self.each |a| {
        if !blk(i, a) { break; }
        i += 1;
    }
}

pure fn all<A,IA:BaseIter<A>>(self: &IA, blk: fn(&A) -> bool) -> bool {
    for self.each |a| {
        if !blk(a) { return false; }
    }
    return true;
}

pure fn any<A,IA:BaseIter<A>>(self: &IA, blk: fn(&A) -> bool) -> bool {
    for self.each |a| {
        if blk(a) { return true; }
    }
    return false;
}

pure fn filter_to_vec<A:Copy,IA:BaseIter<A>>(self: &IA,
                                         prd: fn(+a: A) -> bool) -> ~[A] {
    do vec::build_sized_opt(self.size_hint()) |push| {
        for self.each |a| {
            if prd(*a) { push(*a); }
        }
    }
}

pure fn map_to_vec<A:Copy,B,IA:BaseIter<A>>(self: &IA, op: fn(+v: A) -> B)
    -> ~[B] {
    do vec::build_sized_opt(self.size_hint()) |push| {
        for self.each |a| {
            push(op(*a));
        }
    }
}

pure fn flat_map_to_vec<A:Copy,B:Copy,IA:BaseIter<A>,IB:BaseIter<B>>(
    self: &IA, op: fn(+a: A) -> IB) -> ~[B] {

    do vec::build |push| {
        for self.each |a| {
            for op(*a).each |b| {
                push(*b);
            }
        }
    }
}

pure fn foldl<A,B,IA:BaseIter<A>>(self: &IA, +b0: B, blk: fn(&B, &A) -> B)
    -> B {
    let mut b <- b0;
    for self.each |a| {
        b = blk(&b, a);
    }
    move b
}

pure fn to_vec<A:Copy,IA:BaseIter<A>>(self: &IA) -> ~[A] {
    foldl::<A,~[A],IA>(self, ~[], |r, a| vec::append(*r, ~[*a]))
}

pure fn contains<A:Eq,IA:BaseIter<A>>(self: IA, x: &A) -> bool {
    for self.each |a| {
        if *a == *x { return true; }
    }
    return false;
}

pure fn count<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> uint {
    do foldl(self, 0) |count, value| {
        if *value == *x {
            *count + 1
        } else {
            *count
        }
    }
}

pure fn position<A,IA:BaseIter<A>>(self: IA, f: fn(A) -> bool)
    -> Option<uint>
{
    let mut i = 0;
    for self.each |a| {
        if f(*a) { return Some(i); }
        i += 1;
    }
    return None;
}

// note: 'rposition' would only make sense to provide with a bidirectional
// iter interface, such as would provide "reach" in addition to "each". as is,
// it would have to be implemented with foldr, which is too inefficient.

pure fn repeat(times: uint, blk: fn() -> bool) {
    let mut i = 0u;
    while i < times {
        if !blk() { break }
        i += 1u;
    }
}

pure fn min<A:Copy Ord,IA:BaseIter<A>>(self: &IA) -> A {
    match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
        match a {
          &Some(a_) if a_ < *b => {
             *(move a)
          }
          _ => Some(*b)
        }
    } {
        Some(move val) => val,
        None => fail ~"min called on empty iterator"
    }
}

pure fn max<A:Copy Ord,IA:BaseIter<A>>(self: &IA) -> A {
    match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
        match a {
          &Some(a_) if a_ > *b => {
              *(move a)
          }
          _ => Some(*b)
        }
    } {
        Some(move val) => val,
        None => fail ~"max called on empty iterator"
    }
}

pure fn find<A: Copy,IA:BaseIter<A>>(self: IA,
                                     p: fn(A) -> bool) -> Option<A> {
    for self.each |i| {
        if p(*i) { return Some(*i) }
    }
    return None;
}

// Some functions for just building

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of a sequence.
 *
 * # Arguments
 *
 * * builder - A function that will construct the sequence. It recieves
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pure fn build<A,B: Buildable<A>>(builder: fn(push: pure fn(+v: A))) -> B {
    build_sized(4, builder)
}

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of a sequence.
 * This version takes an initial size for the sequence.
 *
 * # Arguments
 *
 * * size - An option, maybe containing initial size of the sequence
 *          to reserve
 * * builder - A function that will construct the sequence. It recieves
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pure fn build_sized_opt<A,B: Buildable<A>>(
    size: Option<uint>,
    builder: fn(push: pure fn(+v: A))) -> B {

    build_sized(size.get_default(4), builder)
}

// Functions that combine iteration and building

/// Apply a function to each element of an iterable and return the results
fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: IT, f: fn(T) -> U) -> BU {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each() |elem| {
            push(f(*elem));
        }
    }
}

/**
 * Creates and initializes a generic sequence from a function
 *
 * Creates a generic sequence of size `n_elts` and initializes the elements
 * to the value returned by the function `op`.
 */
pure fn from_fn<T,BT: Buildable<T>>(n_elts: uint, op: InitOp<T>) -> BT {
    do build_sized(n_elts) |push| {
        let mut i: uint = 0u;
        while i < n_elts { push(op(i)); i += 1u; }
    }
}

/**
 * Creates and initializes a generic sequence with some element
 *
 * Creates an immutable vector of size `n_elts` and initializes the elements
 * to the value `t`.
 */
pure fn from_elem<T: Copy,BT: Buildable<T>>(n_elts: uint, t: T) -> BT {
    do build_sized(n_elts) |push| {
        let mut i: uint = 0u;
        while i < n_elts { push(t); i += 1u; }
    }
}

/// Appending two generic sequences
#[inline(always)]
pure fn append<T: Copy,IT: BaseIter<T>,BT: Buildable<T>>(
    lhs: IT, rhs: IT) -> BT {
    let size_opt = lhs.size_hint().chain_ref(
        |sz1| rhs.size_hint().map(|sz2| *sz1+*sz2));
    do build_sized_opt(size_opt) |push| {
        for lhs.each |x| { push(*x); }
        for rhs.each |x| { push(*x); }
    }
}

/// Copies a generic sequence, possibly converting it to a different
/// type of sequence.
#[inline(always)]
pure fn copy_seq<T: Copy,IT: BaseIter<T>,BT: Buildable<T>>(
    v: IT) -> BT {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each |x| { push(*x); }
    }
}
<commit_msg>Squash a couple pattern warnings that I missed<commit_after>/*!

The iteration traits and common implementation

*/

use cmp::{Eq, Ord};

/// A function used to initialize the elements of a sequence
type InitOp<T> = &fn(uint) -> T;

trait BaseIter<A> {
    pure fn each(blk: fn(v: &A) -> bool);
    pure fn size_hint() -> Option<uint>;
}

trait ExtendedIter<A> {
    pure fn eachi(blk: fn(uint, v: &A) -> bool);
    pure fn all(blk: fn(&A) -> bool) -> bool;
    pure fn any(blk: fn(&A) -> bool) -> bool;
    pure fn foldl<B>(+b0: B, blk: fn(&B, &A) -> B) -> B;
    pure fn position(f: fn(A) -> bool) -> Option<uint>;
}

trait EqIter<A:Eq> {
    pure fn contains(x: &A) -> bool;
    pure fn count(x: &A) -> uint;
}

trait Times {
    pure fn times(it: fn() -> bool);
}
trait TimesIx{
    pure fn timesi(it: fn(uint) -> bool);
}

trait CopyableIter<A:Copy> {
    pure fn filter_to_vec(pred: fn(+a: A) -> bool) -> ~[A];
    pure fn map_to_vec<B>(op: fn(+v: A) -> B) -> ~[B];
    pure fn to_vec() -> ~[A];
    pure fn find(p: fn(A) -> bool) -> Option<A>;
}

trait CopyableOrderedIter<A:Copy Ord> {
    pure fn min() -> A;
    pure fn max() -> A;
}

// A trait for sequences that can be by imperatively pushing elements
// onto them.
trait Buildable<A> {
    /**
     * Builds a buildable sequence by calling a provided function with
     * an argument function that pushes an element onto the back of
     * the sequence.
     * This version takes an initial size for the sequence.
     *
     * # Arguments
     *
     * * size - A hint for an initial size of the sequence
     * * builder - A function that will construct the sequence. It recieves
     *             as an argument a function that will push an element
     *             onto the sequence being constructed.
     */
     static pure fn build_sized(size: uint,
                                builder: fn(push: pure fn(+v: A))) -> self;
}

pure fn eachi<A,IA:BaseIter<A>>(self: &IA, blk: fn(uint, v: &A) -> bool) {
    let mut i = 0;
    for self.each |a| {
        if !blk(i, a) { break; }
        i += 1;
    }
}

pure fn all<A,IA:BaseIter<A>>(self: &IA, blk: fn(&A) -> bool) -> bool {
    for self.each |a| {
        if !blk(a) { return false; }
    }
    return true;
}

pure fn any<A,IA:BaseIter<A>>(self: &IA, blk: fn(&A) -> bool) -> bool {
    for self.each |a| {
        if blk(a) { return true; }
    }
    return false;
}

pure fn filter_to_vec<A:Copy,IA:BaseIter<A>>(self: &IA,
                                         prd: fn(+a: A) -> bool) -> ~[A] {
    do vec::build_sized_opt(self.size_hint()) |push| {
        for self.each |a| {
            if prd(*a) { push(*a); }
        }
    }
}

pure fn map_to_vec<A:Copy,B,IA:BaseIter<A>>(self: &IA, op: fn(+v: A) -> B)
    -> ~[B] {
    do vec::build_sized_opt(self.size_hint()) |push| {
        for self.each |a| {
            push(op(*a));
        }
    }
}

pure fn flat_map_to_vec<A:Copy,B:Copy,IA:BaseIter<A>,IB:BaseIter<B>>(
    self: &IA, op: fn(+a: A) -> IB) -> ~[B] {

    do vec::build |push| {
        for self.each |a| {
            for op(*a).each |b| {
                push(*b);
            }
        }
    }
}

pure fn foldl<A,B,IA:BaseIter<A>>(self: &IA, +b0: B, blk: fn(&B, &A) -> B)
    -> B {
    let mut b <- b0;
    for self.each |a| {
        b = blk(&b, a);
    }
    move b
}

pure fn to_vec<A:Copy,IA:BaseIter<A>>(self: &IA) -> ~[A] {
    foldl::<A,~[A],IA>(self, ~[], |r, a| vec::append(copy (*r), ~[*a]))
}

pure fn contains<A:Eq,IA:BaseIter<A>>(self: IA, x: &A) -> bool {
    for self.each |a| {
        if *a == *x { return true; }
    }
    return false;
}

pure fn count<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> uint {
    do foldl(self, 0) |count, value| {
        if *value == *x {
            *count + 1
        } else {
            *count
        }
    }
}

pure fn position<A,IA:BaseIter<A>>(self: IA, f: fn(A) -> bool)
    -> Option<uint>
{
    let mut i = 0;
    for self.each |a| {
        if f(*a) { return Some(i); }
        i += 1;
    }
    return None;
}

// note: 'rposition' would only make sense to provide with a bidirectional
// iter interface, such as would provide "reach" in addition to "each". as is,
// it would have to be implemented with foldr, which is too inefficient.

pure fn repeat(times: uint, blk: fn() -> bool) {
    let mut i = 0u;
    while i < times {
        if !blk() { break }
        i += 1u;
    }
}

pure fn min<A:Copy Ord,IA:BaseIter<A>>(self: &IA) -> A {
    match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
        match a {
          &Some(ref a_) if *a_ < *b => {
             *(move a)
          }
          _ => Some(*b)
        }
    } {
        Some(move val) => val,
        None => fail ~"min called on empty iterator"
    }
}

pure fn max<A:Copy Ord,IA:BaseIter<A>>(self: &IA) -> A {
    match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
        match a {
          &Some(ref a_) if *a_ > *b => {
              *(move a)
          }
          _ => Some(*b)
        }
    } {
        Some(move val) => val,
        None => fail ~"max called on empty iterator"
    }
}

pure fn find<A: Copy,IA:BaseIter<A>>(self: IA,
                                     p: fn(A) -> bool) -> Option<A> {
    for self.each |i| {
        if p(*i) { return Some(*i) }
    }
    return None;
}

// Some functions for just building

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of a sequence.
 *
 * # Arguments
 *
 * * builder - A function that will construct the sequence. It recieves
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pure fn build<A,B: Buildable<A>>(builder: fn(push: pure fn(+v: A))) -> B {
    build_sized(4, builder)
}

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of a sequence.
 * This version takes an initial size for the sequence.
 *
 * # Arguments
 *
 * * size - An option, maybe containing initial size of the sequence
 *          to reserve
 * * builder - A function that will construct the sequence. It recieves
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pure fn build_sized_opt<A,B: Buildable<A>>(
    size: Option<uint>,
    builder: fn(push: pure fn(+v: A))) -> B {

    build_sized(size.get_default(4), builder)
}

// Functions that combine iteration and building

/// Apply a function to each element of an iterable and return the results
fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: IT, f: fn(T) -> U) -> BU {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each() |elem| {
            push(f(*elem));
        }
    }
}

/**
 * Creates and initializes a generic sequence from a function
 *
 * Creates a generic sequence of size `n_elts` and initializes the elements
 * to the value returned by the function `op`.
 */
pure fn from_fn<T,BT: Buildable<T>>(n_elts: uint, op: InitOp<T>) -> BT {
    do build_sized(n_elts) |push| {
        let mut i: uint = 0u;
        while i < n_elts { push(op(i)); i += 1u; }
    }
}

/**
 * Creates and initializes a generic sequence with some element
 *
 * Creates an immutable vector of size `n_elts` and initializes the elements
 * to the value `t`.
 */
pure fn from_elem<T: Copy,BT: Buildable<T>>(n_elts: uint, t: T) -> BT {
    do build_sized(n_elts) |push| {
        let mut i: uint = 0u;
        while i < n_elts { push(t); i += 1u; }
    }
}

/// Appending two generic sequences
#[inline(always)]
pure fn append<T: Copy,IT: BaseIter<T>,BT: Buildable<T>>(
    lhs: IT, rhs: IT) -> BT {
    let size_opt = lhs.size_hint().chain_ref(
        |sz1| rhs.size_hint().map(|sz2| *sz1+*sz2));
    do build_sized_opt(size_opt) |push| {
        for lhs.each |x| { push(*x); }
        for rhs.each |x| { push(*x); }
    }
}

/// Copies a generic sequence, possibly converting it to a different
/// type of sequence.
#[inline(always)]
pure fn copy_seq<T: Copy,IT: BaseIter<T>,BT: Buildable<T>>(
    v: IT) -> BT {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each |x| { push(*x); }
    }
}
<|endoftext|>


<commit_before>#[doc = "Random number generation"];

export rng, seed, seeded_rng, weighted, extensions;

enum rctx {}

#[abi = "cdecl"]
native mod rustrt {
    fn rand_seed() -> [u8];
    fn rand_new() -> *rctx;
    fn rand_new_seeded(seed: [u8]) -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

#[doc = "A random number generator"]
iface rng {
    #[doc = "Return the next random integer"]
    fn next() -> u32;
}

#[doc = "A value with a particular weight compared to other values"]
type weighted<T> = { weight: uint, item: T };

#[doc = "Extension methods for random number generators"]
impl extensions for rng {

    #[doc = "Return a random int"]
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    #[doc = "Return an int randomly chosen from the range [start, end], \
             failing if start > end"]
    fn gen_int_from(start: int, end: int) -> int {
        assert start <= end;
        start + int::abs(self.gen_int() % (end - start + 1))
    }

    #[doc = "Return a random i8"]
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    #[doc = "Return a random i16"]
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    #[doc = "Return a random i32"]
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    #[doc = "Return a random i64"]
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    #[doc = "Return a random uint"]
    fn gen_uint() -> uint {
        self.gen_u64() as uint
    }

    #[doc = "Return a uint randomly chosen from the range [start, end], \
             failing if start > end"]
    fn gen_uint_from(start: uint, end: uint) -> uint {
        assert start <= end;
        start + (self.gen_uint() % (end - start + 1u))
    }

    #[doc = "Return a random u8"]
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    #[doc = "Return a random u16"]
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    #[doc = "Return a random u32"]
    fn gen_u32() -> u32 {
        self.next()
    }

    #[doc = "Return a random u64"]
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    #[doc = "Return a random float"]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    #[doc = "Return a random f32"]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    #[doc = "Return a random f64"]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        let scale = u32::max_value as f64;
        ret ((u1 / scale + u2) / scale + u3) / scale;
    }

    #[doc = "Return a random char"]
    fn gen_char() -> char {
        self.next() as char
    }

    #[doc = "Return a char randomly chosen from chars, failing if chars is \
             empty"]
    fn gen_char_from(chars: str) -> char {
        assert !chars.is_empty();
        self.choose(str::chars(chars))
    }

    #[doc = "Return a random bool"]
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    #[doc = "Return a bool with a 1 in n chance of true"]
    fn gen_weighted_bool(n: uint) -> bool {
        if n == 0u {
            true
        } else {
            self.gen_uint_from(1u, n) == 1u
        }
    }

    #[doc = "Return a random string of the specified length composed of A-Z, \
             a-z, 0-9"]
    fn gen_str(len: uint) -> str {
        let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
                      "abcdefghijklmnopqrstuvwxyz" +
                      "0123456789";
        let mut s = "";
        let mut i = 0u;
        while (i < len) {
            s = s + str::from_char(self.gen_char_from(charset));
            i += 1u;
        }
        s
    }

    #[doc = "Return a random byte string of the specified length"]
    fn gen_bytes(len: uint) -> [u8] {
        vec::from_fn(len) {|_i|
            self.gen_u8()
        }
    }

    #[doc = "Choose an item randomly, failing if values is empty"]
    fn choose<T:copy>(values: [T]) -> T {
        self.choose_option(values).get()
    }

    #[doc = "Choose some(item) randomly, returning none if values is empty"]
    fn choose_option<T:copy>(values: [T]) -> option<T> {
        if values.is_empty() {
            none
        } else {
            some(values[self.gen_uint_from(0u, values.len() - 1u)])
        }
    }

    #[doc = "Choose an item respecting the relative weights, failing if \
             the sum of the weights is 0"]
    fn choose_weighted<T: copy>(v : [weighted<T>]) -> T {
        self.choose_weighted_option(v).get()
    }

    #[doc = "Choose some(item) respecting the relative weights, returning \
             none if the sum of the weights is 0"]
    fn choose_weighted_option<T:copy>(v: [weighted<T>]) -> option<T> {
        let mut total = 0u;
        for v.each {|item|
            total += item.weight;
        }
        if total == 0u {
            ret none;
        }
        let chosen = self.gen_uint_from(0u, total - 1u);
        let mut so_far = 0u;
        for v.each {|item|
            so_far += item.weight;
            if so_far > chosen {
                ret some(item.item);
            }
        }
        unreachable();
    }

    #[doc = "Return a vec containing copies of the items, in order, where \
             the weight of the item determines how many copies there are"]
    fn weighted_vec<T:copy>(v: [weighted<T>]) -> [T] {
        let mut r = [];
        for v.each {|item|
            uint::range(0u, item.weight) {|_i|
                r += [item.item];
            }
        }
        r
    }

    #[doc = "Shuffle a vec"]
    fn shuffle<T:copy>(values: [T]) -> [T] {
        let mut m = vec::to_mut(values);
        self.shuffle_mut(m);
        ret vec::from_mut(m);
    }

    #[doc = "Shuffle a mutable vec in place"]
    fn shuffle_mut<T>(&values: [mut T]) {
        let mut i = values.len();
        while i >= 2u {
            // invariant: elements with index >= i have been locked in place.
            i -= 1u;
            // lock element i in place.
            vec::swap(values, i, self.gen_uint_from(0u, i));
        }
    }

}

resource rand_res(c: *rctx) { rustrt::rand_free(c); }

impl of rng for @rand_res {
    fn next() -> u32 { ret rustrt::rand_next(**self); }
}

#[doc = "Create a new random seed for seeded_rng"]
fn seed() -> [u8] {
    rustrt::rand_seed()
}

#[doc = "Create a random number generator with a system specified seed"]
fn rng() -> rng {
    @rand_res(rustrt::rand_new()) as rng
}

#[doc = "Create a random number generator using the specified seed. A \
         generator constructed with a given seed will generate the same \
         sequence of values as all other generators constructed with the \
         same seed. The seed may be any length."]
fn seeded_rng(seed: [u8]) -> rng {
    @rand_res(rustrt::rand_new_seeded(seed)) as rng
}

#[cfg(test)]
mod tests {

    #[test]
    fn rng_seeded() {
        let seed = rand::seed();
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed() {
        // much shorter than generated seeds which are 1024 bytes
        let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn gen_int_from() {
        let r = rand::rng();
        let a = r.gen_int_from(-3, 42);
        assert a >= -3 && a <= 42;
        assert r.gen_int_from(0, 0) == 0;
        assert r.gen_int_from(-12, -12) == -12;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(target_os = "win3"))]
    fn gen_int_from_fail() {
        rand::rng().gen_int_from(5, -2);
    }

    #[test]
    fn gen_uint_from() {
        let r = rand::rng();
        let a = r.gen_uint_from(3u, 42u);
        assert a >= 3u && a <= 42u;
        assert r.gen_uint_from(0u, 0u) == 0u;
        assert r.gen_uint_from(12u, 12u) == 12u;
    }

    #[test]
    #[should_fail]
    fn gen_uint_from_fail() {
        rand::rng().gen_uint_from(5u, 2u);
    }

    #[test]
    fn gen_float() {
        let r = rand::rng();
        let a = r.gen_float();
        let b = r.gen_float();
        log(debug, (a, b));
    }

    #[test]
    fn gen_weighted_bool() {
        let r = rand::rng();
        assert r.gen_weighted_bool(0u) == true;
        assert r.gen_weighted_bool(1u) == true;
    }

    #[test]
    fn gen_str() {
        let r = rand::rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert r.gen_str(0u).len() == 0u;
        assert r.gen_str(10u).len() == 10u;
        assert r.gen_str(16u).len() == 16u;
    }

    #[test]
    fn gen_bytes() {
        let r = rand::rng();
        assert r.gen_bytes(0u).len() == 0u;
        assert r.gen_bytes(10u).len() == 10u;
        assert r.gen_bytes(16u).len() == 16u;
    }

    #[test]
    fn choose() {
        let r = rand::rng();
        assert r.choose([1, 1, 1]) == 1;
    }

    #[test]
    fn choose_option() {
        let r = rand::rng();
        assert r.choose_option([]) == none::<int>;
        assert r.choose_option([1, 1, 1]) == some(1);
    }

    #[test]
    fn choose_weighted() {
        let r = rand::rng();
        assert r.choose_weighted([{weight: 1u, item: 42}]) == 42;
        assert r.choose_weighted([
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == 43;
    }

    #[test]
    fn choose_weighted_option() {
        let r = rand::rng();
        assert r.choose_weighted_option([{weight: 1u, item: 42}]) == some(42);
        assert r.choose_weighted_option([
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == some(43);
        assert r.choose_weighted_option([]) == none::<int>;
    }

    #[test]
    fn weighted_vec() {
        let r = rand::rng();
        let empty: [int] = [];
        assert r.weighted_vec([]) == empty;
        assert r.weighted_vec([
            {weight: 0u, item: 3u},
            {weight: 1u, item: 2u},
            {weight: 2u, item: 1u}
        ]) == [2u, 1u, 1u];
    }

    #[test]
    fn shuffle() {
        let r = rand::rng();
        let empty: [int] = [];
        assert r.shuffle([]) == empty;
        assert r.shuffle([1, 1, 1]) == [1, 1, 1];
    }
}

// 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>core: Ignore another should_fail test on win32<commit_after>#[doc = "Random number generation"];

export rng, seed, seeded_rng, weighted, extensions;

enum rctx {}

#[abi = "cdecl"]
native mod rustrt {
    fn rand_seed() -> [u8];
    fn rand_new() -> *rctx;
    fn rand_new_seeded(seed: [u8]) -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

#[doc = "A random number generator"]
iface rng {
    #[doc = "Return the next random integer"]
    fn next() -> u32;
}

#[doc = "A value with a particular weight compared to other values"]
type weighted<T> = { weight: uint, item: T };

#[doc = "Extension methods for random number generators"]
impl extensions for rng {

    #[doc = "Return a random int"]
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    #[doc = "Return an int randomly chosen from the range [start, end], \
             failing if start > end"]
    fn gen_int_from(start: int, end: int) -> int {
        assert start <= end;
        start + int::abs(self.gen_int() % (end - start + 1))
    }

    #[doc = "Return a random i8"]
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    #[doc = "Return a random i16"]
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    #[doc = "Return a random i32"]
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    #[doc = "Return a random i64"]
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    #[doc = "Return a random uint"]
    fn gen_uint() -> uint {
        self.gen_u64() as uint
    }

    #[doc = "Return a uint randomly chosen from the range [start, end], \
             failing if start > end"]
    fn gen_uint_from(start: uint, end: uint) -> uint {
        assert start <= end;
        start + (self.gen_uint() % (end - start + 1u))
    }

    #[doc = "Return a random u8"]
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    #[doc = "Return a random u16"]
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    #[doc = "Return a random u32"]
    fn gen_u32() -> u32 {
        self.next()
    }

    #[doc = "Return a random u64"]
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    #[doc = "Return a random float"]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    #[doc = "Return a random f32"]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    #[doc = "Return a random f64"]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        let scale = u32::max_value as f64;
        ret ((u1 / scale + u2) / scale + u3) / scale;
    }

    #[doc = "Return a random char"]
    fn gen_char() -> char {
        self.next() as char
    }

    #[doc = "Return a char randomly chosen from chars, failing if chars is \
             empty"]
    fn gen_char_from(chars: str) -> char {
        assert !chars.is_empty();
        self.choose(str::chars(chars))
    }

    #[doc = "Return a random bool"]
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    #[doc = "Return a bool with a 1 in n chance of true"]
    fn gen_weighted_bool(n: uint) -> bool {
        if n == 0u {
            true
        } else {
            self.gen_uint_from(1u, n) == 1u
        }
    }

    #[doc = "Return a random string of the specified length composed of A-Z, \
             a-z, 0-9"]
    fn gen_str(len: uint) -> str {
        let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
                      "abcdefghijklmnopqrstuvwxyz" +
                      "0123456789";
        let mut s = "";
        let mut i = 0u;
        while (i < len) {
            s = s + str::from_char(self.gen_char_from(charset));
            i += 1u;
        }
        s
    }

    #[doc = "Return a random byte string of the specified length"]
    fn gen_bytes(len: uint) -> [u8] {
        vec::from_fn(len) {|_i|
            self.gen_u8()
        }
    }

    #[doc = "Choose an item randomly, failing if values is empty"]
    fn choose<T:copy>(values: [T]) -> T {
        self.choose_option(values).get()
    }

    #[doc = "Choose some(item) randomly, returning none if values is empty"]
    fn choose_option<T:copy>(values: [T]) -> option<T> {
        if values.is_empty() {
            none
        } else {
            some(values[self.gen_uint_from(0u, values.len() - 1u)])
        }
    }

    #[doc = "Choose an item respecting the relative weights, failing if \
             the sum of the weights is 0"]
    fn choose_weighted<T: copy>(v : [weighted<T>]) -> T {
        self.choose_weighted_option(v).get()
    }

    #[doc = "Choose some(item) respecting the relative weights, returning \
             none if the sum of the weights is 0"]
    fn choose_weighted_option<T:copy>(v: [weighted<T>]) -> option<T> {
        let mut total = 0u;
        for v.each {|item|
            total += item.weight;
        }
        if total == 0u {
            ret none;
        }
        let chosen = self.gen_uint_from(0u, total - 1u);
        let mut so_far = 0u;
        for v.each {|item|
            so_far += item.weight;
            if so_far > chosen {
                ret some(item.item);
            }
        }
        unreachable();
    }

    #[doc = "Return a vec containing copies of the items, in order, where \
             the weight of the item determines how many copies there are"]
    fn weighted_vec<T:copy>(v: [weighted<T>]) -> [T] {
        let mut r = [];
        for v.each {|item|
            uint::range(0u, item.weight) {|_i|
                r += [item.item];
            }
        }
        r
    }

    #[doc = "Shuffle a vec"]
    fn shuffle<T:copy>(values: [T]) -> [T] {
        let mut m = vec::to_mut(values);
        self.shuffle_mut(m);
        ret vec::from_mut(m);
    }

    #[doc = "Shuffle a mutable vec in place"]
    fn shuffle_mut<T>(&values: [mut T]) {
        let mut i = values.len();
        while i >= 2u {
            // invariant: elements with index >= i have been locked in place.
            i -= 1u;
            // lock element i in place.
            vec::swap(values, i, self.gen_uint_from(0u, i));
        }
    }

}

resource rand_res(c: *rctx) { rustrt::rand_free(c); }

impl of rng for @rand_res {
    fn next() -> u32 { ret rustrt::rand_next(**self); }
}

#[doc = "Create a new random seed for seeded_rng"]
fn seed() -> [u8] {
    rustrt::rand_seed()
}

#[doc = "Create a random number generator with a system specified seed"]
fn rng() -> rng {
    @rand_res(rustrt::rand_new()) as rng
}

#[doc = "Create a random number generator using the specified seed. A \
         generator constructed with a given seed will generate the same \
         sequence of values as all other generators constructed with the \
         same seed. The seed may be any length."]
fn seeded_rng(seed: [u8]) -> rng {
    @rand_res(rustrt::rand_new_seeded(seed)) as rng
}

#[cfg(test)]
mod tests {

    #[test]
    fn rng_seeded() {
        let seed = rand::seed();
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed() {
        // much shorter than generated seeds which are 1024 bytes
        let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn gen_int_from() {
        let r = rand::rng();
        let a = r.gen_int_from(-3, 42);
        assert a >= -3 && a <= 42;
        assert r.gen_int_from(0, 0) == 0;
        assert r.gen_int_from(-12, -12) == -12;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(target_os = "win3"))]
    fn gen_int_from_fail() {
        rand::rng().gen_int_from(5, -2);
    }

    #[test]
    fn gen_uint_from() {
        let r = rand::rng();
        let a = r.gen_uint_from(3u, 42u);
        assert a >= 3u && a <= 42u;
        assert r.gen_uint_from(0u, 0u) == 0u;
        assert r.gen_uint_from(12u, 12u) == 12u;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(target_os = "win3"))]
    fn gen_uint_from_fail() {
        rand::rng().gen_uint_from(5u, 2u);
    }

    #[test]
    fn gen_float() {
        let r = rand::rng();
        let a = r.gen_float();
        let b = r.gen_float();
        log(debug, (a, b));
    }

    #[test]
    fn gen_weighted_bool() {
        let r = rand::rng();
        assert r.gen_weighted_bool(0u) == true;
        assert r.gen_weighted_bool(1u) == true;
    }

    #[test]
    fn gen_str() {
        let r = rand::rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert r.gen_str(0u).len() == 0u;
        assert r.gen_str(10u).len() == 10u;
        assert r.gen_str(16u).len() == 16u;
    }

    #[test]
    fn gen_bytes() {
        let r = rand::rng();
        assert r.gen_bytes(0u).len() == 0u;
        assert r.gen_bytes(10u).len() == 10u;
        assert r.gen_bytes(16u).len() == 16u;
    }

    #[test]
    fn choose() {
        let r = rand::rng();
        assert r.choose([1, 1, 1]) == 1;
    }

    #[test]
    fn choose_option() {
        let r = rand::rng();
        assert r.choose_option([]) == none::<int>;
        assert r.choose_option([1, 1, 1]) == some(1);
    }

    #[test]
    fn choose_weighted() {
        let r = rand::rng();
        assert r.choose_weighted([{weight: 1u, item: 42}]) == 42;
        assert r.choose_weighted([
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == 43;
    }

    #[test]
    fn choose_weighted_option() {
        let r = rand::rng();
        assert r.choose_weighted_option([{weight: 1u, item: 42}]) == some(42);
        assert r.choose_weighted_option([
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == some(43);
        assert r.choose_weighted_option([]) == none::<int>;
    }

    #[test]
    fn weighted_vec() {
        let r = rand::rng();
        let empty: [int] = [];
        assert r.weighted_vec([]) == empty;
        assert r.weighted_vec([
            {weight: 0u, item: 3u},
            {weight: 1u, item: 2u},
            {weight: 2u, item: 1u}
        ]) == [2u, 1u, 1u];
    }

    #[test]
    fn shuffle() {
        let r = rand::rng();
        let empty: [int] = [];
        assert r.shuffle([]) == empty;
        assert r.shuffle([1, 1, 1]) == [1, 1, 1];
    }
}

// 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>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A bare-metal library supplying functions rustc may lower code to
//!
//! This library is not intended for general use, and is superseded by a system
//! libc if one is available. In a freestanding context, however, common
//! functions such as memset, memcpy, etc are not implemented. This library
//! provides an implementation of these functions which are either required by
//! libcore or called by rustc implicitly.
//!
//! This library is never included by default, and must be manually included if
//! necessary. It is an error to include this library when also linking with
//! the system libc library.

#![crate_name = "rlibc"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/master/")]
#![feature(intrinsics)]

#![no_std]
#![experimental]

// This library defines the builtin functions, so it would be a shame for
// LLVM to optimize these function calls to themselves!
#![no_builtins]

#[cfg(test)] extern crate std;
#[cfg(test)] extern crate native;

// Require the offset intrinsics for LLVM to properly optimize the
// implementations below. If pointer arithmetic is done through integers the
// optimizations start to break down.
extern "rust-intrinsic" {
    fn offset<T>(dst: *const T, offset: int) -> *const T;
}

#[no_mangle]
pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8,
                                n: uint) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *(offset(dest as *const u8, i as int) as *mut u8) =
            *offset(src, i as int);
        i += 1;
    }
    return dest;
}

#[no_mangle]
pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8,
                                 n: uint) -> *mut u8 {
    if src < dest as *const u8 { // copy from end
        let mut i = n;
        while i != 0 {
            i -= 1;
            *(offset(dest as *const u8, i as int) as *mut u8) =
                *offset(src, i as int);
        }
    } else { // copy from beginning
        let mut i = 0;
        while i < n {
            *(offset(dest as *const u8, i as int) as *mut u8) =
                *offset(src, i as int);
            i += 1;
        }
    }
    return dest;
}

#[no_mangle]
pub unsafe extern "C" fn memset(s: *mut u8, c: i32, n: uint) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *(offset(s as *const u8, i as int) as *mut u8) = c as u8;
        i += 1;
    }
    return s;
}

#[no_mangle]
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: uint) -> i32 {
    let mut i = 0;
    while i < n {
        let a = *offset(s1, i as int);
        let b = *offset(s2, i as int);
        if a != b {
            return (a - b) as i32
        }
        i += 1;
    }
    return 0;
}

#[test] fn work_on_windows() { } // FIXME #10872 needed for a happy windows
<commit_msg>rlibc: fix bug in `memcmp()`<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A bare-metal library supplying functions rustc may lower code to
//!
//! This library is not intended for general use, and is superseded by a system
//! libc if one is available. In a freestanding context, however, common
//! functions such as memset, memcpy, etc are not implemented. This library
//! provides an implementation of these functions which are either required by
//! libcore or called by rustc implicitly.
//!
//! This library is never included by default, and must be manually included if
//! necessary. It is an error to include this library when also linking with
//! the system libc library.

#![crate_name = "rlibc"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/master/")]
#![feature(intrinsics)]

#![no_std]
#![experimental]

// This library defines the builtin functions, so it would be a shame for
// LLVM to optimize these function calls to themselves!
#![no_builtins]

#[cfg(test)] extern crate std;
#[cfg(test)] extern crate native;

// Require the offset intrinsics for LLVM to properly optimize the
// implementations below. If pointer arithmetic is done through integers the
// optimizations start to break down.
extern "rust-intrinsic" {
    fn offset<T>(dst: *const T, offset: int) -> *const T;
}

#[no_mangle]
pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8,
                                n: uint) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *(offset(dest as *const u8, i as int) as *mut u8) =
            *offset(src, i as int);
        i += 1;
    }
    return dest;
}

#[no_mangle]
pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8,
                                 n: uint) -> *mut u8 {
    if src < dest as *const u8 { // copy from end
        let mut i = n;
        while i != 0 {
            i -= 1;
            *(offset(dest as *const u8, i as int) as *mut u8) =
                *offset(src, i as int);
        }
    } else { // copy from beginning
        let mut i = 0;
        while i < n {
            *(offset(dest as *const u8, i as int) as *mut u8) =
                *offset(src, i as int);
            i += 1;
        }
    }
    return dest;
}

#[no_mangle]
pub unsafe extern "C" fn memset(s: *mut u8, c: i32, n: uint) -> *mut u8 {
    let mut i = 0;
    while i < n {
        *(offset(s as *const u8, i as int) as *mut u8) = c as u8;
        i += 1;
    }
    return s;
}

#[no_mangle]
pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: uint) -> i32 {
    let mut i = 0;
    while i < n {
        let a = *offset(s1, i as int);
        let b = *offset(s2, i as int);
        if a != b {
            return a as i32 - b as i32
        }
        i += 1;
    }
    return 0;
}

#[test] fn work_on_windows() { } // FIXME #10872 needed for a happy windows
<|endoftext|>


<commit_before>//! A component to use secure communication
//! using keys. It is not yet clear ...
//! basically what libp2p offers is best.
use libp2p::{
    self,
    core::{identity, PeerId},
    pnet::PreSharedKey,
};

pub fn get_p2p_server_id<'a>() -> PeerId {
    PeerId::from(SERVER_KEY.public())
}

lazy_static! {
    pub static ref SERVER_KEY: identity::Keypair = identity::Keypair::generate_ed25519();
    pub static ref PRESHARED_SECRET: PreSharedKey = {
        PreSharedKey::new([
            0x23, 0x89, 0xb4, 0x82, 0x42, 0x89, 0x7e, 0x8f, 0x54, 0x85, 0xd1, 0x3e, 0xd1, 0x2e,
            0xaf, 0x33, 0xc1, 0x44, 0x86, 0x89, 0xde, 0x8c, 0x21, 0xc5, 0x82, 0x8d, 0xe7, 0x70,
            0x34, 0x21, 0x74, 0xc9,
        ])
    };
}
<commit_msg>[documentation] add net key documentation<commit_after>//! A component to use secure communication
//! using keys. It is not yet clear ...
//! basically what libp2p offers is best.
use libp2p::{
    self,
    core::{identity, PeerId},
    pnet::PreSharedKey,
};

/// Gets a newly generated server ID
pub fn get_p2p_server_id<'a>() -> PeerId {
    PeerId::from(SERVER_KEY.public())
}

lazy_static! {
    /// Generates a new ed25519 key-pair
    pub static ref SERVER_KEY: identity::Keypair = identity::Keypair::generate_ed25519();
    /// This is the to be hidden/read preshare key for the net communication process
    pub static ref PRESHARED_SECRET: PreSharedKey = {
        PreSharedKey::new([
            0x23, 0x89, 0xb4, 0x82, 0x42, 0x89, 0x7e, 0x8f, 0x54, 0x85, 0xd1, 0x3e, 0xd1, 0x2e,
            0xaf, 0x33, 0xc1, 0x44, 0x86, 0x89, 0xde, 0x8c, 0x21, 0xc5, 0x82, 0x8d, 0xe7, 0x70,
            0x34, 0x21, 0x74, 0xc9,
        ])
    };
}
<|endoftext|>


<commit_before>use std::io;
use std::io::{Read, BufReader};

use base64;
use serde_json;
use serde_json::Value;

use jsontypes::RawSourceMap;
use types::{RawToken, SourceMap, SourceMapIndex, SourceMapSection, DecodedMap};
use errors::{Result, Error};
use vlq::parse_vlq_segment;

const DATA_PREABLE: &'static str = "data:application/json;base64,";

#[derive(PartialEq)]
enum HeaderState {
    Undecided,
    Junk,
    AwaitingNewline,
    PastHeader,
}

pub struct StripHeaderReader<R: Read> {
    r: R,
    header_state: HeaderState,
}

impl<R: Read> StripHeaderReader<R> {
    pub fn new(reader: R) -> StripHeaderReader<R> {
        StripHeaderReader {
            r: reader,
            header_state: HeaderState::Undecided,
        }
    }
}

fn is_junk_json(byte: u8) -> bool {
    byte == b')' || byte == b']' || byte == b'}' || byte == b'\''
}

impl<R: Read> Read for StripHeaderReader<R> {
    #[inline(always)]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if self.header_state == HeaderState::PastHeader {
            return self.r.read(buf);
        }
        self.strip_head_read(buf)
    }
}

impl<R: Read> StripHeaderReader<R> {
    fn strip_head_read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut backing = vec![0; buf.len()];
        let local_buf: &mut [u8] = &mut *backing;

        loop {
            let read = self.r.read(local_buf)?;
            if read == 0 {
                return Ok(0);
            }
            for (offset, &byte) in local_buf[0..read].iter().enumerate() {
                self.header_state = match self.header_state {
                    HeaderState::Undecided => {
                        if is_junk_json(byte) {
                            HeaderState::Junk
                        } else {
                            (&mut buf[..read]).copy_from_slice(&local_buf[..read]);
                            self.header_state = HeaderState::PastHeader;
                            return Ok(read);
                        }
                    }
                    HeaderState::Junk => {
                        if byte == b'\r' {
                            HeaderState::AwaitingNewline
                        } else if byte == b'\n' {
                            HeaderState::PastHeader
                        } else {
                            HeaderState::Junk
                        }
                    }
                    HeaderState::AwaitingNewline => {
                        if byte == b'\n' {
                            HeaderState::PastHeader
                        } else {
                            fail!(io::Error::new(io::ErrorKind::InvalidData, "expected newline"));
                        }
                    }
                    HeaderState::PastHeader => {
                        let rem = read - offset;
                        (&mut buf[..rem]).copy_from_slice(&local_buf[offset..read]);
                        return Ok(rem);
                    }
                };
            }
        }
    }
}

pub fn strip_junk_header(slice: &[u8]) -> io::Result<&[u8]> {
    if slice.len() == 0 || !is_junk_json(slice[0]) {
        return Ok(slice);
    }
    let mut need_newline = false;
    for (idx, &byte) in slice.iter().enumerate() {
        if need_newline && byte != b'\n' {
            fail!(io::Error::new(io::ErrorKind::InvalidData, "expected newline"));
        } else if is_junk_json(byte) {
            continue;
        } else if byte == b'\r' {
            need_newline = true;
        } else if byte == b'\n' {
            return Ok(&slice[idx..]);
        }
    }
    Ok(&slice[slice.len()..])
}

fn decode_regular(rsm: RawSourceMap) -> Result<SourceMap> {
    let mut dst_col;
    let mut src_id = 0;
    let mut src_line = 0;
    let mut src_col = 0;
    let mut name_id = 0;

    let names = rsm.names.unwrap_or(vec![]);
    let mut sources = rsm.sources.unwrap_or_else(|| vec![]);
    let mappings = rsm.mappings.unwrap_or_else(|| "".into());
    let allocation_size = mappings.matches(&[',', ';'][..]).count() + 10;
    let mut tokens = Vec::with_capacity(allocation_size);

    for (dst_line, line) in mappings.split(';').enumerate() {
        dst_col = 0;

        for segment in line.split(',') {
            if segment.len() == 0 {
                continue;
            }

            let nums = parse_vlq_segment(segment)?;
            dst_col = (dst_col as i64 + nums[0]) as u32;

            let mut src = !0;
            let mut name = !0;

            if nums.len() > 1 {
                if nums.len() != 4 && nums.len() != 5 {
                    fail!(Error::BadSegmentSize(nums.len() as u32));
                }
                src_id = (src_id as i64 + nums[1]) as u32;
                if src_id >= sources.len() as u32 {
                    fail!(Error::BadSourceReference(src_id));
                }

                src = src_id;
                src_line = (src_line as i64 + nums[2]) as u32;
                src_col = (src_col as i64 + nums[3]) as u32;

                if nums.len() > 4 {
                    name_id = (name_id as i64 + nums[4]) as u32;
                    if name_id >= names.len() as u32 {
                        fail!(Error::BadNameReference(name_id));
                    }
                    name = name_id as u32;
                }
            }

            tokens.push(RawToken {
                dst_line: dst_line as u32,
                dst_col: dst_col,
                src_line: src_line,
                src_col: src_col,
                src_id: src,
                name_id: name,
            });
        }
    }

    if let Some(source_root) = rsm.source_root {
        if !source_root.is_empty() {
            let source_root = source_root.trim_right_matches('/');
            sources = sources.into_iter()
                .map(|x| {
                    if x.len() > 0 &&
                       (x.starts_with('/') || x.starts_with("http:") || x.starts_with("https:")) {
                        x
                    } else {
                        format!("{}/{}", source_root, x)
                    }
                })
                .collect();
        }
    }

    // apparently we can encounter some non string types in real world
    // sourcemaps :(
    let names = names.into_iter()
        .map(|val| {
            match val {
                Value::String(s) => s,
                Value::Number(num) => num.to_string(),
                _ => "".into(),
            }
        })
        .collect::<Vec<String>>();

    // file sometimes is not a string for unexplicable reasons
    let file = rsm.file.map(|val| {
        match val {
            Value::String(s) => s,
            _ => "<invalid>".into(),
        }
    });

    Ok(SourceMap::new(file, tokens, names, sources, rsm.sources_content))
}

fn decode_index(rsm: RawSourceMap) -> Result<SourceMapIndex> {
    let mut sections = vec![];

    for mut raw_section in rsm.sections.unwrap_or(vec![]) {
        sections.push(SourceMapSection::new((raw_section.offset.line, raw_section.offset.column),
                                            raw_section.url,
                                            match raw_section.map.take() {
                                                Some(map) => Some(decode_regular(*map)?),
                                                None => None,
                                            }));
    }

    sections.sort_by_key(|sect| sect.get_offset());

    // file sometimes is not a string for unexplicable reasons
    let file = rsm.file.map(|val| {
        match val {
            Value::String(s) => s,
            _ => "<invalid>".into(),
        }
    });

    Ok(SourceMapIndex::new(file, sections))
}

fn decode_common(rsm: RawSourceMap) -> Result<DecodedMap> {
    Ok(if rsm.sections.is_some() {
        DecodedMap::Index(decode_index(rsm)?)
    } else {
        DecodedMap::Regular(decode_regular(rsm)?)
    })
}

/// Decodes a sourcemap or sourcemap index from a reader
///
/// This supports both sourcemaps and sourcemap indexes unless the
/// specialized methods on the individual types.
pub fn decode<R: Read>(rdr: R) -> Result<DecodedMap> {
    let mut rdr = StripHeaderReader::new(rdr);
    let mut rdr = BufReader::new(&mut rdr);
    let rsm: RawSourceMap = serde_json::from_reader(&mut rdr)?;
    decode_common(rsm)
}

/// Decodes a sourcemap or sourcemap index from a byte slice
///
/// This supports both sourcemaps and sourcemap indexes unless the
/// specialized methods on the individual types.
pub fn decode_slice(slice: &[u8]) -> Result<DecodedMap> {
    let content = strip_junk_header(slice)?;
    let rsm: RawSourceMap = serde_json::from_slice(content)?;
    decode_common(rsm)
}

/// Loads a sourcemap from a data URL
pub fn decode_data_url(url: &str) -> Result<DecodedMap> {
    if !url.starts_with(DATA_PREABLE) {
        fail!(Error::InvalidDataUrl);
    }
    let data_b64 = &url[DATA_PREABLE.len()..];
    let data = base64::decode(data_b64).map_err(|_| Error::InvalidDataUrl)?;
    decode_slice(&data[..])
}
<commit_msg>feat: Skip empty sections of the VLQ (#6)<commit_after>use std::io;
use std::io::{Read, BufReader};

use base64;
use serde_json;
use serde_json::Value;

use jsontypes::RawSourceMap;
use types::{RawToken, SourceMap, SourceMapIndex, SourceMapSection, DecodedMap};
use errors::{Result, Error};
use vlq::parse_vlq_segment;

const DATA_PREABLE: &'static str = "data:application/json;base64,";

#[derive(PartialEq)]
enum HeaderState {
    Undecided,
    Junk,
    AwaitingNewline,
    PastHeader,
}

pub struct StripHeaderReader<R: Read> {
    r: R,
    header_state: HeaderState,
}

impl<R: Read> StripHeaderReader<R> {
    pub fn new(reader: R) -> StripHeaderReader<R> {
        StripHeaderReader {
            r: reader,
            header_state: HeaderState::Undecided,
        }
    }
}

fn is_junk_json(byte: u8) -> bool {
    byte == b')' || byte == b']' || byte == b'}' || byte == b'\''
}

impl<R: Read> Read for StripHeaderReader<R> {
    #[inline(always)]
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if self.header_state == HeaderState::PastHeader {
            return self.r.read(buf);
        }
        self.strip_head_read(buf)
    }
}

impl<R: Read> StripHeaderReader<R> {
    fn strip_head_read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let mut backing = vec![0; buf.len()];
        let local_buf: &mut [u8] = &mut *backing;

        loop {
            let read = self.r.read(local_buf)?;
            if read == 0 {
                return Ok(0);
            }
            for (offset, &byte) in local_buf[0..read].iter().enumerate() {
                self.header_state = match self.header_state {
                    HeaderState::Undecided => {
                        if is_junk_json(byte) {
                            HeaderState::Junk
                        } else {
                            (&mut buf[..read]).copy_from_slice(&local_buf[..read]);
                            self.header_state = HeaderState::PastHeader;
                            return Ok(read);
                        }
                    }
                    HeaderState::Junk => {
                        if byte == b'\r' {
                            HeaderState::AwaitingNewline
                        } else if byte == b'\n' {
                            HeaderState::PastHeader
                        } else {
                            HeaderState::Junk
                        }
                    }
                    HeaderState::AwaitingNewline => {
                        if byte == b'\n' {
                            HeaderState::PastHeader
                        } else {
                            fail!(io::Error::new(io::ErrorKind::InvalidData, "expected newline"));
                        }
                    }
                    HeaderState::PastHeader => {
                        let rem = read - offset;
                        (&mut buf[..rem]).copy_from_slice(&local_buf[offset..read]);
                        return Ok(rem);
                    }
                };
            }
        }
    }
}

pub fn strip_junk_header(slice: &[u8]) -> io::Result<&[u8]> {
    if slice.len() == 0 || !is_junk_json(slice[0]) {
        return Ok(slice);
    }
    let mut need_newline = false;
    for (idx, &byte) in slice.iter().enumerate() {
        if need_newline && byte != b'\n' {
            fail!(io::Error::new(io::ErrorKind::InvalidData, "expected newline"));
        } else if is_junk_json(byte) {
            continue;
        } else if byte == b'\r' {
            need_newline = true;
        } else if byte == b'\n' {
            return Ok(&slice[idx..]);
        }
    }
    Ok(&slice[slice.len()..])
}

fn decode_regular(rsm: RawSourceMap) -> Result<SourceMap> {
    let mut dst_col;
    let mut src_id = 0;
    let mut src_line = 0;
    let mut src_col = 0;
    let mut name_id = 0;

    let names = rsm.names.unwrap_or(vec![]);
    let mut sources = rsm.sources.unwrap_or_else(|| vec![]);
    let mappings = rsm.mappings.unwrap_or_else(|| "".into());
    let allocation_size = mappings.matches(&[',', ';'][..]).count() + 10;
    let mut tokens = Vec::with_capacity(allocation_size);

    for (dst_line, line) in mappings.split(';').enumerate() {
        if line.len() == 0 {
            continue;
        }

        dst_col = 0;

        for segment in line.split(',') {
            if segment.len() == 0 {
                continue;
            }

            let nums = parse_vlq_segment(segment)?;
            dst_col = (dst_col as i64 + nums[0]) as u32;

            let mut src = !0;
            let mut name = !0;

            if nums.len() > 1 {
                if nums.len() != 4 && nums.len() != 5 {
                    fail!(Error::BadSegmentSize(nums.len() as u32));
                }
                src_id = (src_id as i64 + nums[1]) as u32;
                if src_id >= sources.len() as u32 {
                    fail!(Error::BadSourceReference(src_id));
                }

                src = src_id;
                src_line = (src_line as i64 + nums[2]) as u32;
                src_col = (src_col as i64 + nums[3]) as u32;

                if nums.len() > 4 {
                    name_id = (name_id as i64 + nums[4]) as u32;
                    if name_id >= names.len() as u32 {
                        fail!(Error::BadNameReference(name_id));
                    }
                    name = name_id as u32;
                }
            }

            tokens.push(RawToken {
                dst_line: dst_line as u32,
                dst_col: dst_col,
                src_line: src_line,
                src_col: src_col,
                src_id: src,
                name_id: name,
            });
        }
    }

    if let Some(source_root) = rsm.source_root {
        if !source_root.is_empty() {
            let source_root = source_root.trim_right_matches('/');
            sources = sources.into_iter()
                .map(|x| {
                    if x.len() > 0 &&
                       (x.starts_with('/') || x.starts_with("http:") || x.starts_with("https:")) {
                        x
                    } else {
                        format!("{}/{}", source_root, x)
                    }
                })
                .collect();
        }
    }

    // apparently we can encounter some non string types in real world
    // sourcemaps :(
    let names = names.into_iter()
        .map(|val| {
            match val {
                Value::String(s) => s,
                Value::Number(num) => num.to_string(),
                _ => "".into(),
            }
        })
        .collect::<Vec<String>>();

    // file sometimes is not a string for unexplicable reasons
    let file = rsm.file.map(|val| {
        match val {
            Value::String(s) => s,
            _ => "<invalid>".into(),
        }
    });

    Ok(SourceMap::new(file, tokens, names, sources, rsm.sources_content))
}

fn decode_index(rsm: RawSourceMap) -> Result<SourceMapIndex> {
    let mut sections = vec![];

    for mut raw_section in rsm.sections.unwrap_or(vec![]) {
        sections.push(SourceMapSection::new((raw_section.offset.line, raw_section.offset.column),
                                            raw_section.url,
                                            match raw_section.map.take() {
                                                Some(map) => Some(decode_regular(*map)?),
                                                None => None,
                                            }));
    }

    sections.sort_by_key(|sect| sect.get_offset());

    // file sometimes is not a string for unexplicable reasons
    let file = rsm.file.map(|val| {
        match val {
            Value::String(s) => s,
            _ => "<invalid>".into(),
        }
    });

    Ok(SourceMapIndex::new(file, sections))
}

fn decode_common(rsm: RawSourceMap) -> Result<DecodedMap> {
    Ok(if rsm.sections.is_some() {
        DecodedMap::Index(decode_index(rsm)?)
    } else {
        DecodedMap::Regular(decode_regular(rsm)?)
    })
}

/// Decodes a sourcemap or sourcemap index from a reader
///
/// This supports both sourcemaps and sourcemap indexes unless the
/// specialized methods on the individual types.
pub fn decode<R: Read>(rdr: R) -> Result<DecodedMap> {
    let mut rdr = StripHeaderReader::new(rdr);
    let mut rdr = BufReader::new(&mut rdr);
    let rsm: RawSourceMap = serde_json::from_reader(&mut rdr)?;
    decode_common(rsm)
}

/// Decodes a sourcemap or sourcemap index from a byte slice
///
/// This supports both sourcemaps and sourcemap indexes unless the
/// specialized methods on the individual types.
pub fn decode_slice(slice: &[u8]) -> Result<DecodedMap> {
    let content = strip_junk_header(slice)?;
    let rsm: RawSourceMap = serde_json::from_slice(content)?;
    decode_common(rsm)
}

/// Loads a sourcemap from a data URL
pub fn decode_data_url(url: &str) -> Result<DecodedMap> {
    if !url.starts_with(DATA_PREABLE) {
        fail!(Error::InvalidDataUrl);
    }
    let data_b64 = &url[DATA_PREABLE.len()..];
    let data = base64::decode(data_b64).map_err(|_| Error::InvalidDataUrl)?;
    decode_slice(&data[..])
}
<|endoftext|>


<commit_before>use std::f64::{EPSILON, MIN};
use std::iter::FromIterator;

use super::{CharIndex, ToChar};
use super::enigma::Enigma;

lazy_static! {
    static ref QGRAMS: Vec<f64> = {
        let f = include_str!("data/quadgrams.txt");

        let mut total: usize = 0;
        let mut qgrams = Vec::new();

        for line in f.lines() {
            let mut iter = line.split(' ');
            let qgram = iter.next().unwrap();
            let count = iter.next().unwrap().parse().unwrap();

            qgrams.push((qgram, count));
            total += count;
        }

        let mut v = vec![EPSILON.ln(); 456_976];

        for (qgram, n) in qgrams {
            let frequency = (n as f64) / (total as f64);
            let index = qgram.chars().fold(0, |acc, c| 26 * acc + c.index());
            v[index] = frequency.ln();
        }

        v
    };
}

/// Decrypts the given string by iterating through multiple possible Enigma
/// configurations, returning the tuple `(plaintext, key, ring, rotor)`
/// corresponding to the most probable plaintext.
pub fn decrypt(msg: &str) -> (String, String, String, String) {
    let mut best_score = MIN;
    let mut best_msg = msg.to_owned();
    let mut best_key = "AAA".to_owned();
    let mut best_ring = "AAA".to_owned();
    let mut best_rotor = "123".to_owned();

    // Rotor and key settings (60*26^3 == 1,054,560 decryptions)
    let r = vec!['1', '2', '3', '4', '5'].into_iter();

    for (slow, mid, fast) in iproduct!(r.clone(), r.clone(), r.clone()) {
        // Skip rotor combinations that contain duplicates
        if (slow == mid) || (slow == fast) || (mid == fast) {
            continue;
        }

        for (a, b, c) in iproduct!(0..26, 0..26, 0..26) {
            let rotor = String::from_iter(vec![slow, mid, fast]);
            let key = String::from_iter(vec![a.to_char(), b.to_char(), c.to_char()]);

            let mut enigma = Enigma::new(&rotor, &key, "AAA", 'B', "");
            let plaintext = enigma.encrypt(msg);
            let score = qgram_score(&plaintext);

            if score > best_score {
                best_score = score;
                best_msg = plaintext;
                best_key = key;
                best_rotor = rotor;
            }
        }
    }

    let first_key = best_key.chars().nth(0).unwrap();

    // Key and ring settings (26^4 == 456,976 decryptions)
    for (key2, key3, ring2, ring3) in iproduct!(0..26, 0..26, 0..26, 0..26) {
        let key = String::from_iter(vec![first_key, key2.to_char(), key3.to_char()]);
        let ring = String::from_iter(vec!['A', ring2.to_char(), ring3.to_char()]);

        let mut enigma = Enigma::new(&best_rotor, &key, &ring, 'B', "");
        let plaintext = enigma.encrypt(msg);
        let score = qgram_score(&plaintext);

        if score > best_score {
            best_score = score;
            best_msg = plaintext;
            best_key = key;
            best_ring = ring;
        }
    }

    (best_msg, best_key, best_ring, best_rotor)
}

/// Strips all non-alphabetic characters from the given message string and
/// returns the sum of the log-probabilities of each quadgram substring.
pub fn qgram_score(msg: &str) -> f64 {
    let msg: Vec<usize> = msg.chars()
        .filter(|&c| c.is_alphabetic())
        .map(|c| c.index())
        .collect();

    if msg.len() < 4 {
        panic!("Input string must be longer than 4 characters.");
    }

    let mut sum = 0.0;

    for i in 0..(msg.len() - 3) {
        let a = msg[i];
        let b = msg[i + 1];
        let c = msg[i + 2];
        let d = msg[i + 3];

        let index = (((a * 26) + b) * 26 + c) * 26 + d;
        sum += QGRAMS[index];
    }

    sum
}

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

    #[test]
    fn qgram_estimate() {
        // Score should be approximately -138.3319940227875
        assert!((qgram_score("THE QUICK BROWN FOX") + 138.3).abs() < 0.1);
    }

    #[test]
    fn sensible_qgram_scores() {
        assert!(qgram_score("AN ENGLISH PHRASE") > qgram_score("ESARHP HSILGNE NA"));
    }

    #[test]
    #[should_panic]
    fn invalid_qgram_check() {
        qgram_score("ABC");
    }
}
<commit_msg>Use Chars iterator for rotor permutations<commit_after>use std::f64::{EPSILON, MIN};
use std::iter::FromIterator;

use super::{CharIndex, ToChar};
use super::enigma::Enigma;

lazy_static! {
    static ref QGRAMS: Vec<f64> = {
        let f = include_str!("data/quadgrams.txt");

        let mut total: usize = 0;
        let mut qgrams = Vec::new();

        for line in f.lines() {
            let mut iter = line.split(' ');
            let qgram = iter.next().unwrap();
            let count = iter.next().unwrap().parse().unwrap();

            qgrams.push((qgram, count));
            total += count;
        }

        let mut v = vec![EPSILON.ln(); 456_976];

        for (qgram, n) in qgrams {
            let frequency = (n as f64) / (total as f64);
            let index = qgram.chars().fold(0, |acc, c| 26 * acc + c.index());
            v[index] = frequency.ln();
        }

        v
    };
}

/// Decrypts the given string by iterating through multiple possible Enigma
/// configurations, returning the tuple `(plaintext, key, ring, rotor)`
/// corresponding to the most probable plaintext.
pub fn decrypt(msg: &str) -> (String, String, String, String) {
    let mut best_score = MIN;
    let mut best_msg = msg.to_owned();
    let mut best_key = "AAA".to_owned();
    let mut best_ring = "AAA".to_owned();
    let mut best_rotor = "123".to_owned();

    // Rotor and key settings (60*26^3 == 1,054,560 decryptions)
    let r = "12345".chars();

    for (slow, mid, fast) in iproduct!(r.clone(), r.clone(), r.clone()) {
        // Skip rotor combinations that contain duplicates
        if (slow == mid) || (slow == fast) || (mid == fast) {
            continue;
        }

        for (a, b, c) in iproduct!(0..26, 0..26, 0..26) {
            let rotor = String::from_iter(vec![slow, mid, fast]);
            let key = String::from_iter(vec![a.to_char(), b.to_char(), c.to_char()]);

            let mut enigma = Enigma::new(&rotor, &key, "AAA", 'B', "");
            let plaintext = enigma.encrypt(msg);
            let score = qgram_score(&plaintext);

            if score > best_score {
                best_score = score;
                best_msg = plaintext;
                best_key = key;
                best_rotor = rotor;
            }
        }
    }

    let first_key = best_key.chars().nth(0).unwrap();

    // Key and ring settings (26^4 == 456,976 decryptions)
    for (key2, key3, ring2, ring3) in iproduct!(0..26, 0..26, 0..26, 0..26) {
        let key = String::from_iter(vec![first_key, key2.to_char(), key3.to_char()]);
        let ring = String::from_iter(vec!['A', ring2.to_char(), ring3.to_char()]);

        let mut enigma = Enigma::new(&best_rotor, &key, &ring, 'B', "");
        let plaintext = enigma.encrypt(msg);
        let score = qgram_score(&plaintext);

        if score > best_score {
            best_score = score;
            best_msg = plaintext;
            best_key = key;
            best_ring = ring;
        }
    }

    (best_msg, best_key, best_ring, best_rotor)
}

/// Strips all non-alphabetic characters from the given message string and
/// returns the sum of the log-probabilities of each quadgram substring.
pub fn qgram_score(msg: &str) -> f64 {
    let msg: Vec<usize> = msg.chars()
        .filter(|&c| c.is_alphabetic())
        .map(|c| c.index())
        .collect();

    if msg.len() < 4 {
        panic!("Input string must be longer than 4 characters.");
    }

    let mut sum = 0.0;

    for i in 0..(msg.len() - 3) {
        let a = msg[i];
        let b = msg[i + 1];
        let c = msg[i + 2];
        let d = msg[i + 3];

        let index = (((a * 26) + b) * 26 + c) * 26 + d;
        sum += QGRAMS[index];
    }

    sum
}

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

    #[test]
    fn qgram_estimate() {
        // Score should be approximately -138.3319940227875
        assert!((qgram_score("THE QUICK BROWN FOX") + 138.3).abs() < 0.1);
    }

    #[test]
    fn sensible_qgram_scores() {
        assert!(qgram_score("AN ENGLISH PHRASE") > qgram_score("ESARHP HSILGNE NA"));
    }

    #[test]
    #[should_panic]
    fn invalid_qgram_check() {
        qgram_score("ABC");
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::path::Path;
use std::process::Command;

fn main() {
    if env::var("SKIP_GRAPHQL_SCHEMA").unwrap_or("0".to_owned()) == "1" {
        return
    }

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_path = Path::new(&out_dir);

    let schema_path = out_path.join("graphql-schema.json");

    let src_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let src_path = Path::new(&src_dir);

    Command::new(env::var("CARGO").unwrap())
        .args(&[
            "install",
            "--path", src_dir.as_ref(),
            "--bin", "turingarena-graphql-schema",
            "--root", out_path.to_str().unwrap(),
            "--force",
            "--debug",
            "--no-default-features",
        ])
        .env("CARGO_TARGET_DIR", out_path.join("graphql-schema-target").to_str().unwrap())
        .env("SKIP_GRAPHQL_SCHEMA", "1")
        .status()
        .unwrap();

    Command::new(env::var("CARGO").unwrap())
        .args(&[
            "install",
            "graphql_client_cli",
            "--root", out_path.to_str().unwrap(),
            "--force",
        ])
        .env("CARGO_TARGET_DIR", out_path.join("graphql-client-cli-target").to_str().unwrap())
        .status()
        .unwrap();

    let schema_file = File::create(&schema_path).unwrap();

    Command::new(out_path.join("bin").join("turingarena-graphql-schema"))
        .stdout(schema_file)
        .status()
        .unwrap();

    Command::new(out_path.join("bin").join("graphql-client"))
        .args(&[
            "generate",
            "--output-directory", out_path.to_str().unwrap(),
            "--schema-path", schema_path.to_str().unwrap(),
            src_path.join("src").join("operations.graphql").to_str().unwrap(),
        ])
        .status()
        .unwrap();
}
<commit_msg>contest: install GraphQL schema gen `--offline`<commit_after>use std::env;
use std::fs::File;
use std::path::Path;
use std::process::Command;

fn main() {
    if env::var("SKIP_GRAPHQL_SCHEMA").unwrap_or("0".to_owned()) == "1" {
        return
    }

    let out_dir = env::var("OUT_DIR").unwrap();
    let out_path = Path::new(&out_dir);

    let schema_path = out_path.join("graphql-schema.json");

    let src_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let src_path = Path::new(&src_dir);

    Command::new(env::var("CARGO").unwrap())
        .args(&[
            "install",
            "--path", src_dir.as_ref(),
            "--bin", "turingarena-graphql-schema",
            "--root", out_path.to_str().unwrap(),
            "--force",
            "--debug",
            "--offline",
            "--no-default-features",
        ])
        .env("CARGO_TARGET_DIR", out_path.join("graphql-schema-target").to_str().unwrap())
        .env("SKIP_GRAPHQL_SCHEMA", "1")
        .status()
        .unwrap();

    Command::new(env::var("CARGO").unwrap())
        .args(&[
            "install",
            "graphql_client_cli",
            "--root", out_path.to_str().unwrap(),
            "--force",
        ])
        .env("CARGO_TARGET_DIR", out_path.join("graphql-client-cli-target").to_str().unwrap())
        .status()
        .unwrap();

    let schema_file = File::create(&schema_path).unwrap();

    Command::new(out_path.join("bin").join("turingarena-graphql-schema"))
        .stdout(schema_file)
        .status()
        .unwrap();

    Command::new(out_path.join("bin").join("graphql-client"))
        .args(&[
            "generate",
            "--output-directory", out_path.to_str().unwrap(),
            "--schema-path", schema_path.to_str().unwrap(),
            src_path.join("src").join("operations.graphql").to_str().unwrap(),
        ])
        .status()
        .unwrap();
}
<|endoftext|>