<commit_before>// extern crate rand;

// use rand::{thread_rng, Rng};

fn score(c1: char, c2: char, scr_match: f64, scr_miss: f64, scr_gap: f64) -> f64 {
    if c1 == '_' || c2 == '_' {
        scr_gap
    } else if c1 == c2 {
        scr_match
    } else {
        scr_miss
    }
}

fn seqs_distance(seq_1: &str,
                 seq_2: &str,
                 scr_match: f64,
                 scr_miss: f64,
                 scr_gap: f64)
                 -> Vec<Vec<f64>> {
    println!("{} vs {}", seq_1, seq_2);
    let len_1 = seq_1.len();
    let len_2 = seq_2.len();
    let mut dist_vec = vec![Vec::new(); seq_2.len()];

    for j in 0..len_2 {
        for i in 0..len_1 {
            dist_vec[j].push(score(seq_1.chars().nth(i).unwrap(),
                                   seq_2.chars().nth(j).unwrap(),
                                   scr_match,
                                   scr_miss,
                                   scr_gap));
        }
        println!("{:?}", dist_vec[j]);
    }
    println!("");

    dist_vec
}

fn seqs_visibility(seq_1: &str,
                   seq_2: &str,
                   scr_match: f64,
                   scr_miss: f64,
                   scr_gap: f64)
                   -> Vec<Vec<f64>> {
    println!("{} vs {}", seq_1, seq_2);
    let len_1 = seq_1.len();
    let len_2 = seq_2.len();
    let mut visib_vec = vec![Vec::new(); seq_2.len()];

    for j in 0..len_2 {
        for i in 0..len_1 {
            visib_vec[j].push(1.0 /
                              score(seq_1.chars().nth(i).unwrap(),
                                    seq_2.chars().nth(j).unwrap(),
                                    scr_match,
                                    scr_miss,
                                    scr_gap));
        }
        println!("{:?}", visib_vec[j]);
    }
    println!("");

    visib_vec
}

fn seqs_pheromone(seq_1: &str, seq_2: &str, init_phero: f64) -> Vec<Vec<f64>> {
    println!("{} vs {}", seq_1, seq_2);
    let len_1 = seq_1.len();
    let len_2 = seq_2.len();
    let mut phero_vec = vec![Vec::new(); seq_2.len()];

    for j in 0..len_2 {
        for _ in 0..len_1 {
            phero_vec[j].push(init_phero);
        }
        println!("{:?}", phero_vec[j]);
    }
    println!("");

    phero_vec
}

fn seqs_deviation(seq_1: &str, seq_2: &str) -> Vec<Vec<f64>> {
    println!("{} vs {}", seq_1, seq_2);
    let mut deviat_vec = vec![Vec::new(); seq_2.len()];

    for j in 0..seq_2.len() {
        for i in 0..seq_1.len() {
            deviat_vec[j].push(1.0 / ((i as f64 - j as f64).abs() + 1.0));
        }
        println!("{:?}", deviat_vec[j]);
    }
    println!("");

    deviat_vec
}

#[derive(Debug)]
struct Ant {
    memory: Vec<usize>,
}

impl Ant {
    fn new() -> Ant {
        Ant {
            // memory: Vec::new()
            memory: vec![0, 3, 3, 4, 1, 5, 5, 5, 3, 6, 6, 6, 4, 8, 0, 0],
        }
    }

    fn print(&self) {
        println!("{:?}", self.memory);
    }
}

#[derive(Debug)]
struct AntColony {
    rho: f64,
    q: i32,
    q_0: f64,
    phi: f64,
    init_phero: f64,
    num_ant: usize,
    num_it: usize,
    seqs: Vec<String>,
    distance: Vec<Vec<Vec<f64>>>,
    visibility: Vec<Vec<Vec<f64>>>,
    pheromone: Vec<Vec<Vec<f64>>>,
    deviation: Vec<Vec<Vec<f64>>>,
}

impl AntColony {
    fn new(rho: f64,
           q: i32,
           q_0: f64,
           phi: f64,
           init_phero: f64,
           num_ant: usize,
           num_it: usize)
           -> AntColony {
        AntColony {
            rho: rho,
            q: q,
            q_0: q_0,
            phi: phi,
            init_phero: init_phero,
            num_ant: num_ant,
            num_it: num_it,
            seqs: Vec::new(),
            distance: Vec::new(),
            visibility: Vec::new(),
            pheromone: Vec::new(),
            deviation: Vec::new(),
        }
    }

    fn set_sequences(&mut self, input: &[&str], scr_match: f64, scr_miss: f64, scr_gap: f64) {
        self.seqs = input.iter().map(|x| x.to_string()).collect();
        let len = self.seqs.len();
        /****************DISTANCIAS*****************/
        for i in 0..len {
            let j = i + 1;
            if j == len {
                break;
            }
            println!("Distancias {} {}", i, j);
            self.distance
                .push(seqs_distance(input[i], input[j], scr_match, scr_miss, scr_gap));
        }
        /****************VISIBILIDAD*****************/
        for i in 0..len {
            let j = i + 1;
            if j == len {
                break;
            }
            println!("Visibilidad {} {}", i, j);
            self.visibility
                .push(seqs_visibility(input[i], input[j], scr_match, scr_miss, scr_gap));
        }
        /****************FEROMONA*****************/
        for i in 0..len {
            let j = i + 1;
            if j == len {
                break;
            }
            println!("Feromona {} {}", i, j);
            self.visibility
                .push(seqs_pheromone(input[i], input[j], self.init_phero));
        }
        /****************DEVIATION*****************/
        for i in 0..len {
            let j = i + 1;
            if j == len {
                break;
            }
            println!("Desviación {} {}", i, j);
            self.visibility.push(seqs_deviation(input[i], input[j]));
        }
    }

    fn print_alignment(&self, ant: &Ant) {
        let n_seqs = self.seqs.len();
        let n_arr = ant.memory.len() / n_seqs;
        let mut indx_iter = ant.memory.iter();
        // let mut alignments = Vec::new();
        for _ in 0..n_arr {
            let mut indx_aux = vec![0; n_seqs];
            let mut offset = vec![0; n_seqs];
            let mut greatest: usize = 0;

            for i in 0..n_seqs {
                let indx = *indx_iter.next().unwrap();
                offset[i] = indx - indx_aux[i];
                indx_aux[i] = indx;
                if greatest < indx {
                    greatest = indx;
                }
            }

            // for i in 0..n_seqs {

            // }

            println!("{}: {:?} -> {:?}", greatest, indx_aux, offset);
        }
    }

    fn iterate(&mut self) {
        let ant = Ant::new();
        ant.print();
        self.print_alignment(&ant);
        println!("Hello world!");
    }
}

fn main() {
    let mut colony = AntColony::new(0.99, 1, 0.7, 0.05, 1.0, 3, 100);
    colony.set_sequences(&["AGTCATTAAT", "CCAATTAGG", "ACCATTC", "GTTCAAGG"],
                         1.0,
                         4.0,
                         5.0);
    colony.iterate();
    // let input = vec!["AGTCATTAAT", "CCAATTAGG", "ACCATTC", "GTTCAAGG"];
    // colony.ant_iteration(&input);
}<commit_msg>some progress on practica 18<commit_after>// extern crate rand;

// use rand::{thread_rng, Rng};

fn score(c1: char, c2: char, scr_match: f64, scr_miss: f64, scr_gap: f64) -> f64 {
    if c1 == '_' || c2 == '_' {
        scr_gap
    } else if c1 == c2 {
        scr_match
    } else {
        scr_miss
    }
}

fn get_hsp(w1: &String, w2: &String, match_scr: f64, mism_scr: f64, gap_scr: f64) -> f64 {
    let mut hsp = 0.0;

    let mut chars2 = w2.chars();
    for c1 in w1.chars() {
        let c2 = chars2.next().unwrap();
        hsp += if c1 == '_' || c2 == '_' {
            gap_scr
        } else if c1 == c2 {
            match_scr
        } else {
            mism_scr
        } as f64;
    }

    hsp
}

fn seqs_distance(seq_1: &str,
                 seq_2: &str,
                 scr_match: f64,
                 scr_miss: f64,
                 scr_gap: f64)
                 -> Vec<Vec<f64>> {
    println!("{} vs {}", seq_1, seq_2);
    let len_1 = seq_1.len();
    let len_2 = seq_2.len();
    let mut dist_vec = vec![Vec::new(); seq_2.len()];

    for j in 0..len_2 {
        for i in 0..len_1 {
            dist_vec[j].push(score(seq_1.chars().nth(i).unwrap(),
                                   seq_2.chars().nth(j).unwrap(),
                                   scr_match,
                                   scr_miss,
                                   scr_gap));
        }
        println!("{:?}", dist_vec[j]);
    }
    println!("");

    dist_vec
}

fn seqs_visibility(seq_1: &str,
                   seq_2: &str,
                   scr_match: f64,
                   scr_miss: f64,
                   scr_gap: f64)
                   -> Vec<Vec<f64>> {
    println!("{} vs {}", seq_1, seq_2);
    let len_1 = seq_1.len();
    let len_2 = seq_2.len();
    let mut visib_vec = vec![Vec::new(); seq_2.len()];

    for j in 0..len_2 {
        for i in 0..len_1 {
            visib_vec[j].push(1.0 /
                              score(seq_1.chars().nth(i).unwrap(),
                                    seq_2.chars().nth(j).unwrap(),
                                    scr_match,
                                    scr_miss,
                                    scr_gap));
        }
        println!("{:?}", visib_vec[j]);
    }
    println!("");

    visib_vec
}

fn seqs_pheromone(seq_1: &str, seq_2: &str, init_phero: f64) -> Vec<Vec<f64>> {
    println!("{} vs {}", seq_1, seq_2);
    let len_1 = seq_1.len();
    let len_2 = seq_2.len();
    let mut phero_vec = vec![Vec::new(); seq_2.len()];

    for j in 0..len_2 {
        for _ in 0..len_1 {
            phero_vec[j].push(init_phero);
        }
        println!("{:?}", phero_vec[j]);
    }
    println!("");

    phero_vec
}

fn seqs_deviation(seq_1: &str, seq_2: &str) -> Vec<Vec<f64>> {
    println!("{} vs {}", seq_1, seq_2);
    let mut deviat_vec = vec![Vec::new(); seq_2.len()];

    for j in 0..seq_2.len() {
        for i in 0..seq_1.len() {
            deviat_vec[j].push(1.0 / ((i as f64 - j as f64).abs() + 1.0));
        }
        println!("{:?}", deviat_vec[j]);
    }
    println!("");

    deviat_vec
}

#[derive(Debug)]
struct Ant {
    memory: Vec<usize>,
}

impl Ant {
    fn new() -> Ant {
        Ant {
            // memory: Vec::new()
            // memory: vec![0, 3, 3, 4, 1, 5, 5, 5, 3, 6, 6, 6, 4, 8, 0, 0],
            memory: vec![2, 1, 1, 3, 4, 3, 3, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 0, 0],
        }
    }

    fn print(&self) {
        println!("{:?}", self.memory);
    }
}

#[derive(Debug)]
struct AntColony {
    rho: f64,
    q: i32,
    q_0: f64,
    phi: f64,
    init_phero: f64,
    num_ant: usize,
    num_it: usize,
    seqs: Vec<String>,
    distance: Vec<Vec<Vec<f64>>>,
    visibility: Vec<Vec<Vec<f64>>>,
    pheromone: Vec<Vec<Vec<f64>>>,
    deviation: Vec<Vec<Vec<f64>>>,
}

impl AntColony {
    fn new(rho: f64,
           q: i32,
           q_0: f64,
           phi: f64,
           init_phero: f64,
           num_ant: usize,
           num_it: usize)
           -> AntColony {
        AntColony {
            rho: rho,
            q: q,
            q_0: q_0,
            phi: phi,
            init_phero: init_phero,
            num_ant: num_ant,
            num_it: num_it,
            seqs: Vec::new(),
            distance: Vec::new(),
            visibility: Vec::new(),
            pheromone: Vec::new(),
            deviation: Vec::new(),
        }
    }

    fn set_sequences(&mut self, input: &[&str], scr_match: f64, scr_miss: f64, scr_gap: f64) {
        self.seqs = input.iter().map(|x| x.to_string()).collect();
        let len = self.seqs.len();
        /****************DISTANCIAS*****************/
        for i in 0..len {
            let j = i + 1;
            if j == len {
                break;
            }
            println!("Distancias {} {}", i, j);
            self.distance
                .push(seqs_distance(input[i], input[j], scr_match, scr_miss, scr_gap));
        }
        /****************VISIBILIDAD*****************/
        for i in 0..len {
            let j = i + 1;
            if j == len {
                break;
            }
            println!("Visibilidad {} {}", i, j);
            self.visibility
                .push(seqs_visibility(input[i], input[j], scr_match, scr_miss, scr_gap));
        }
        /****************FEROMONA*****************/
        for i in 0..len {
            let j = i + 1;
            if j == len {
                break;
            }
            println!("Feromona {} {}", i, j);
            self.visibility
                .push(seqs_pheromone(input[i], input[j], self.init_phero));
        }
        /****************DEVIATION*****************/
        for i in 0..len {
            let j = i + 1;
            if j == len {
                break;
            }
            println!("Desviación {} {}", i, j);
            self.visibility.push(seqs_deviation(input[i], input[j]));
        }
    }

    fn scr_alignment(&self, ant: &Ant) -> f64 {
        let n_seqs = self.seqs.len();
        let n_arr = ant.memory.len() / n_seqs;
        let mut indx_iter = ant.memory.iter();
        let mut alignments = vec![String::new(); n_seqs];
        let mut indx_aux = vec![0; n_seqs];
        let mut offset = vec![0; n_seqs];
        let mut seqs = self.seqs.clone();

        for x in 0..n_arr {
            let mut greatest_offset = 0;
            for i in 0..n_seqs {
                let indx = *indx_iter.next().unwrap();

                offset[i] = if indx > 0 || x == 0 {
                                indx - indx_aux[i]
                            } else {
                                1
                            };

                if greatest_offset < offset[i] {
                    greatest_offset = offset[i];
                }

                indx_aux[i] = indx;
            }

            for i in 0..n_seqs {
                // print!("{} - {} -> ", greatest_offset, offset[i]);
                let n_dashes = greatest_offset - offset[i];
                // print!("\"-\" = {}: ", n_dashes);

                let slice = if seqs[i].len() > 0 {
                    let remnant = seqs[i].split_off(offset[i]);
                    let slice = seqs[i].clone();
                    seqs[i] = remnant;
                    slice
                } else {
                    seqs[i].clone()
                };
                alignments[i].push_str(slice.as_str());

                for _ in 0..n_dashes {
                    alignments[i].push_str("_");
                }
                // alignments[i].push_str(".");
            }

        }

        let mut lngst_seq = 0;
        for i in 0..n_seqs {
            if lngst_seq < seqs[i].len() {
                lngst_seq = seqs[i].len();
            }
            alignments[i].push_str(seqs[i].as_str());
        }

        for i in 0..n_seqs {
            for _ in 0..(lngst_seq - seqs[i].len()) {
                alignments[i].push_str("_");
            }
        }

        for seq in &alignments {
            println!("{}", seq);
        }

        let mut score = 0.0;
        // for i in 0..n_seqs {
        //     for j in i + 1..n_seqs {
        //         score += get_hsp(alignments[i], alignments[j], match_scr, mism_scr, gap_scr);
        //     }
        // }

        println!("Suma Pares: {}", score);
        score
    }

    fn iterate(&mut self) {
        let ant = Ant::new();
        ant.print();
        let score = self.scr_alignment(&ant);
        println!("Hello world!");
    }
}

fn main() {
    let mut colony = AntColony::new(0.99, 1, 0.7, 0.05, 1.0, 3, 100);
    colony.set_sequences(&["AGTCATTAAT", "CCAATTAGG", "ACCATTC", "GTTCAAGG"],
                         1.0,
                         4.0,
                         5.0);
    colony.iterate();
    // let input = vec!["AGTCATTAAT", "CCAATTAGG", "ACCATTC", "GTTCAAGG"];
    // colony.ant_iteration(&input);
}<|endoftext|>


<commit_before>#[doc = "

A task-based interface to the uv loop

The I/O task runs in its own single-threaded scheduler.  By using the
`interact` function you can execute code in a uv callback.

"];

export iotask::{};
export spawn_iotask;
export interact;
export exit;

import libc::c_void;
import ptr::addr_of;
import comm::{port, chan, methods};
import ll = uv_ll;

#[doc = "
Used to abstract-away direct interaction with a libuv loop.
"]
enum iotask {
    iotask_({
        async_handle: *ll::uv_async_t,
        op_chan: chan<iotask_msg>
    })
}

fn spawn_iotask(-builder: task::builder) -> iotask {

    import task::{set_opts, get_opts, single_threaded, run};

    let iotask_po = port::<iotask>();
    let iotask_ch = iotask_po.chan();

    set_opts(builder, {
        sched: some({
            mode: single_threaded,
            native_stack_size: none
        })
        with get_opts(builder)
    });

    run(builder) {||
        #debug("entering libuv task");
        run_loop(iotask_ch);
        #debug("libuv task exiting");
    };

    iotask_po.recv()
}

#[doc = "
Provide a callback to be processed by `iotask`

The primary way to do operations again a running `iotask` that
doesn't involve creating a uv handle via `safe_handle`

# Warning

This function is the only safe way to interact with _any_ `iotask`.
Using functions in the `uv::ll` module outside of the `cb` passed into
this function is _very dangerous_.

# Arguments

* iotask - a uv I/O task that you want to do operations against
* cb - a function callback to be processed on the running loop's
thread. The only parameter passed in is an opaque pointer representing the
running `uv_loop_t*`. In the context of this callback, it is safe to use
this pointer to do various uv_* API calls contained within the `uv::ll`
module. It is not safe to send the `loop_ptr` param to this callback out
via ports/chans.
"]
unsafe fn interact(iotask: iotask,
                   -cb: fn~(*c_void)) {
    send_msg(iotask, interaction(cb));
}

#[doc="
Shut down the I/O task

Is used to signal to the loop that it should close the internally-held
async handle and do a sanity check to make sure that all other handles are
closed, causing a failure otherwise.
"]
fn exit(iotask: iotask) unsafe {
    send_msg(iotask, teardown_loop);
}

// INTERNAL API

enum iotask_msg {
    interaction (fn~(*libc::c_void)),
    teardown_loop
}

#[doc = "
Run the loop and begin handling messages
"]
fn run_loop(iotask_ch: chan<iotask>) unsafe {
    let msg_po = port::<iotask_msg>();
    let loop_ptr = ll::loop_new();
    // set up the special async handle we'll use to allow multi-task
    // communication with this loop
    let async = ll::async_t();
    let async_handle = addr_of(async);
    // associate the async handle with the loop
    ll::async_init(loop_ptr, async_handle, wake_up_cb);

    // initialize our loop data and store it in the loop
    let data: iotask_loop_data = {
        async_handle: async_handle,
        mut active: true,
        msg_po_ptr: addr_of(msg_po)
    };
    ll::set_data_for_uv_handle(async_handle, addr_of(data));

    // Send out a handle through which folks can talk to us
    // while we dwell in the I/O loop
    let iotask = iotask_({
        async_handle: async_handle,
        op_chan: msg_po.chan()
    });
    iotask_ch.send(iotask);

    log(debug, "about to run uv loop");
    // enter the loop... this blocks until the loop is done..
    ll::run(loop_ptr);
    log(debug, "uv loop ended");
    ll::loop_delete(loop_ptr);
}

// data that lives for the lifetime of the high-evel oo
type iotask_loop_data = {
    async_handle: *ll::uv_async_t,
    mut active: bool,
    msg_po_ptr: *port<iotask_msg>
};

fn send_msg(iotask: iotask,
            -msg: iotask_msg) unsafe {
    iotask.op_chan.send(msg);
    ll::async_send(iotask.async_handle);
}

// this will be invoked by a call to uv::hl::interact() with
// the high_level_loop corresponding to this async_handle. We
// simply check if the loop is active and, if so, invoke the
// user-supplied on_wake callback that is stored in the loop's
// data member
crust fn wake_up_cb(async_handle: *ll::uv_async_t,
                    status: int) unsafe {
    log(debug, #fmt("wake_up_cb crust.. handle: %? status: %?",
                     async_handle, status));
    let loop_ptr = ll::get_loop_for_uv_handle(async_handle);
    let data = ll::get_data_for_uv_handle(async_handle) as *iotask_loop_data;
    // FIXME: What is this checking?
    if (*data).active {
        let msg_po = *((*data).msg_po_ptr);
        while msg_po.peek() {
            let msg = msg_po.recv();
            if (*data).active {
                alt msg {
                  interaction(cb) {
                    cb(loop_ptr);
                  }
                  teardown_loop {
                    begin_teardown(data);
                  }
                }
            } else {
                // FIXME: drop msg ?
            }
        }
    } else {
        // loop not active
    }
}

crust fn tear_down_close_cb(handle: *ll::uv_async_t) unsafe {
    let loop_ptr = ll::get_loop_for_uv_handle(handle);
    let loop_refs = ll::loop_refcount(loop_ptr);
    log(debug, #fmt("tear_down_close_cb called, closing handle at %? refs %?",
                    handle, loop_refs));
    assert loop_refs == 1i32;
}

fn begin_teardown(data: *iotask_loop_data) unsafe {
    log(debug, "iotask begin_teardown() called, close async_handle");
    // call user-suppled before_tear_down cb
    let async_handle = (*data).async_handle;
    ll::close(async_handle as *c_void, tear_down_close_cb);
}

#[cfg(test)]
mod test {
    crust fn async_close_cb(handle: *ll::uv_async_t) unsafe {
        log(debug, #fmt("async_close_cb handle %?", handle));
        let exit_ch = (*(ll::get_data_for_uv_handle(handle)
                        as *ah_data)).exit_ch;
        comm::send(exit_ch, ());
    }
    crust fn async_handle_cb(handle: *ll::uv_async_t, status: libc::c_int)
        unsafe {
        log(debug, #fmt("async_handle_cb handle %? status %?",handle,status));
        ll::close(handle, async_close_cb);
    }
    type ah_data = {
        iotask: iotask,
        exit_ch: comm::chan<()>
    };
    fn impl_uv_iotask_async(iotask: iotask) unsafe {
        let async_handle = ll::async_t();
        let ah_ptr = ptr::addr_of(async_handle);
        let exit_po = comm::port::<()>();
        let exit_ch = comm::chan(exit_po);
        let ah_data = {
            iotask: iotask,
            exit_ch: exit_ch
        };
        let ah_data_ptr = ptr::addr_of(ah_data);
        interact(iotask) {|loop_ptr|
            ll::async_init(loop_ptr, ah_ptr, async_handle_cb);
            ll::set_data_for_uv_handle(ah_ptr, ah_data_ptr as *libc::c_void);
            ll::async_send(ah_ptr);
        };
        comm::recv(exit_po);
    }

    // this fn documents the bear minimum neccesary to roll your own
    // high_level_loop
    unsafe fn spawn_test_loop(exit_ch: comm::chan<()>) -> iotask {
        let iotask_port = comm::port::<iotask>();
        let iotask_ch = comm::chan(iotask_port);
        task::spawn_sched(task::manual_threads(1u)) {||
            run_loop(iotask_ch);
            exit_ch.send(());
        };
        ret comm::recv(iotask_port);
    }

    crust fn lifetime_handle_close(handle: *libc::c_void) unsafe {
        log(debug, #fmt("lifetime_handle_close ptr %?", handle));
    }

    crust fn lifetime_async_callback(handle: *libc::c_void,
                                     status: libc::c_int) {
        log(debug, #fmt("lifetime_handle_close ptr %? status %?",
                        handle, status));
    }

    #[test]
    fn test_uv_iotask_async() unsafe {
        let exit_po = comm::port::<()>();
        let exit_ch = comm::chan(exit_po);
        let iotask = spawn_test_loop(exit_ch);

        // using this handle to manage the lifetime of the high_level_loop,
        // as it will exit the first time one of the impl_uv_hl_async() is
        // cleaned up with no one ref'd handles on the loop (Which can happen
        // under race-condition type situations.. this ensures that the loop
        // lives until, at least, all of the impl_uv_hl_async() runs have been
        // called, at least.
        let work_exit_po = comm::port::<()>();
        let work_exit_ch = comm::chan(work_exit_po);
        iter::repeat(7u) {||
            task::spawn_sched(task::manual_threads(1u), {||
                impl_uv_iotask_async(iotask);
                comm::send(work_exit_ch, ());
            });
        };
        iter::repeat(7u) {||
            comm::recv(work_exit_po);
        };
        log(debug, "sending teardown_loop msg..");
        exit(iotask);
        comm::recv(exit_po);
        log(debug, "after recv on exit_po.. exiting..");
    }
}
<commit_msg>std: Remove unused iotask field `active`<commit_after>#[doc = "

A task-based interface to the uv loop

The I/O task runs in its own single-threaded scheduler.  By using the
`interact` function you can execute code in a uv callback.

"];

export iotask::{};
export spawn_iotask;
export interact;
export exit;

import libc::c_void;
import ptr::addr_of;
import comm::{port, chan, methods};
import ll = uv_ll;

#[doc = "
Used to abstract-away direct interaction with a libuv loop.
"]
enum iotask {
    iotask_({
        async_handle: *ll::uv_async_t,
        op_chan: chan<iotask_msg>
    })
}

fn spawn_iotask(-builder: task::builder) -> iotask {

    import task::{set_opts, get_opts, single_threaded, run};

    let iotask_po = port::<iotask>();
    let iotask_ch = iotask_po.chan();

    set_opts(builder, {
        sched: some({
            mode: single_threaded,
            native_stack_size: none
        })
        with get_opts(builder)
    });

    run(builder) {||
        #debug("entering libuv task");
        run_loop(iotask_ch);
        #debug("libuv task exiting");
    };

    iotask_po.recv()
}

#[doc = "
Provide a callback to be processed by `iotask`

The primary way to do operations again a running `iotask` that
doesn't involve creating a uv handle via `safe_handle`

# Warning

This function is the only safe way to interact with _any_ `iotask`.
Using functions in the `uv::ll` module outside of the `cb` passed into
this function is _very dangerous_.

# Arguments

* iotask - a uv I/O task that you want to do operations against
* cb - a function callback to be processed on the running loop's
thread. The only parameter passed in is an opaque pointer representing the
running `uv_loop_t*`. In the context of this callback, it is safe to use
this pointer to do various uv_* API calls contained within the `uv::ll`
module. It is not safe to send the `loop_ptr` param to this callback out
via ports/chans.
"]
unsafe fn interact(iotask: iotask,
                   -cb: fn~(*c_void)) {
    send_msg(iotask, interaction(cb));
}

#[doc="
Shut down the I/O task

Is used to signal to the loop that it should close the internally-held
async handle and do a sanity check to make sure that all other handles are
closed, causing a failure otherwise.
"]
fn exit(iotask: iotask) unsafe {
    send_msg(iotask, teardown_loop);
}

// INTERNAL API

enum iotask_msg {
    interaction (fn~(*libc::c_void)),
    teardown_loop
}

#[doc = "
Run the loop and begin handling messages
"]
fn run_loop(iotask_ch: chan<iotask>) unsafe {
    let msg_po = port::<iotask_msg>();
    let loop_ptr = ll::loop_new();
    // set up the special async handle we'll use to allow multi-task
    // communication with this loop
    let async = ll::async_t();
    let async_handle = addr_of(async);
    // associate the async handle with the loop
    ll::async_init(loop_ptr, async_handle, wake_up_cb);

    // initialize our loop data and store it in the loop
    let data: iotask_loop_data = {
        async_handle: async_handle,
        msg_po_ptr: addr_of(msg_po)
    };
    ll::set_data_for_uv_handle(async_handle, addr_of(data));

    // Send out a handle through which folks can talk to us
    // while we dwell in the I/O loop
    let iotask = iotask_({
        async_handle: async_handle,
        op_chan: msg_po.chan()
    });
    iotask_ch.send(iotask);

    log(debug, "about to run uv loop");
    // enter the loop... this blocks until the loop is done..
    ll::run(loop_ptr);
    log(debug, "uv loop ended");
    ll::loop_delete(loop_ptr);
}

// data that lives for the lifetime of the high-evel oo
type iotask_loop_data = {
    async_handle: *ll::uv_async_t,
    msg_po_ptr: *port<iotask_msg>
};

fn send_msg(iotask: iotask,
            -msg: iotask_msg) unsafe {
    iotask.op_chan.send(msg);
    ll::async_send(iotask.async_handle);
}

// this will be invoked by a call to uv::hl::interact() with
// the high_level_loop corresponding to this async_handle. We
// simply check if the loop is active and, if so, invoke the
// user-supplied on_wake callback that is stored in the loop's
// data member
crust fn wake_up_cb(async_handle: *ll::uv_async_t,
                    status: int) unsafe {
    log(debug, #fmt("wake_up_cb crust.. handle: %? status: %?",
                     async_handle, status));
    let loop_ptr = ll::get_loop_for_uv_handle(async_handle);
    let data = ll::get_data_for_uv_handle(async_handle) as *iotask_loop_data;
    let msg_po = *((*data).msg_po_ptr);
    while msg_po.peek() {
        let msg = msg_po.recv();
        alt msg {
          interaction(cb) {
            cb(loop_ptr);
          }
          teardown_loop {
            begin_teardown(data);
          }
        }
    }
}

fn begin_teardown(data: *iotask_loop_data) unsafe {
    log(debug, "iotask begin_teardown() called, close async_handle");
    // call user-suppled before_tear_down cb
    let async_handle = (*data).async_handle;
    ll::close(async_handle as *c_void, tear_down_close_cb);
}

crust fn tear_down_close_cb(handle: *ll::uv_async_t) unsafe {
    let loop_ptr = ll::get_loop_for_uv_handle(handle);
    let loop_refs = ll::loop_refcount(loop_ptr);
    log(debug, #fmt("tear_down_close_cb called, closing handle at %? refs %?",
                    handle, loop_refs));
    assert loop_refs == 1i32;
}

#[cfg(test)]
mod test {
    crust fn async_close_cb(handle: *ll::uv_async_t) unsafe {
        log(debug, #fmt("async_close_cb handle %?", handle));
        let exit_ch = (*(ll::get_data_for_uv_handle(handle)
                        as *ah_data)).exit_ch;
        comm::send(exit_ch, ());
    }
    crust fn async_handle_cb(handle: *ll::uv_async_t, status: libc::c_int)
        unsafe {
        log(debug, #fmt("async_handle_cb handle %? status %?",handle,status));
        ll::close(handle, async_close_cb);
    }
    type ah_data = {
        iotask: iotask,
        exit_ch: comm::chan<()>
    };
    fn impl_uv_iotask_async(iotask: iotask) unsafe {
        let async_handle = ll::async_t();
        let ah_ptr = ptr::addr_of(async_handle);
        let exit_po = comm::port::<()>();
        let exit_ch = comm::chan(exit_po);
        let ah_data = {
            iotask: iotask,
            exit_ch: exit_ch
        };
        let ah_data_ptr = ptr::addr_of(ah_data);
        interact(iotask) {|loop_ptr|
            ll::async_init(loop_ptr, ah_ptr, async_handle_cb);
            ll::set_data_for_uv_handle(ah_ptr, ah_data_ptr as *libc::c_void);
            ll::async_send(ah_ptr);
        };
        comm::recv(exit_po);
    }

    // this fn documents the bear minimum neccesary to roll your own
    // high_level_loop
    unsafe fn spawn_test_loop(exit_ch: comm::chan<()>) -> iotask {
        let iotask_port = comm::port::<iotask>();
        let iotask_ch = comm::chan(iotask_port);
        task::spawn_sched(task::manual_threads(1u)) {||
            run_loop(iotask_ch);
            exit_ch.send(());
        };
        ret comm::recv(iotask_port);
    }

    crust fn lifetime_handle_close(handle: *libc::c_void) unsafe {
        log(debug, #fmt("lifetime_handle_close ptr %?", handle));
    }

    crust fn lifetime_async_callback(handle: *libc::c_void,
                                     status: libc::c_int) {
        log(debug, #fmt("lifetime_handle_close ptr %? status %?",
                        handle, status));
    }

    #[test]
    fn test_uv_iotask_async() unsafe {
        let exit_po = comm::port::<()>();
        let exit_ch = comm::chan(exit_po);
        let iotask = spawn_test_loop(exit_ch);

        // using this handle to manage the lifetime of the high_level_loop,
        // as it will exit the first time one of the impl_uv_hl_async() is
        // cleaned up with no one ref'd handles on the loop (Which can happen
        // under race-condition type situations.. this ensures that the loop
        // lives until, at least, all of the impl_uv_hl_async() runs have been
        // called, at least.
        let work_exit_po = comm::port::<()>();
        let work_exit_ch = comm::chan(work_exit_po);
        iter::repeat(7u) {||
            task::spawn_sched(task::manual_threads(1u), {||
                impl_uv_iotask_async(iotask);
                comm::send(work_exit_ch, ());
            });
        };
        iter::repeat(7u) {||
            comm::recv(work_exit_po);
        };
        log(debug, "sending teardown_loop msg..");
        exit(iotask);
        comm::recv(exit_po);
        log(debug, "after recv on exit_po.. exiting..");
    }
}
<|endoftext|>


<commit_before>use super::buckets::Buckets;
use super::metric::{Metric, MetricKind};
use std::collections::HashMap;
use std::cmp::Ordering;
use time;

/// Creates derived values from metric data.
///
/// Creates:
///
/// - timer percentile data.
/// - internal processing metrics
pub fn process(buckets: &mut Buckets) {
    let start_time = time::get_time();

    let mut timer_data = HashMap::new();

    // Add the various derived values for timers.
    for (key, values) in buckets.timers().iter() {
        let mut v = values.clone();
        v.sort_by(|a, b| a.partial_cmp(b).unwrap());

        let len = v.len() as f64;
        let sum = v.iter().fold(0.0, |sum, x| sum + x);
        let mean = sum / len;

        // Get population standard deviation
        let sum_diff = v.iter().fold(0.0, |sum, x| sum + (x - mean).powi(2));
        let stddev = (sum_diff / len).sqrt();

        let median = percentile(&v, 0.5);
        let upper_95 = percentile(&v, 0.95);

        timer_data.insert(format!("{}.min", key), v[0]);
        timer_data.insert(format!("{}.max", key), v[v.len() - 1]);
        timer_data.insert(format!("{}.count", key), len);
        timer_data.insert(format!("{}.mean", key), mean);
        timer_data.insert(format!("{}.median", key), median);
        timer_data.insert(format!("{}.stddev", key), stddev);
        timer_data.insert(format!("{}.upper_95", key), upper_95);
    }
    buckets.set_timer_data(timer_data);

    let duration = time::get_time() - start_time;
    let process_duration = Metric::new(
        "statsd.processing_time",
        duration.num_milliseconds() as f64,
        MetricKind::Counter(1.0));
    buckets.add(&process_duration);
}

fn percentile(values :&Vec<f64>, tile: f64) -> f64 {
    let len = values.len() as f64;
    let index = (len * tile) as usize;
    if (values.len() % 2) == 0 {
        return (values[index - 1] + values[index]) / 2.0;
    } else {
        return values[index];
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use super::super::buckets::Buckets;
    use super::super::metric::{Metric, MetricKind};
    use std::option::Option;
    use time;

    fn make_buckets() -> Buckets {
        let mut buckets = Buckets::new();

        let metrics = [
            Metric::new("some.timer", 13.1, MetricKind::Timer),
            Metric::new("some.timer", 33.7, MetricKind::Timer),
            Metric::new("some.timer", 3.4, MetricKind::Timer),
            Metric::new("some.timer", 12.1, MetricKind::Timer),
        ];
        for m in metrics.iter() {
            buckets.add(&m);
        }
        buckets
    }

    fn assert_float(expected: &str, value: &f64) {
        assert_eq!(expected, format!("{:.*}", 3, value));
    }

    #[test]
    fn test_process_timer_data() {
        let mut buckets = make_buckets();
        process(&mut buckets);

        assert_eq!(Some(&3.4), buckets.timer_data().get("some.timer.min"));
        assert_eq!(Some(&33.7), buckets.timer_data().get("some.timer.max"));
        assert_eq!(Some(&4.0), buckets.timer_data().get("some.timer.count"));
        assert_float(
            "15.575",
            buckets.timer_data().get("some.timer.mean").unwrap());
        assert_float(
            "12.600",
            buckets.timer_data().get("some.timer.median").unwrap());
        assert_float(
            "11.124",
            buckets.timer_data().get("some.timer.stddev").unwrap());
        assert_float(
            "23.400",
            buckets.timer_data().get("some.timer.upper_95").unwrap());
    }

    #[test]
    fn test_set_internal_metrics() {
    }
}
<commit_msg>Add some comments.<commit_after>use super::buckets::Buckets;
use super::metric::{Metric, MetricKind};
use std::collections::HashMap;
use std::cmp::Ordering;
use time;

/// Creates derived values from metric data.
///
/// Creates:
///
/// - timer percentile data.
/// - internal processing metrics
pub fn process(buckets: &mut Buckets) {
    let start_time = time::get_time();

    let mut timer_data = HashMap::new();

    // Add the various derived values for timers.
    for (key, values) in buckets.timers().iter() {
        let mut v = values.clone();
        v.sort_by(|a, b| a.partial_cmp(b).unwrap());

        let len = v.len() as f64;
        let sum = v.iter().fold(0.0, |sum, x| sum + x);
        let mean = sum / len;

        // Get population standard deviation
        let sum_diff = v.iter().fold(0.0, |sum, x| sum + (x - mean).powi(2));
        let stddev = (sum_diff / len).sqrt();

        let median = percentile(&v, 0.5);
        let upper_95 = percentile(&v, 0.95);

        timer_data.insert(format!("{}.min", key), v[0]);
        timer_data.insert(format!("{}.max", key), v[v.len() - 1]);
        timer_data.insert(format!("{}.count", key), len);
        timer_data.insert(format!("{}.mean", key), mean);
        timer_data.insert(format!("{}.median", key), median);
        timer_data.insert(format!("{}.stddev", key), stddev);
        timer_data.insert(format!("{}.upper_95", key), upper_95);
    }
    buckets.set_timer_data(timer_data);

    let duration = time::get_time() - start_time;
    let process_duration = Metric::new(
        "statsd.processing_time",
        duration.num_milliseconds() as f64,
        MetricKind::Counter(1.0));
    buckets.add(&process_duration);
}

/// Extract the value at the given percentile.
/// If vector has an even length, two values will be
/// averaged together.
fn percentile(values :&Vec<f64>, tile: f64) -> f64 {
    let len = values.len() as f64;
    let index = (len * tile) as usize;
    if (values.len() % 2) == 0 {
        return (values[index - 1] + values[index]) / 2.0;
    } else {
        return values[index];
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use super::super::buckets::Buckets;
    use super::super::metric::{Metric, MetricKind};
    use std::option::Option;
    use time;

    fn make_buckets() -> Buckets {
        let mut buckets = Buckets::new();

        let metrics = [
            Metric::new("some.timer", 13.1, MetricKind::Timer),
            Metric::new("some.timer", 33.7, MetricKind::Timer),
            Metric::new("some.timer", 3.4, MetricKind::Timer),
            Metric::new("some.timer", 12.1, MetricKind::Timer),
        ];
        for m in metrics.iter() {
            buckets.add(&m);
        }
        buckets
    }

    fn assert_float(expected: &str, value: &f64) {
        assert_eq!(expected, format!("{:.*}", 3, value));
    }

    #[test]
    fn test_process_timer_data() {
        let mut buckets = make_buckets();
        process(&mut buckets);

        assert_eq!(Some(&3.4), buckets.timer_data().get("some.timer.min"));
        assert_eq!(Some(&33.7), buckets.timer_data().get("some.timer.max"));
        assert_eq!(Some(&4.0), buckets.timer_data().get("some.timer.count"));
        assert_float(
            "15.575",
            buckets.timer_data().get("some.timer.mean").unwrap());
        assert_float(
            "12.600",
            buckets.timer_data().get("some.timer.median").unwrap());
        assert_float(
            "11.124",
            buckets.timer_data().get("some.timer.stddev").unwrap());
        assert_float(
            "23.400",
            buckets.timer_data().get("some.timer.upper_95").unwrap());
    }

    #[test]
    fn test_set_internal_metrics() {
    }
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::ty;
use rustc::hir::*;
use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then};

#[allow(missing_copy_implementations)]
pub struct EtaPass;

/// **What it does:** Checks for closures which just call another function where
/// the function can be called directly. `unsafe` functions or calls where types
/// get adjusted are ignored.
///
/// **Why is this bad?** Needlessly creating a closure adds code for no benefit
/// and gives the optimizer more work.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// xs.map(|x| foo(x))
/// ```
/// where `foo(_)` is a plain function that takes the exact argument type of
/// `x`.
declare_clippy_lint! {
    pub REDUNDANT_CLOSURE,
    style,
    "redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`)"
}

impl LintPass for EtaPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(REDUNDANT_CLOSURE)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        match expr.node {
            ExprKind::Call(_, ref args) | ExprKind::MethodCall(_, _, ref args) => for arg in args {
                check_closure(cx, arg)
            },
            _ => (),
        }
    }
}

fn check_closure(cx: &LateContext, expr: &Expr) {
    if let ExprKind::Closure(_, ref decl, eid, _, _) = expr.node {
        let body = cx.tcx.hir.body(eid);
        let ex = &body.value;
        if let ExprKind::Call(ref caller, ref args) = ex.node {
            if args.len() != decl.inputs.len() {
                // Not the same number of arguments, there
                // is no way the closure is the same as the function
                return;
            }
            if is_adjusted(cx, ex) || args.iter().any(|arg| is_adjusted(cx, arg)) {
                // Are the expression or the arguments type-adjusted? Then we need the closure
                return;
            }
            let fn_ty = cx.tables.expr_ty(caller);
            match fn_ty.sty {
                // Is it an unsafe function? They don't implement the closure traits
                ty::TyFnDef(..) | ty::TyFnPtr(_) => {
                    let sig = fn_ty.fn_sig(cx.tcx);
                    if sig.skip_binder().unsafety == Unsafety::Unsafe || sig.skip_binder().output().sty == ty::TyNever {
                        return;
                    }
                },
                _ => (),
            }
            for (a1, a2) in iter_input_pats(decl, body).zip(args) {
                if let PatKind::Binding(_, _, ident, _) = a1.pat.node {
                    // XXXManishearth Should I be checking the binding mode here?
                    if let ExprKind::Path(QPath::Resolved(None, ref p)) = a2.node {
                        if p.segments.len() != 1 {
                            // If it's a proper path, it can't be a local variable
                            return;
                        }
                        if p.segments[0].ident.name != ident.name {
                            // The two idents should be the same
                            return;
                        }
                    } else {
                        return;
                    }
                } else {
                    return;
                }
            }
            span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| {
                if let Some(snippet) = snippet_opt(cx, caller.span) {
                    db.span_suggestion(expr.span, "remove closure as shown", snippet);
                }
            });
        }
    }
}
<commit_msg>Add known problem for redundant_closure lint<commit_after>use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use rustc::ty;
use rustc::hir::*;
use crate::utils::{is_adjusted, iter_input_pats, snippet_opt, span_lint_and_then};

#[allow(missing_copy_implementations)]
pub struct EtaPass;

/// **What it does:** Checks for closures which just call another function where
/// the function can be called directly. `unsafe` functions or calls where types
/// get adjusted are ignored.
///
/// **Why is this bad?** Needlessly creating a closure adds code for no benefit
/// and gives the optimizer more work.
///
/// **Known problems:** If creating the closure inside the closure has a side-
/// effect then moving the closure creation out will change when that side-
/// effect runs.
/// See https://github.com/rust-lang-nursery/rust-clippy/issues/1439 for more
/// details.
///
/// **Example:**
/// ```rust
/// xs.map(|x| foo(x))
/// ```
/// where `foo(_)` is a plain function that takes the exact argument type of
/// `x`.
declare_clippy_lint! {
    pub REDUNDANT_CLOSURE,
    style,
    "redundant closures, i.e. `|a| foo(a)` (which can be written as just `foo`)"
}

impl LintPass for EtaPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(REDUNDANT_CLOSURE)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EtaPass {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        match expr.node {
            ExprKind::Call(_, ref args) | ExprKind::MethodCall(_, _, ref args) => for arg in args {
                check_closure(cx, arg)
            },
            _ => (),
        }
    }
}

fn check_closure(cx: &LateContext, expr: &Expr) {
    if let ExprKind::Closure(_, ref decl, eid, _, _) = expr.node {
        let body = cx.tcx.hir.body(eid);
        let ex = &body.value;
        if let ExprKind::Call(ref caller, ref args) = ex.node {
            if args.len() != decl.inputs.len() {
                // Not the same number of arguments, there
                // is no way the closure is the same as the function
                return;
            }
            if is_adjusted(cx, ex) || args.iter().any(|arg| is_adjusted(cx, arg)) {
                // Are the expression or the arguments type-adjusted? Then we need the closure
                return;
            }
            let fn_ty = cx.tables.expr_ty(caller);
            match fn_ty.sty {
                // Is it an unsafe function? They don't implement the closure traits
                ty::TyFnDef(..) | ty::TyFnPtr(_) => {
                    let sig = fn_ty.fn_sig(cx.tcx);
                    if sig.skip_binder().unsafety == Unsafety::Unsafe || sig.skip_binder().output().sty == ty::TyNever {
                        return;
                    }
                },
                _ => (),
            }
            for (a1, a2) in iter_input_pats(decl, body).zip(args) {
                if let PatKind::Binding(_, _, ident, _) = a1.pat.node {
                    // XXXManishearth Should I be checking the binding mode here?
                    if let ExprKind::Path(QPath::Resolved(None, ref p)) = a2.node {
                        if p.segments.len() != 1 {
                            // If it's a proper path, it can't be a local variable
                            return;
                        }
                        if p.segments[0].ident.name != ident.name {
                            // The two idents should be the same
                            return;
                        }
                    } else {
                        return;
                    }
                } else {
                    return;
                }
            }
            span_lint_and_then(cx, REDUNDANT_CLOSURE, expr.span, "redundant closure found", |db| {
                if let Some(snippet) = snippet_opt(cx, caller.span) {
                    db.span_suggestion(expr.span, "remove closure as shown", snippet);
                }
            });
        }
    }
}
<|endoftext|>


<commit_before>use libc::{gid_t, uid_t};

/// Credentials of a process
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct UCred {
    /// UID (user ID) of the process
    pub uid: uid_t,
    /// GID (group ID) of the process
    pub gid: gid_t,
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::impl_linux::get_peer_cred;

#[cfg(any(target_os = "dragonfly", target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd"))]
pub use self::impl_macos::get_peer_cred;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod impl_linux {
    use libc::{c_void, getsockopt, socklen_t, SOL_SOCKET, SO_PEERCRED};
    use std::{io, mem};
    use UnixStream;
    use std::os::unix::io::AsRawFd;

    use libc::ucred;

    pub fn get_peer_cred(sock: &UnixStream) -> io::Result<super::UCred> {
        unsafe {
            let raw_fd = sock.as_raw_fd();

            let mut ucred = ucred {
                pid: 0,
                uid: 0,
                gid: 0,
            };

            let ucred_size = mem::size_of::<ucred>();

            // These paranoid checks should be optimized-out
            assert!(mem::size_of::<u32>() <= mem::size_of::<usize>());
            assert!(ucred_size <= u32::max_value() as usize);

            let mut ucred_size = ucred_size as socklen_t;

            let ret = getsockopt(
                raw_fd,
                SOL_SOCKET,
                SO_PEERCRED,
                &mut ucred as *mut ucred as *mut c_void,
                &mut ucred_size,
            );
            if ret == 0 && ucred_size as usize == mem::size_of::<ucred>() {
                Ok(super::UCred {
                    uid: ucred.uid,
                    gid: ucred.gid,
                })
            } else {
                Err(io::Error::last_os_error())
            }
        }
    }
}

#[cfg(any(target_os = "dragonfly", target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd"))]
pub mod impl_macos {
    use libc::getpeereid;
    use std::{io, mem};
    use UnixStream;
    use std::os::unix::io::AsRawFd;

    pub fn get_peer_cred(sock: &UnixStream) -> io::Result<super::UCred> {
        unsafe {
            let raw_fd = sock.as_raw_fd();

            let mut cred: super::UCred = mem::uninitialized();

            let ret = getpeereid(raw_fd, &mut cred.uid, &mut cred.gid);

            if ret == 0 {
                Ok(cred)
            } else {
                Err(io::Error::last_os_error())
            }
        }
    }
}

// Note that SO_PEERCRED is not supported on DragonFly (yet). So do not run tests.
#[cfg(not(target_os = "dragonfly"))]
#[cfg(test)]
mod test {
    use UnixStream;
    use libc::geteuid;
    use libc::getegid;

    #[test]
    fn test_socket_pair() {
        let (a, b) = UnixStream::pair().unwrap();
        let cred_a = a.peer_cred().unwrap();
        let cred_b = b.peer_cred().unwrap();
        assert_eq!(cred_a, cred_b);

        let uid = unsafe { geteuid() };
        let gid = unsafe { getegid() };

        assert_eq!(cred_a.uid, uid);
        assert_eq!(cred_a.gid, gid);
    }
}
<commit_msg>Ignore tokio-uds's test_socket_pair on FreeBSD. (#493)<commit_after>use libc::{gid_t, uid_t};

/// Credentials of a process
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct UCred {
    /// UID (user ID) of the process
    pub uid: uid_t,
    /// GID (group ID) of the process
    pub gid: gid_t,
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::impl_linux::get_peer_cred;

#[cfg(any(target_os = "dragonfly", target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd"))]
pub use self::impl_macos::get_peer_cred;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod impl_linux {
    use libc::{c_void, getsockopt, socklen_t, SOL_SOCKET, SO_PEERCRED};
    use std::{io, mem};
    use UnixStream;
    use std::os::unix::io::AsRawFd;

    use libc::ucred;

    pub fn get_peer_cred(sock: &UnixStream) -> io::Result<super::UCred> {
        unsafe {
            let raw_fd = sock.as_raw_fd();

            let mut ucred = ucred {
                pid: 0,
                uid: 0,
                gid: 0,
            };

            let ucred_size = mem::size_of::<ucred>();

            // These paranoid checks should be optimized-out
            assert!(mem::size_of::<u32>() <= mem::size_of::<usize>());
            assert!(ucred_size <= u32::max_value() as usize);

            let mut ucred_size = ucred_size as socklen_t;

            let ret = getsockopt(
                raw_fd,
                SOL_SOCKET,
                SO_PEERCRED,
                &mut ucred as *mut ucred as *mut c_void,
                &mut ucred_size,
            );
            if ret == 0 && ucred_size as usize == mem::size_of::<ucred>() {
                Ok(super::UCred {
                    uid: ucred.uid,
                    gid: ucred.gid,
                })
            } else {
                Err(io::Error::last_os_error())
            }
        }
    }
}

#[cfg(any(target_os = "dragonfly", target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd"))]
pub mod impl_macos {
    use libc::getpeereid;
    use std::{io, mem};
    use UnixStream;
    use std::os::unix::io::AsRawFd;

    pub fn get_peer_cred(sock: &UnixStream) -> io::Result<super::UCred> {
        unsafe {
            let raw_fd = sock.as_raw_fd();

            let mut cred: super::UCred = mem::uninitialized();

            let ret = getpeereid(raw_fd, &mut cred.uid, &mut cred.gid);

            if ret == 0 {
                Ok(cred)
            } else {
                Err(io::Error::last_os_error())
            }
        }
    }
}

// Note that LOCAL_PEERCRED is not supported on DragonFly (yet). So do not run tests.
#[cfg(not(target_os = "dragonfly"))]
#[cfg(test)]
mod test {
    use UnixStream;
    use libc::geteuid;
    use libc::getegid;

    #[test]
    #[cfg_attr(target_os = "freebsd", ignore = "Requires FreeBSD 12.0 or later. https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=176419")]
    fn test_socket_pair() {
        let (a, b) = UnixStream::pair().unwrap();
        let cred_a = a.peer_cred().unwrap();
        let cred_b = b.peer_cred().unwrap();
        assert_eq!(cred_a, cred_b);

        let uid = unsafe { geteuid() };
        let gid = unsafe { getegid() };

        assert_eq!(cred_a.uid, uid);
        assert_eq!(cred_a.gid, gid);
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;

use rosxmlrpc;
use std;
use self::rustc_serialize::{Decodable, Decoder, Encodable};

pub struct Master {
    client: rosxmlrpc::Client,
    client_id: String,
    caller_api: String,
}

impl Master {
    pub fn new(client_id: &str, caller_api: &str) -> Master {
        let master_uri = std::env::var("ROS_MASTER_URI")
            .unwrap_or("http://localhost:11311/".to_owned());
        Master {
            client: rosxmlrpc::Client::new(&master_uri),
            client_id: client_id.to_owned(),
            caller_api: caller_api.to_owned(),
        }
    }

    fn remove_wrap<T>(data: MasterResult<ResponseData<T>>) -> MasterResult<T> {
        data.map(|d| d.0)
    }

    fn request<T: Decodable>(&self, function_name: &str, parameters: &[&str]) -> MasterResult<T> {
        Master::remove_wrap(self.client
            .request(function_name, parameters))
    }

    fn request_long<T: Decodable, Targ: Encodable>(&self,
                                                   function_name: &str,
                                                   parameters: &[&str],
                                                   extra_parameter: Targ)
                                                   -> MasterResult<T> {
        Master::remove_wrap(self.client
            .request_long(function_name, parameters, Some(&extra_parameter)))
    }

    pub fn register_service(&self, service: &str, service_api: &str) -> MasterResult<i32> {
        self.request("registerService",
                     &[self.client_id.as_str(), service, service_api, self.caller_api.as_str()])
    }

    pub fn unregister_service(&self, service: &str, service_api: &str) -> MasterResult<i32> {
        self.request("unregisterService",
                     &[self.client_id.as_str(), service, service_api])
    }

    pub fn register_subscriber(&self, topic: &str, topic_type: &str) -> MasterResult<Vec<String>> {
        self.request("registerSubscriber",
                     &[self.client_id.as_str(), topic, topic_type, self.caller_api.as_str()])
    }

    pub fn unregister_subscriber(&self, topic: &str) -> MasterResult<i32> {
        self.request("unregisterSubscriber",
                     &[self.client_id.as_str(), topic, self.caller_api.as_str()])
    }

    pub fn register_publisher(&self, topic: &str, topic_type: &str) -> MasterResult<Vec<String>> {
        self.request("registerPublisher",
                     &[self.client_id.as_str(), topic, topic_type, self.caller_api.as_str()])
    }

    pub fn unregister_publisher(&self, topic: &str) -> MasterResult<i32> {
        self.request("unregisterPublisher",
                     &[self.client_id.as_str(), topic, self.caller_api.as_str()])
    }

    pub fn lookup_node(&self, node_name: &str) -> MasterResult<String> {
        self.request("lookupNode", &[self.client_id.as_str(), node_name])
    }

    pub fn get_published_topics(&self, subgraph: &str) -> MasterResult<Vec<(String, String)>> {
        self.request("getPublishedTopics", &[self.client_id.as_str(), subgraph])
    }

    pub fn get_topic_types(&self) -> MasterResult<Vec<(String, String)>> {
        self.request("getTopicTypes", &[self.client_id.as_str()])
    }

    pub fn get_system_state(&self) -> MasterResult<Vec<Vec<(String, Vec<String>)>>> {
        self.request("getSystemState", &[self.client_id.as_str()])
    }

    pub fn get_uri(&self) -> MasterResult<String> {
        self.request("getUri", &[self.client_id.as_str()])
    }

    pub fn lookup_service(&self, service: &str) -> MasterResult<String> {
        self.request("lookupService", &[self.client_id.as_str(), service])
    }

    pub fn delete_param(&self, key: &str) -> MasterResult<i32> {
        self.request("deleteParam", &[self.client_id.as_str(), key])
    }

    pub fn set_param<T: Encodable>(&self, key: &str, value: &T) -> MasterResult<i32> {
        self.request_long("setParam", &[self.client_id.as_str(), key], value)
    }

    pub fn get_param<T: Decodable>(&self, key: &str) -> MasterResult<T> {
        self.request("getParam", &[self.client_id.as_str(), key])
    }

    pub fn search_param(&self, key: &str) -> MasterResult<String> {
        self.request("searchParam", &[self.client_id.as_str(), key])
    }

    pub fn subscribe_param<T: Decodable>(&self, caller_api: &str, key: &str) -> MasterResult<T> {
        self.request("subscribeParam",
                     &[self.client_id.as_str(), caller_api, key])
    }

    pub fn unsubscribe_param(&self, caller_api: &str, key: &str) -> MasterResult<i32> {
        self.request("unsubscribeParam",
                     &[self.client_id.as_str(), caller_api, key])
    }

    pub fn has_param(&self, key: &str) -> MasterResult<bool> {
        self.request("hasParam", &[self.client_id.as_str(), key])
    }

    pub fn get_param_names(&self) -> MasterResult<Vec<String>> {
        self.request("getParamNames", &[self.client_id.as_str()])
    }
}

pub type Error = rosxmlrpc::client::Error;

pub type MasterResult<T> = Result<T, Error>;

#[derive(Debug)]
pub struct ResponseData<T>(T);

impl<T: Decodable> Decodable for ResponseData<T> {
    fn decode<D: Decoder>(d: &mut D) -> Result<ResponseData<T>, D::Error> {
        d.read_struct("ResponseData", 3, |d| {
            let code = try!(d.read_struct_field("status_code", 0, |d| d.read_i32()));
            let message = try!(d.read_struct_field("status_message", 1, |d| d.read_str()));
            match code {
                0 | -1 => Err(d.error(&message)),
                1 => Ok(ResponseData(try!(d.read_struct_field("data", 2, |d| T::decode(d))))),
                _ => Err(d.error("Invalid response code returned by ROS")),
            }
        })
    }
}
<commit_msg>Remove duplicate need for Caller API<commit_after>extern crate rustc_serialize;

use rosxmlrpc;
use std;
use self::rustc_serialize::{Decodable, Decoder, Encodable};

pub struct Master {
    client: rosxmlrpc::Client,
    client_id: String,
    caller_api: String,
}

impl Master {
    pub fn new(client_id: &str, caller_api: &str) -> Master {
        let master_uri = std::env::var("ROS_MASTER_URI")
            .unwrap_or("http://localhost:11311/".to_owned());
        Master {
            client: rosxmlrpc::Client::new(&master_uri),
            client_id: client_id.to_owned(),
            caller_api: caller_api.to_owned(),
        }
    }

    fn remove_wrap<T>(data: MasterResult<ResponseData<T>>) -> MasterResult<T> {
        data.map(|d| d.0)
    }

    fn request<T: Decodable>(&self, function_name: &str, parameters: &[&str]) -> MasterResult<T> {
        Master::remove_wrap(self.client
            .request(function_name, parameters))
    }

    fn request_long<T: Decodable, Targ: Encodable>(&self,
                                                   function_name: &str,
                                                   parameters: &[&str],
                                                   extra_parameter: Targ)
                                                   -> MasterResult<T> {
        Master::remove_wrap(self.client
            .request_long(function_name, parameters, Some(&extra_parameter)))
    }

    pub fn register_service(&self, service: &str, service_api: &str) -> MasterResult<i32> {
        self.request("registerService",
                     &[self.client_id.as_str(), service, service_api, self.caller_api.as_str()])
    }

    pub fn unregister_service(&self, service: &str, service_api: &str) -> MasterResult<i32> {
        self.request("unregisterService",
                     &[self.client_id.as_str(), service, service_api])
    }

    pub fn register_subscriber(&self, topic: &str, topic_type: &str) -> MasterResult<Vec<String>> {
        self.request("registerSubscriber",
                     &[self.client_id.as_str(), topic, topic_type, self.caller_api.as_str()])
    }

    pub fn unregister_subscriber(&self, topic: &str) -> MasterResult<i32> {
        self.request("unregisterSubscriber",
                     &[self.client_id.as_str(), topic, self.caller_api.as_str()])
    }

    pub fn register_publisher(&self, topic: &str, topic_type: &str) -> MasterResult<Vec<String>> {
        self.request("registerPublisher",
                     &[self.client_id.as_str(), topic, topic_type, self.caller_api.as_str()])
    }

    pub fn unregister_publisher(&self, topic: &str) -> MasterResult<i32> {
        self.request("unregisterPublisher",
                     &[self.client_id.as_str(), topic, self.caller_api.as_str()])
    }

    pub fn lookup_node(&self, node_name: &str) -> MasterResult<String> {
        self.request("lookupNode", &[self.client_id.as_str(), node_name])
    }

    pub fn get_published_topics(&self, subgraph: &str) -> MasterResult<Vec<(String, String)>> {
        self.request("getPublishedTopics", &[self.client_id.as_str(), subgraph])
    }

    pub fn get_topic_types(&self) -> MasterResult<Vec<(String, String)>> {
        self.request("getTopicTypes", &[self.client_id.as_str()])
    }

    pub fn get_system_state(&self) -> MasterResult<Vec<Vec<(String, Vec<String>)>>> {
        self.request("getSystemState", &[self.client_id.as_str()])
    }

    pub fn get_uri(&self) -> MasterResult<String> {
        self.request("getUri", &[self.client_id.as_str()])
    }

    pub fn lookup_service(&self, service: &str) -> MasterResult<String> {
        self.request("lookupService", &[self.client_id.as_str(), service])
    }

    pub fn delete_param(&self, key: &str) -> MasterResult<i32> {
        self.request("deleteParam", &[self.client_id.as_str(), key])
    }

    pub fn set_param<T: Encodable>(&self, key: &str, value: &T) -> MasterResult<i32> {
        self.request_long("setParam", &[self.client_id.as_str(), key], value)
    }

    pub fn get_param<T: Decodable>(&self, key: &str) -> MasterResult<T> {
        self.request("getParam", &[self.client_id.as_str(), key])
    }

    pub fn search_param(&self, key: &str) -> MasterResult<String> {
        self.request("searchParam", &[self.client_id.as_str(), key])
    }

    pub fn subscribe_param<T: Decodable>(&self, key: &str) -> MasterResult<T> {
        self.request("subscribeParam",
                     &[self.client_id.as_str(), self.caller_api.as_str(), key])
    }

    pub fn unsubscribe_param(&self, key: &str) -> MasterResult<i32> {
        self.request("unsubscribeParam",
                     &[self.client_id.as_str(), self.caller_api.as_str(), key])
    }

    pub fn has_param(&self, key: &str) -> MasterResult<bool> {
        self.request("hasParam", &[self.client_id.as_str(), key])
    }

    pub fn get_param_names(&self) -> MasterResult<Vec<String>> {
        self.request("getParamNames", &[self.client_id.as_str()])
    }
}

pub type Error = rosxmlrpc::client::Error;

pub type MasterResult<T> = Result<T, Error>;

#[derive(Debug)]
pub struct ResponseData<T>(T);

impl<T: Decodable> Decodable for ResponseData<T> {
    fn decode<D: Decoder>(d: &mut D) -> Result<ResponseData<T>, D::Error> {
        d.read_struct("ResponseData", 3, |d| {
            let code = try!(d.read_struct_field("status_code", 0, |d| d.read_i32()));
            let message = try!(d.read_struct_field("status_message", 1, |d| d.read_str()));
            match code {
                0 | -1 => Err(d.error(&message)),
                1 => Ok(ResponseData(try!(d.read_struct_field("data", 2, |d| T::decode(d))))),
                _ => Err(d.error("Invalid response code returned by ROS")),
            }
        })
    }
}
<|endoftext|>


<commit_before>//! A LinkedList that lets you insert elements from the front or the end of the list.
//! TODO: Add the ability to insert in-between a Node.
//! Lots of thanks to reem and Sharp for help with this from the #rust channel

use std::mem;

/// A Node is the basic unit in a LinkedList which stores the payload of type T.
#[derive(Debug,PartialEq)]
struct Node<T> {
    /// The payload of type T that is wrapped aorund a Node.
    pub payload: T,
    /// An Option of a boxed Node<T> that would point to the next Node<T>.
    next: Option<Box<Node<T>>>,
    /// An Option of a boxed Node<T> that would point to the previous Node<T>.
    prev: Option<Box<Node<T>>>,
}

impl<T> Node<T> {

    pub fn new(payload: T) -> Node<T> {
        //! Creates a instance of a `Node` with `next` and `prev` point to a Option::Node.
        Node::<T> {
            payload: payload,
            next: None,
            prev: None,
        }
    }

    pub fn payload(&self) -> Option<&T> {
        //! Access to a payload of Node.
        Some(&self.payload)
    }

    pub fn insert_after(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        //! Takes a new boxed Node<T> and swaps it with any existing Node after the current one.
        //! We replace any Option::None or Option::Some with a new Option<Box<Node<T>>>
        mem::swap(&mut new.next, &mut self.next);
        mem::replace(&mut self.next, Some(new))
    }

    pub fn insert_before(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        //! Takes a new boxed Node<T> and swaps it with any existing Node after the current one.
        //! We replace any Option::None or Option::Some with a new Option<Box<Node<T>>>
        mem::swap(&mut new.prev, &mut self.prev);
        mem::replace(&mut self.prev, Some(new))
    }

    pub fn remove_after(&mut self) -> Option<Box<Node<T>>> {
        //! Removes the Node after the current node.
        match self.next.take() {
            Some(mut next)  => {
                mem::swap(&mut self.next, &mut next.next);
                Some(next)
            },
            None => None,
        }
    }

    pub fn remove_before(&mut self) -> Option<Box<Node<T>>> {
        //! Removes the Node before the current node.
        match self.prev.take() {
            Some(mut prev)  => {
                mem::swap(&mut self.prev, &mut prev.prev);
                Some(prev)
            },
            None => None,
        }
    }

    pub fn next(&mut self) -> Option<&mut T> {
        //! Goes to the next Node and returns an Option to it.
        let Node {
            ref mut payload,
            ref mut prev,
            ref mut next,
        } = *self;

        match *next {
            Some(ref mut next) => {
                mem::swap(&mut next.payload, payload);

                let mut next = &mut **next;     // Cannot completely understand this bit yet.
                mem::swap(&mut next.next, &mut next.prev);

                mem::swap(&mut next.prev, prev);
            },
            None => return None,
        }
        mem::swap(prev, next);
        Some(payload)
    }

    pub fn prev(&mut self) -> Option<&mut T> {
        let Node {
            ref mut payload,
            ref mut prev,
            ref mut next,
        } = *self;

        match *prev {
            Some(ref mut prev) => {
                mem::swap(&mut prev.payload, payload);

                let mut prev = &mut **prev;     // Still don't understand this bit.
                mem::swap(&mut prev.prev, &mut prev.next);

                mem::swap(&mut prev.next, next);
            },
            None => return None,
        }
        mem::swap(prev, next);
        Some(payload)
    }
}

/// A LinkedList is the struct that you would need to use to create a list of elements.
/// It contains a pointer to the first and last node in the list represented as `head and `tail`
/// respectively.
pub struct LinkedList<T> {
    /// First element in the list.
    head: Option<Box<Node<T>>>,
    /// Last element in the list.
    tail: Option<Box<Node<T>>>,
}

impl<T> LinkedList<T> {
    pub fn new() -> LinkedList<T> {
        //! Create a new LinkedList to contain a payloads with type T.
        LinkedList::<T> {
            head: None,
            tail: None,
        }
    }

    pub fn push_back(&mut self, mut new: T) {
        let new_node = Box::new(Node::new(new));
        match self.tail {
            Some(ref mut tail_node) => {
                tail_node.insert_after(new_node);
            },
            None => {
                mem::swap(&mut self.tail, &mut Some(new_node));
            },
        }
    }
}

#[test]
fn node_new() {
    let expected = Node {
        payload: "test",
        next: None,
        prev: None,
    };

    let node: Node<&str> = Node::new("test");

    assert_eq!(expected.payload,  node.payload);
    assert_eq!(expected.next,     node.next);
    assert_eq!(expected.prev,     node.prev);
}

#[test]
fn node_payload() {
    let node: Node<&str> = Node::new("test");
    assert_eq!(&"test", node.payload().unwrap());
}

#[test]
fn node_insert_after() {
    let mut node: Node<&str> = Node::new("one");
    node.insert_after(Box::new(Node::new("two")));
    assert_eq!("two", node.next.unwrap().payload);
}

#[test]
fn node_insert_before() {
    let mut node: Node<&str> = Node::new("two");
    node.insert_before(Box::new(Node::new("one")));
    assert_eq!("one", node.prev.unwrap().payload);
}

#[test]
fn node_remove_next() {
    let mut node: Node<&str> = Node::new("one");
    node.insert_after(Box::new(Node::new("two")));
    node.remove_after();
}

#[test]
fn node_remove_prev() {
    let mut node: Node<&str> = Node::new("one");
    node.insert_before(Box::new(Node::new("two")));
    node.remove_before();
}

#[test]
fn node_next() {
    let mut node: Node<&str> = Node::new("one");
    node.insert_after(Box::new(Node::new("two")));
    assert_eq!("two", *node.next().unwrap());
}

#[test]
fn node_prev() {
    let mut node: Node<&str> = Node::new("two");
    node.insert_before(Box::new(Node::new("one")));
    assert_eq!("one", *node.prev().unwrap());
}

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

    #[test]
    fn test_push_back_linked_list() {
        let mut list: LinkedList<String> = LinkedList::new();
        list.push_back("one".to_string());
        assert_eq!("one".to_string(), list.tail.unwrap().payload);
    }

}
<commit_msg>(Breaks) Added a new test to push_back<commit_after>//! A LinkedList that lets you insert elements from the front or the end of the list.
//! TODO: Add the ability to insert in-between a Node.
//! Lots of thanks to reem and Sharp for help with this from the #rust channel

use std::mem;

/// A Node is the basic unit in a LinkedList which stores the payload of type T.
#[derive(Debug,PartialEq)]
struct Node<T> {
    /// The payload of type T that is wrapped aorund a Node.
    pub payload: T,
    /// An Option of a boxed Node<T> that would point to the next Node<T>.
    next: Option<Box<Node<T>>>,
    /// An Option of a boxed Node<T> that would point to the previous Node<T>.
    prev: Option<Box<Node<T>>>,
}

impl<T> Node<T> {

    pub fn new(payload: T) -> Node<T> {
        //! Creates a instance of a `Node` with `next` and `prev` point to a Option::Node.
        Node::<T> {
            payload: payload,
            next: None,
            prev: None,
        }
    }

    pub fn payload(&self) -> Option<&T> {
        //! Access to a payload of Node.
        Some(&self.payload)
    }

    pub fn insert_after(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        //! Takes a new boxed Node<T> and swaps it with any existing Node after the current one.
        //! We replace any Option::None or Option::Some with a new Option<Box<Node<T>>>
        mem::swap(&mut new.next, &mut self.next);
        mem::replace(&mut self.next, Some(new))
    }

    pub fn insert_before(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        //! Takes a new boxed Node<T> and swaps it with any existing Node after the current one.
        //! We replace any Option::None or Option::Some with a new Option<Box<Node<T>>>
        mem::swap(&mut new.prev, &mut self.prev);
        mem::replace(&mut self.prev, Some(new))
    }

    pub fn remove_after(&mut self) -> Option<Box<Node<T>>> {
        //! Removes the Node after the current node.
        match self.next.take() {
            Some(mut next)  => {
                mem::swap(&mut self.next, &mut next.next);
                Some(next)
            },
            None => None,
        }
    }

    pub fn remove_before(&mut self) -> Option<Box<Node<T>>> {
        //! Removes the Node before the current node.
        match self.prev.take() {
            Some(mut prev)  => {
                mem::swap(&mut self.prev, &mut prev.prev);
                Some(prev)
            },
            None => None,
        }
    }

    pub fn next(&mut self) -> Option<&mut T> {
        //! Goes to the next Node and returns an Option to it.
        let Node {
            ref mut payload,
            ref mut prev,
            ref mut next,
        } = *self;

        match *next {
            Some(ref mut next) => {
                mem::swap(&mut next.payload, payload);

                let mut next = &mut **next;     // Cannot completely understand this bit yet.
                mem::swap(&mut next.next, &mut next.prev);

                mem::swap(&mut next.prev, prev);
            },
            None => return None,
        }
        mem::swap(prev, next);
        Some(payload)
    }

    pub fn prev(&mut self) -> Option<&mut T> {
        let Node {
            ref mut payload,
            ref mut prev,
            ref mut next,
        } = *self;

        match *prev {
            Some(ref mut prev) => {
                mem::swap(&mut prev.payload, payload);

                let mut prev = &mut **prev;     // Still don't understand this bit.
                mem::swap(&mut prev.prev, &mut prev.next);

                mem::swap(&mut prev.next, next);
            },
            None => return None,
        }
        mem::swap(prev, next);
        Some(payload)
    }
}

/// A LinkedList is the struct that you would need to use to create a list of elements.
/// It contains a pointer to the first and last node in the list represented as `head and `tail`
/// respectively.
pub struct LinkedList<T> {
    /// First element in the list.
    head: Option<Box<Node<T>>>,
    /// Last element in the list.
    tail: Option<Box<Node<T>>>,
    /// Number of nodes in the list.
    size: usize,
}

impl<T> LinkedList<T> {
    pub fn new() -> LinkedList<T> {
        //! Create a new LinkedList to contain a payloads with type T.
        LinkedList::<T> {
            head: None,
            tail: None,
            size: 0,
        }
    }

    pub fn push_back(&mut self, mut new: T) {
        let new_node = Box::new(Node::new(new));
        //if self.size == 0 {
            // Then `head` and `tail` need to point to the same node.
            // But can I do that in rust? Have one point as mutable and the other as immutable?!
        //} else {
            match self.tail {
                Some(ref mut tail_node) => {
                    tail_node.insert_before(new_node);
                },
                None => {
                    mem::swap(&mut self.tail, &mut Some(new_node));
                },
            }
        //}
        self.size += 1;
    }
}

#[test]
fn node_new() {
    let expected = Node {
        payload: "test",
        next: None,
        prev: None,
    };

    let node: Node<&str> = Node::new("test");

    assert_eq!(expected.payload,  node.payload);
    assert_eq!(expected.next,     node.next);
    assert_eq!(expected.prev,     node.prev);
}

#[test]
fn node_payload() {
    let node: Node<&str> = Node::new("test");
    assert_eq!(&"test", node.payload().unwrap());
}

#[test]
fn node_insert_after() {
    let mut node: Node<&str> = Node::new("one");
    node.insert_after(Box::new(Node::new("two")));
    assert_eq!("two", node.next.unwrap().payload);
}

#[test]
fn node_insert_before() {
    let mut node: Node<&str> = Node::new("two");
    node.insert_before(Box::new(Node::new("one")));
    assert_eq!("one", node.prev.unwrap().payload);
}

#[test]
fn node_remove_next() {
    let mut node: Node<&str> = Node::new("one");
    node.insert_after(Box::new(Node::new("two")));
    node.remove_after();
}

#[test]
fn node_remove_prev() {
    let mut node: Node<&str> = Node::new("one");
    node.insert_before(Box::new(Node::new("two")));
    node.remove_before();
}

#[test]
fn node_next() {
    let mut node: Node<&str> = Node::new("one");
    node.insert_after(Box::new(Node::new("two")));
    assert_eq!("two", *node.next().unwrap());
}

#[test]
fn node_prev() {
    let mut node: Node<&str> = Node::new("two");
    node.insert_before(Box::new(Node::new("one")));
    assert_eq!("one", *node.prev().unwrap());
}

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

    //#[test]
    fn test_push_back() {
        let mut list: LinkedList<String> = LinkedList::new();
        list.push_back("one".to_string());
        assert_eq!("one".to_string(), list.tail.unwrap().payload);
    }

    #[test]
    fn test_push_back_two() {
        let mut list: LinkedList<String> = LinkedList::new();
        list.push_back("one".to_string());
        list.push_back("two".to_string());
        //assert_eq!("one".to_string(), list.tail.unwrap().payload);
        assert_eq!("one".to_string(), list.tail.unwrap().prev.unwrap().payload);
    }

}
<|endoftext|>


<commit_before>/*
Copyright (c) 2017 The swc Project Developers

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

use crate::{
    complete_output, get_compiler,
    util::{deserialize_json, CtxtExt, MapErr},
};
use anyhow::{anyhow, bail, Context as _, Error};
use fxhash::FxHashSet;
use napi::{CallContext, Env, JsBoolean, JsBuffer, JsObject, JsString, JsUnknown, Status, Task};
use next_swc::{custom_before_pass, TransformOptions};
use std::fs::read_to_string;
use std::{
    cell::RefCell,
    convert::TryFrom,
    panic::{catch_unwind, AssertUnwindSafe},
    rc::Rc,
    sync::Arc,
};
use swc::{try_with_handler, Compiler, TransformOutput};
use swc_common::{errors::ColorConfig, FileName, SourceFile};
use swc_ecmascript::ast::Program;
use swc_ecmascript::transforms::pass::noop;

/// Input to transform
#[derive(Debug)]
pub enum Input {
    /// Raw source code.
    Source { src: String },
    /// Get source code from filename in options
    FromFilename,
}

pub struct TransformTask {
    pub c: Arc<Compiler>,
    pub input: Input,
    pub options: String,
}

impl Task for TransformTask {
    type Output = (TransformOutput, FxHashSet<String>);
    type JsValue = JsObject;

    fn compute(&mut self) -> napi::Result<Self::Output> {
        let eliminated_packages: Rc<RefCell<fxhash::FxHashSet<String>>> = Default::default();
        let res = catch_unwind(AssertUnwindSafe(|| {
            try_with_handler(
                self.c.cm.clone(),
                swc::HandlerOpts {
                    color: ColorConfig::Never,
                    skip_filename: true,
                },
                |handler| {
                    self.c.run(|| {
                        let options: TransformOptions = deserialize_json(&self.options)?;
                        let fm = match &self.input {
                            Input::Source { src } => {
                                let filename = if options.swc.filename.is_empty() {
                                    FileName::Anon
                                } else {
                                    FileName::Real(options.swc.filename.clone().into())
                                };

                                self.c.cm.new_source_file(filename, src.to_string())
                            }
                            Input::FromFilename => {
                                let filename = &options.swc.filename;
                                if filename.is_empty() {
                                    bail!("no filename is provided via options");
                                }

                                self.c.cm.new_source_file(
                                    FileName::Real(filename.into()),
                                    read_to_string(filename).with_context(|| {
                                        format!("Failed to read source code from {}", filename)
                                    })?,
                                )
                            }
                        };
                        let options = options.patch(&fm);

                        let cm = self.c.cm.clone();
                        let file = fm.clone();

                        self.c.process_js_with_custom_pass(
                            fm,
                            None,
                            handler,
                            &options.swc,
                            |_, comments| {
                                custom_before_pass(
                                    cm,
                                    file,
                                    &options,
                                    comments.clone(),
                                    eliminated_packages.clone(),
                                )
                            },
                            |_, _| noop(),
                        )
                    })
                },
            )
        }))
        .map_err(|err| {
            if let Some(s) = err.downcast_ref::<String>() {
                anyhow!("failed to process {}", s)
            } else {
                anyhow!("failed to process")
            }
        });

        match res {
            Ok(res) => res
                .map(|o| (o, eliminated_packages.replace(Default::default())))
                .convert_err(),
            Err(err) => Err(napi::Error::new(
                Status::GenericFailure,
                format!("{:?}", err),
            )),
        }
    }

    fn resolve(
        self,
        env: Env,
        (output, eliminated_packages): Self::Output,
    ) -> napi::Result<Self::JsValue> {
        complete_output(&env, output, eliminated_packages)
    }
}

/// returns `compiler, (src / path), options, plugin, callback`
pub fn schedule_transform<F>(cx: CallContext, op: F) -> napi::Result<JsObject>
where
    F: FnOnce(&Arc<Compiler>, Input, bool, String) -> TransformTask,
{
    let c = get_compiler(&cx);

    let unknown_src = cx.get::<JsUnknown>(0)?;
    let src = match unknown_src.get_type()? {
        napi::ValueType::String => napi::Result::Ok(Input::Source {
            src: JsString::try_from(unknown_src)?
                .into_utf8()?
                .as_str()?
                .to_owned(),
        }),
        napi::ValueType::Object => napi::Result::Ok(Input::Source {
            src: String::from_utf8_lossy(JsBuffer::try_from(unknown_src)?.into_value()?.as_ref())
                .to_string(),
        }),
        napi::ValueType::Undefined => napi::Result::Ok(Input::FromFilename),
        _ => Err(napi::Error::new(
            Status::GenericFailure,
            "first argument must be a String or Buffer".to_string(),
        )),
    }?;
    let is_module = cx.get::<JsBoolean>(1)?;
    let options = cx.get_buffer_as_string(2)?;

    let task = op(&c, src, is_module.get_value()?, options);

    cx.env.spawn(task).map(|t| t.promise_object())
}

pub fn exec_transform<F>(cx: CallContext, op: F) -> napi::Result<JsObject>
where
    F: FnOnce(&Compiler, String, &TransformOptions) -> Result<Arc<SourceFile>, Error>,
{
    let c = get_compiler(&cx);

    let s = cx.get::<JsString>(0)?.into_utf8()?;
    let is_module = cx.get::<JsBoolean>(1)?;
    let mut options: TransformOptions = cx.get_deserialized(2)?;
    options.swc.swcrc = false;

    let output = try_with_handler(
        c.cm.clone(),
        swc::HandlerOpts {
            color: ColorConfig::Never,
            skip_filename: true,
        },
        |handler| {
            c.run(|| {
                if is_module.get_value()? {
                    let program: Program = serde_json::from_str(s.as_str()?)
                        .context("failed to deserialize Program")?;
                    c.process_js(handler, program, &options.swc)
                } else {
                    let fm =
                        op(&c, s.as_str()?.to_string(), &options).context("failed to load file")?;
                    c.process_js_file(fm, handler, &options.swc)
                }
            })
        },
    )
    .convert_err()?;

    complete_output(cx.env, output, Default::default())
}

#[js_function(4)]
pub fn transform(cx: CallContext) -> napi::Result<JsObject> {
    schedule_transform(cx, |c, input, _, options| TransformTask {
        c: c.clone(),
        input,
        options,
    })
}

#[js_function(4)]
pub fn transform_sync(cx: CallContext) -> napi::Result<JsObject> {
    exec_transform(cx, |c, src, options| {
        Ok(c.cm.new_source_file(
            if options.swc.filename.is_empty() {
                FileName::Anon
            } else {
                FileName::Real(options.swc.filename.clone().into())
            },
            src,
        ))
    })
}

#[test]
fn test_deser() {
    const JSON_STR: &str = r#"{"jsc":{"parser":{"syntax":"ecmascript","dynamicImport":true,"jsx":true},"transform":{"react":{"runtime":"automatic","pragma":"React.createElement","pragmaFrag":"React.Fragment","throwIfNamespace":true,"development":false,"useBuiltins":true}},"target":"es5"},"filename":"/Users/timneutkens/projects/next.js/packages/next/dist/client/next.js","sourceMaps":false,"sourceFileName":"/Users/timneutkens/projects/next.js/packages/next/dist/client/next.js"}"#;

    let tr: TransformOptions = serde_json::from_str(JSON_STR).unwrap();

    println!("{:#?}", tr);
}

#[test]
fn test_deserialize_transform_regenerator() {
    const JSON_STR: &str = r#"{"jsc":{"parser":{"syntax":"ecmascript","dynamicImport":true,"jsx":true},"transform":{ "regenerator": { "importPath": "foo" }, "react":{"runtime":"automatic","pragma":"React.createElement","pragmaFrag":"React.Fragment","throwIfNamespace":true,"development":false,"useBuiltins":true}},"target":"es5"},"filename":"/Users/timneutkens/projects/next.js/packages/next/dist/client/next.js","sourceMaps":false,"sourceFileName":"/Users/timneutkens/projects/next.js/packages/next/dist/client/next.js"}"#;

    let tr: TransformOptions = serde_json::from_str(JSON_STR).unwrap();

    println!("{:#?}", tr);
}
<commit_msg>Align behavior of SWC transform & transformSync (#36500)<commit_after>/*
Copyright (c) 2017 The swc Project Developers

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the
Software without restriction, including without
limitation the rights to use, copy, modify, merge,
publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software
is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice
shall be included in all copies or substantial portions
of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/

use crate::{
    complete_output, get_compiler,
    util::{deserialize_json, CtxtExt, MapErr},
};
use anyhow::{anyhow, bail, Context as _};
use fxhash::FxHashSet;
use napi::{CallContext, Env, JsBoolean, JsBuffer, JsObject, JsString, JsUnknown, Status, Task};
use next_swc::{custom_before_pass, TransformOptions};
use std::fs::read_to_string;
use std::{
    cell::RefCell,
    convert::TryFrom,
    panic::{catch_unwind, AssertUnwindSafe},
    rc::Rc,
    sync::Arc,
};
use swc::{try_with_handler, Compiler, TransformOutput};
use swc_common::{errors::ColorConfig, FileName};
use swc_ecmascript::transforms::pass::noop;

/// Input to transform
#[derive(Debug)]
pub enum Input {
    /// Raw source code.
    Source { src: String },
    /// Get source code from filename in options
    FromFilename,
}

pub struct TransformTask {
    pub c: Arc<Compiler>,
    pub input: Input,
    pub options: String,
}

impl Task for TransformTask {
    type Output = (TransformOutput, FxHashSet<String>);
    type JsValue = JsObject;

    fn compute(&mut self) -> napi::Result<Self::Output> {
        let eliminated_packages: Rc<RefCell<fxhash::FxHashSet<String>>> = Default::default();
        let res = catch_unwind(AssertUnwindSafe(|| {
            try_with_handler(
                self.c.cm.clone(),
                swc::HandlerOpts {
                    color: ColorConfig::Never,
                    skip_filename: true,
                },
                |handler| {
                    self.c.run(|| {
                        let options: TransformOptions = deserialize_json(&self.options)?;
                        let fm = match &self.input {
                            Input::Source { src } => {
                                let filename = if options.swc.filename.is_empty() {
                                    FileName::Anon
                                } else {
                                    FileName::Real(options.swc.filename.clone().into())
                                };

                                self.c.cm.new_source_file(filename, src.to_string())
                            }
                            Input::FromFilename => {
                                let filename = &options.swc.filename;
                                if filename.is_empty() {
                                    bail!("no filename is provided via options");
                                }

                                self.c.cm.new_source_file(
                                    FileName::Real(filename.into()),
                                    read_to_string(filename).with_context(|| {
                                        format!("Failed to read source code from {}", filename)
                                    })?,
                                )
                            }
                        };
                        let options = options.patch(&fm);

                        let cm = self.c.cm.clone();
                        let file = fm.clone();

                        self.c.process_js_with_custom_pass(
                            fm,
                            None,
                            handler,
                            &options.swc,
                            |_, comments| {
                                custom_before_pass(
                                    cm,
                                    file,
                                    &options,
                                    comments.clone(),
                                    eliminated_packages.clone(),
                                )
                            },
                            |_, _| noop(),
                        )
                    })
                },
            )
        }))
        .map_err(|err| {
            if let Some(s) = err.downcast_ref::<String>() {
                anyhow!("failed to process {}", s)
            } else {
                anyhow!("failed to process")
            }
        });

        match res {
            Ok(res) => res
                .map(|o| (o, eliminated_packages.replace(Default::default())))
                .convert_err(),
            Err(err) => Err(napi::Error::new(
                Status::GenericFailure,
                format!("{:?}", err),
            )),
        }
    }

    fn resolve(
        self,
        env: Env,
        (output, eliminated_packages): Self::Output,
    ) -> napi::Result<Self::JsValue> {
        complete_output(&env, output, eliminated_packages)
    }
}

/// returns `compiler, (src / path), options, plugin, callback`
pub fn schedule_transform<F>(cx: &CallContext, op: F) -> napi::Result<TransformTask>
where
    F: FnOnce(&Arc<Compiler>, Input, bool, String) -> TransformTask,
{
    let c = get_compiler(cx);

    let unknown_src = cx.get::<JsUnknown>(0)?;
    let src = match unknown_src.get_type()? {
        napi::ValueType::String => napi::Result::Ok(Input::Source {
            src: JsString::try_from(unknown_src)?
                .into_utf8()?
                .as_str()?
                .to_owned(),
        }),
        napi::ValueType::Object => napi::Result::Ok(Input::Source {
            src: String::from_utf8_lossy(JsBuffer::try_from(unknown_src)?.into_value()?.as_ref())
                .to_string(),
        }),
        napi::ValueType::Undefined => napi::Result::Ok(Input::FromFilename),
        _ => Err(napi::Error::new(
            Status::GenericFailure,
            "first argument must be a String or Buffer".to_string(),
        )),
    }?;
    let is_module = cx.get::<JsBoolean>(1)?;
    let options = cx.get_buffer_as_string(2)?;

    Ok(op(&c, src, is_module.get_value()?, options))
}

#[js_function(4)]
pub fn transform(cx: CallContext) -> napi::Result<JsObject> {
    let task = schedule_transform(&cx, |c, input, _, options| TransformTask {
        c: c.clone(),
        input,
        options,
    })?;
    cx.env.spawn(task).map(|handle| handle.promise_object())
}

#[js_function(4)]
pub fn transform_sync(cx: CallContext) -> napi::Result<JsObject> {
    let mut task = schedule_transform(&cx, |c, input, _, options| TransformTask {
        c: c.clone(),
        input,
        options,
    })?;
    let output = task.compute()?;
    task.resolve(*cx.env, output)
}

#[test]
fn test_deser() {
    const JSON_STR: &str = r#"{"jsc":{"parser":{"syntax":"ecmascript","dynamicImport":true,"jsx":true},"transform":{"react":{"runtime":"automatic","pragma":"React.createElement","pragmaFrag":"React.Fragment","throwIfNamespace":true,"development":false,"useBuiltins":true}},"target":"es5"},"filename":"/Users/timneutkens/projects/next.js/packages/next/dist/client/next.js","sourceMaps":false,"sourceFileName":"/Users/timneutkens/projects/next.js/packages/next/dist/client/next.js"}"#;

    let tr: TransformOptions = serde_json::from_str(JSON_STR).unwrap();

    println!("{:#?}", tr);
}

#[test]
fn test_deserialize_transform_regenerator() {
    const JSON_STR: &str = r#"{"jsc":{"parser":{"syntax":"ecmascript","dynamicImport":true,"jsx":true},"transform":{ "regenerator": { "importPath": "foo" }, "react":{"runtime":"automatic","pragma":"React.createElement","pragmaFrag":"React.Fragment","throwIfNamespace":true,"development":false,"useBuiltins":true}},"target":"es5"},"filename":"/Users/timneutkens/projects/next.js/packages/next/dist/client/next.js","sourceMaps":false,"sourceFileName":"/Users/timneutkens/projects/next.js/packages/next/dist/client/next.js"}"#;

    let tr: TransformOptions = serde_json::from_str(JSON_STR).unwrap();

    println!("{:#?}", tr);
}
<|endoftext|>