<commit_before>extern crate udt;

use udt::*;

#[test]
fn test_getsockopt() {
    init();
    let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();

    // test some defaults
    assert_eq!(sock.getsockopt(UdtOpts::UDT_MSS).unwrap(), 1500 as i32);
    assert_eq!(sock.getsockopt(UdtOpts::UDT_SNDSYN).unwrap(), true);
    assert_eq!(sock.getsockopt(UdtOpts::UDT_RCVSYN).unwrap(), true);
    assert_eq!(sock.getsockopt(UdtOpts::UDT_FC).unwrap(), 25600 as i32);
    assert_eq!(sock.getsockopt(UdtOpts::UDT_RENDEZVOUS).unwrap(), false);
    assert_eq!(sock.getsockopt(UdtOpts::UDT_SNDTIMEO).unwrap(), -1);
    assert_eq!(sock.getsockopt(UdtOpts::UDT_RCVTIMEO).unwrap(), -1);

}

#[test]
fn test_setsockopt() {
    init();
    let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();

    assert_eq!(sock.getsockopt(UdtOpts::UDT_MSS).unwrap(), 1500);
    sock.setsockopt(UdtOpts::UDT_MSS, 1400).unwrap();
    assert_eq!(sock.getsockopt(UdtOpts::UDT_MSS).unwrap(), 1400);
}

#[test]
fn test_sendmsg() {
    use std::thread::spawn;
    use std::net::{SocketAddr, SocketAddrV4};
    use std::net::Ipv4Addr;
    use std::str::FromStr;
    use std::sync::mpsc::channel;

    init();

    let localhost = Ipv4Addr::from_str("127.0.0.1").unwrap();

    // the server will bind to a random port and pass it back for the client to connect to
    let (tx, rx) = channel();

    // spawn the server
    let server = spawn(move || {
        let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();
        sock.bind(SocketAddr::V4(SocketAddrV4::new(localhost, 0))).unwrap();
        let my_addr = sock.getsockname().unwrap();
        println!("Server bound to {:?}", my_addr);

        sock.listen(5).unwrap();

        tx.send(my_addr.port());

        let (mut new, peer) = sock.accept().unwrap();
        println!("Server recieved connection from {:?}", peer);

        let peer2 = new.getpeername().unwrap();
        assert_eq!(peer2, peer);

        let msg = new.recvmsg(100).unwrap();
        assert_eq!(msg.len(), 5);
        assert_eq!(msg, "hello".as_bytes());
        new.sendmsg("world".as_bytes()).unwrap();

        new.close();
        sock.close();

    });

    let client = spawn(move || {
        let port = rx.recv().unwrap();
        println!("Client connecting to port {:?}", port);
        let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();
        sock.connect(SocketAddr::V4(SocketAddrV4::new(localhost, port))).unwrap();

        sock.sendmsg("hello".as_bytes()).unwrap();
        let msg = sock.recvmsg(1024).unwrap();
        assert_eq!(msg.len(), 5);
        assert_eq!(msg, "world".as_bytes());

        sock.close();

    });

    server.join();
    client.join();

}

#[test]
fn test_send() {
    use std::thread::spawn;
    use std::net::{SocketAddr, SocketAddrV4};
    use std::net::Ipv4Addr;
    use std::str::FromStr;
    use std::sync::mpsc::channel;

    init();

    let localhost = Ipv4Addr::from_str("127.0.0.1").unwrap();

    // the server will bind to a random port and pass it back for the client to connect to
    let (tx, rx) = channel();

    // spawn the server
    let server = spawn(move || {
        let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Stream).unwrap();
        sock.bind(SocketAddr::V4(SocketAddrV4::new(localhost, 0))).unwrap();
        let my_addr = sock.getsockname().unwrap();
        println!("Server bound to {:?}", my_addr);

        sock.listen(5).unwrap();

        tx.send(my_addr.port());

        let (mut new, new_peer) = sock.accept().unwrap();
        println!("Server recieved connection from {:?}", new_peer);

        let mut buf: [u8; 10] = [0; 10];
        assert_eq!(new.recv(&mut buf, 5).unwrap(), 5);
        assert_eq!(&buf[0..5], "hello".as_bytes());
        assert_eq!(&buf[5..], [0; 5]);
        assert_eq!(new.recv(&mut buf[5..], 5).unwrap(), 5);
        assert_eq!(&buf[5..], "world".as_bytes());
        assert_eq!(&buf, "helloworld".as_bytes());

        new.close();
        sock.close();

    });

    let client = spawn(move || {
        let port = rx.recv().unwrap();
        println!("Client connecting to port {:?}", port);
        let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Stream).unwrap();
        sock.connect(SocketAddr::V4(SocketAddrV4::new(localhost, port))).unwrap();

        assert_eq!(sock.send("hello".as_bytes()).unwrap(), 5);
        assert_eq!(sock.send("world".as_bytes()).unwrap(), 5);

        sock.close();

    });

    server.join();
    client.join();

}

#[test]
fn test_epoll() {
    use std::thread::spawn;
    use std::net::{SocketAddr, SocketAddrV4};
    use std::net::Ipv4Addr;
    use std::str::FromStr;
    use std::sync::mpsc::channel;
    use std::thread::sleep_ms;

    init();

    let localhost = Ipv4Addr::from_str("127.0.0.1").unwrap();

    // the server will bind to a random port and pass it back for the client to connect to
    let (tx, rx) = channel();

    // spawn the server
    let server = spawn(move || {
        let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();
        sock.bind(SocketAddr::V4(SocketAddrV4::new(localhost, 0))).unwrap();
        let my_addr = sock.getsockname().unwrap();
        println!("Server bound to {:?}", my_addr);

        sock.listen(5).unwrap();

        tx.send(my_addr.port());

        let mut epoll = Epoll::create().unwrap();

        epoll.add_usock(&sock).unwrap();

        let mut counter = 0;
        loop {
            let (pending_rd, pending_wr) = epoll.wait(1000, true).unwrap();
            println!("Pending sockets: {:?} {:?}", pending_rd, pending_wr);

            let rd_len = pending_rd.len();
            for mut s in pending_rd {
                if s == sock {
                    println!("trying to accept new sock");
                    let (mut new, peer) = sock.accept().unwrap();
                    println!("Server recieved connection from {:?}", peer);
                    epoll.add_usock(&new).unwrap();
                } else {
                    let msg = s.recvmsg(100).unwrap();
                    let msg_string = String::from_utf8(msg).unwrap();
                    println!("Received message: {:?}", msg_string);
                }

            }

            for mut s in pending_wr {
                let state = s.getstate();
                if rd_len == 0 && (state == UdtStatus::BROKEN || state == UdtStatus::CLOSED || state == UdtStatus::NONEXIST) {
                    epoll.remove_usock(&s);
                    return;
                }
                println!("Sock {:?} is in state {:?}", s, state);
            }
            sleep_ms(100);
            counter += 1;
            assert!(counter < 500);
        }

        sock.close();

    });

    let client = spawn(move || {
        let port = rx.recv().unwrap();
        println!("Client connecting to port {:?}", port);
        let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();
        sock.connect(SocketAddr::V4(SocketAddrV4::new(localhost, port))).unwrap();

        sock.sendmsg("hello".as_bytes()).unwrap();

        sleep_ms(3000);
        sock.sendmsg("world".as_bytes()).unwrap();
        sock.sendmsg("done.".as_bytes()).unwrap();

        sock.close();

    });

    server.join();
    client.join();

}

<commit_msg>unwrap joinguards to properly capture test failures<commit_after>extern crate udt;

use udt::*;

#[test]
fn test_getsockopt() {
    init();
    let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();

    // test some defaults
    assert_eq!(sock.getsockopt(UdtOpts::UDT_MSS).unwrap(), 1500 as i32);
    assert_eq!(sock.getsockopt(UdtOpts::UDT_SNDSYN).unwrap(), true);
    assert_eq!(sock.getsockopt(UdtOpts::UDT_RCVSYN).unwrap(), true);
    assert_eq!(sock.getsockopt(UdtOpts::UDT_FC).unwrap(), 25600 as i32);
    assert_eq!(sock.getsockopt(UdtOpts::UDT_RENDEZVOUS).unwrap(), false);
    assert_eq!(sock.getsockopt(UdtOpts::UDT_SNDTIMEO).unwrap(), -1);
    assert_eq!(sock.getsockopt(UdtOpts::UDT_RCVTIMEO).unwrap(), -1);

}

#[test]
fn test_setsockopt() {
    init();
    let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();

    assert_eq!(sock.getsockopt(UdtOpts::UDT_MSS).unwrap(), 1500);
    sock.setsockopt(UdtOpts::UDT_MSS, 1400).unwrap();
    assert_eq!(sock.getsockopt(UdtOpts::UDT_MSS).unwrap(), 1400);
}

#[test]
fn test_sendmsg() {
    use std::thread::spawn;
    use std::net::{SocketAddr, SocketAddrV4};
    use std::net::Ipv4Addr;
    use std::str::FromStr;
    use std::sync::mpsc::channel;

    init();

    let localhost = Ipv4Addr::from_str("127.0.0.1").unwrap();

    // the server will bind to a random port and pass it back for the client to connect to
    let (tx, rx) = channel();

    // spawn the server
    let server = spawn(move || {
        let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();
        sock.bind(SocketAddr::V4(SocketAddrV4::new(localhost, 0))).unwrap();
        let my_addr = sock.getsockname().unwrap();
        println!("Server bound to {:?}", my_addr);

        sock.listen(5).unwrap();

        tx.send(my_addr.port());

        let (mut new, peer) = sock.accept().unwrap();
        println!("Server recieved connection from {:?}", peer);

        let peer2 = new.getpeername().unwrap();
        assert_eq!(peer2, peer);

        let msg = new.recvmsg(100).unwrap();
        assert_eq!(msg.len(), 5);
        assert_eq!(msg, "hello".as_bytes());
        new.sendmsg("world".as_bytes()).unwrap();

        new.close();
        sock.close();

    });

    let client = spawn(move || {
        let port = rx.recv().unwrap();
        println!("Client connecting to port {:?}", port);
        let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();
        sock.connect(SocketAddr::V4(SocketAddrV4::new(localhost, port))).unwrap();

        sock.sendmsg("hello".as_bytes()).unwrap();
        let msg = sock.recvmsg(1024).unwrap();
        assert_eq!(msg.len(), 5);
        assert_eq!(msg, "world".as_bytes());

        sock.close();

    });

    server.join().unwrap();
    client.join().unwrap();

}

#[test]
fn test_send() {
    use std::thread::spawn;
    use std::net::{SocketAddr, SocketAddrV4};
    use std::net::Ipv4Addr;
    use std::str::FromStr;
    use std::sync::mpsc::channel;

    init();

    let localhost = Ipv4Addr::from_str("127.0.0.1").unwrap();

    // the server will bind to a random port and pass it back for the client to connect to
    let (tx, rx) = channel();

    // spawn the server
    let server = spawn(move || {
        let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Stream).unwrap();
        sock.bind(SocketAddr::V4(SocketAddrV4::new(localhost, 0))).unwrap();
        let my_addr = sock.getsockname().unwrap();
        println!("Server bound to {:?}", my_addr);

        sock.listen(5).unwrap();

        tx.send(my_addr.port());

        let (mut new, new_peer) = sock.accept().unwrap();
        println!("Server recieved connection from {:?}", new_peer);

        let mut buf: [u8; 10] = [0; 10];
        assert_eq!(new.recv(&mut buf, 5).unwrap(), 5);
        assert_eq!(&buf[0..5], "hello".as_bytes());
        assert_eq!(&buf[5..], [0; 5]);
        assert_eq!(new.recv(&mut buf[5..], 5).unwrap(), 5);
        assert_eq!(&buf[5..], "world".as_bytes());
        assert_eq!(&buf, "helloworld".as_bytes());

        new.close();
        sock.close();

    });

    let client = spawn(move || {
        let port = rx.recv().unwrap();
        println!("Client connecting to port {:?}", port);
        let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Stream).unwrap();
        sock.connect(SocketAddr::V4(SocketAddrV4::new(localhost, port))).unwrap();

        assert_eq!(sock.send("hello".as_bytes()).unwrap(), 5);
        assert_eq!(sock.send("world".as_bytes()).unwrap(), 5);

        sock.close();

    });

    server.join().unwrap();
    client.join().unwrap();

}

#[test]
fn test_epoll() {
    use std::thread::spawn;
    use std::net::{SocketAddr, SocketAddrV4};
    use std::net::Ipv4Addr;
    use std::str::FromStr;
    use std::sync::mpsc::channel;
    use std::thread::sleep_ms;

    init();

    let localhost = Ipv4Addr::from_str("127.0.0.1").unwrap();

    // the server will bind to a random port and pass it back for the client to connect to
    let (tx, rx) = channel();

    // spawn the server
    let server = spawn(move || {
        let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();
        sock.bind(SocketAddr::V4(SocketAddrV4::new(localhost, 0))).unwrap();
        let my_addr = sock.getsockname().unwrap();
        println!("Server bound to {:?}", my_addr);

        sock.listen(5).unwrap();

        tx.send(my_addr.port());

        let mut epoll = Epoll::create().unwrap();

        epoll.add_usock(&sock).unwrap();

        let mut counter = 0;
        loop {
            let (pending_rd, pending_wr) = epoll.wait(1000, true).unwrap();
            println!("Pending sockets: {:?} {:?}", pending_rd, pending_wr);

            let rd_len = pending_rd.len();
            for mut s in pending_rd {
                if s == sock {
                    println!("trying to accept new sock");
                    let (mut new, peer) = sock.accept().unwrap();
                    println!("Server recieved connection from {:?}", peer);
                    epoll.add_usock(&new).unwrap();
                } else {
                    let msg = s.recvmsg(100).unwrap();
                    let msg_string = String::from_utf8(msg).unwrap();
                    println!("Received message: {:?}", msg_string);
                }

            }

            for mut s in pending_wr {
                let state = s.getstate();
                if rd_len == 0 && (state == UdtStatus::BROKEN || state == UdtStatus::CLOSED || state == UdtStatus::NONEXIST) {
                    epoll.remove_usock(&s);
                    return;
                }
                println!("Sock {:?} is in state {:?}", s, state);
            }
            sleep_ms(100);
            counter += 1;
            assert!(counter < 500);
        }

        sock.close();

    });

    let client = spawn(move || {
        let port = rx.recv().unwrap();
        println!("Client connecting to port {:?}", port);
        let mut sock = UdtSocket::new(SocketFamily::AFInet, SocketType::Datagram).unwrap();
        sock.connect(SocketAddr::V4(SocketAddrV4::new(localhost, port))).unwrap();

        sock.sendmsg("hello".as_bytes()).unwrap();

        sleep_ms(3000);
        sock.sendmsg("world".as_bytes()).unwrap();
        sock.sendmsg("done.".as_bytes()).unwrap();

        sock.close();

    });

    server.join().unwrap();
    client.join().unwrap();

}

<|endoftext|>


<commit_before>#[macro_use] extern crate cfor;

#[test]
fn smoketest() {
    let mut tick = 0;
    cfor!{let mut i = 1; i <= 0b1000_0000; i *= 2; {
        tick += 1;
    }}

    assert_eq!(tick, 8);

    tick = 0;
    cfor!{let (mut a, mut b) = (0, 0); a + b < 20; { a += 1; b += 1; }; {
        tick += 1;
    }}
    assert_eq!(tick, 10);
}

#[test]
#[should_panic]
fn continue_updates() {
    cfor!(let i = 0; i < 10; panic!(); {
        // we *should* hit the step expression.
        continue
    })
}

#[test]
fn missing_parts() {
    let mut inside = false;
    cfor!{;; (); {
        inside = true;
        break
    }}
    assert!(inside);

    inside = false;
    cfor!{();; (); {
        inside = true;
        break
    }}
    assert!(inside);

    cfor!{; false; ; {
        panic!()
    }}
}
<commit_msg>Added tests<commit_after>#[macro_use] extern crate cfor;

#[test]
fn smoketest() {
    let mut tick = 0;
    cfor!{let mut i = 1; i <= 0b1000_0000; i *= 2; {
        tick += 1;
    }}

    assert_eq!(tick, 8);

    tick = 0;
    cfor!{let (mut a, mut b) = (0, 0); a + b < 20; { a += 1; b += 1; }; {
        tick += 1;
    }}
    assert_eq!(tick, 10);
}

#[test]
#[should_panic]
fn continue_updates() {
    cfor!(let i = 0; i < 10; panic!(); {
        // we *should* hit the step expression.
        continue
    })
}

#[test]
fn missing_parts() {
    let mut inside = false;
    cfor!{;; (); {
        inside = true;
        break
    }}
    assert!(inside);

    inside = false;
    cfor!{();; (); {
        inside = true;
        break
    }}
    assert!(inside);

    cfor!{; false; ; {
        panic!()
    }}
}

#[test]
fn multi_dec() {
    cfor!(let x = true, let y = x, let z = false; false;; {
        assert!(x);
        assert_eq!(x, y);
        assert!(!z);
    });
}

#[test]
fn multi_step() {
    let mut x = 0;
    let mut y = 0;
    cfor!(; x < 10 && y < 100; x += 1, y += 10; {});
    assert_eq!(x, 10);
    assert_eq!(y, 100);
}
<|endoftext|>


<commit_before>extern crate cargo;
extern crate url;
extern crate env_logger;
extern crate git2_curl;
extern crate toml;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

use std::collections::BTreeSet;
use std::collections::HashMap;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};

use cargo::core::shell::{Shell, Verbosity};
use cargo::util::{self, CliResult, lev_distance, Config, CargoResult, CargoError, CargoErrorKind};
use cargo::util::CliError;

#[derive(Deserialize)]
pub struct Flags {
    flag_list: bool,
    flag_version: bool,
    flag_verbose: u32,
    flag_quiet: Option<bool>,
    flag_color: Option<String>,
    flag_explain: Option<String>,
    arg_command: String,
    arg_args: Vec<String>,
    flag_locked: bool,
    flag_frozen: bool,
}

const USAGE: &'static str = "
Rust's package manager

Usage:
    cargo <command> [<args>...]
    cargo [options]

Options:
    -h, --help          Display this message
    -V, --version       Print version info and exit
    --list              List installed commands
    --explain CODE      Run `rustc --explain CODE`
    -v, --verbose ...   Use verbose output (-vv very verbose/build.rs output)
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never
    --frozen            Require Cargo.lock and cache are up to date
    --locked            Require Cargo.lock is up to date

Some common cargo commands are (see all commands with --list):
    build       Compile the current project
    check       Analyze the current project and report errors, but don't build object files
    clean       Remove the target directory
    doc         Build this project's and its dependencies' documentation
    new         Create a new cargo project
    init        Create a new cargo project in an existing directory
    run         Build and execute src/main.rs
    test        Run the tests
    bench       Run the benchmarks
    update      Update dependencies listed in Cargo.lock
    search      Search registry for crates
    publish     Package and upload this project to the registry
    install     Install a Rust binary

See 'cargo help <command>' for more information on a specific command.
";

fn main() {
    env_logger::init().unwrap();

    let config = match Config::default() {
        Ok(cfg) => cfg,
        Err(e) => {
            let mut shell = Shell::new();
            cargo::exit_with_error(e.into(), &mut shell)
        }
    };

    let result = (|| {
        let args: Vec<_> = try!(env::args_os()
            .map(|s| {
                s.into_string().map_err(|s| {
                    CargoError::from(format!("invalid unicode in argument: {:?}", s))
                })
            })
            .collect());
        let rest = &args;
        cargo::call_main_without_stdin(execute, &config, USAGE, rest, true)
    })();

    match result {
        Err(e) => cargo::exit_with_error(e, &mut *config.shell()),
        Ok(()) => {}
    }
}

macro_rules! each_subcommand{
    ($mac:ident) => {
        $mac!(bench);
        $mac!(build);
        $mac!(check);
        $mac!(clean);
        $mac!(doc);
        $mac!(fetch);
        $mac!(generate_lockfile);
        $mac!(git_checkout);
        $mac!(help);
        $mac!(init);
        $mac!(install);
        $mac!(locate_project);
        $mac!(login);
        $mac!(metadata);
        $mac!(new);
        $mac!(owner);
        $mac!(package);
        $mac!(pkgid);
        $mac!(publish);
        $mac!(read_manifest);
        $mac!(run);
        $mac!(rustc);
        $mac!(rustdoc);
        $mac!(search);
        $mac!(test);
        $mac!(uninstall);
        $mac!(update);
        $mac!(verify_project);
        $mac!(version);
        $mac!(yank);
    }
}

macro_rules! declare_mod {
    ($name:ident) => ( pub mod $name; )
}
each_subcommand!(declare_mod);

/**
  The top-level `cargo` command handles configuration and project location
  because they are fundamental (and intertwined). Other commands can rely
  on this top-level information.
*/
fn execute(flags: Flags, config: &Config) -> CliResult {
    config.configure(flags.flag_verbose,
                   flags.flag_quiet,
                   &flags.flag_color,
                   flags.flag_frozen,
                   flags.flag_locked)?;

    init_git_transports(config);
    let _token = cargo::util::job::setup();

    if flags.flag_version {
        let version = cargo::version();
        println!("{}", version);
        if flags.flag_verbose > 0 {
            println!("release: {}.{}.{}",
                     version.major,
                     version.minor,
                     version.patch);
            if let Some(ref cfg) = version.cfg_info {
                if let Some(ref ci) = cfg.commit_info {
                    println!("commit-hash: {}", ci.commit_hash);
                    println!("commit-date: {}", ci.commit_date);
                }
            }
        }
        return Ok(());
    }

    if flags.flag_list {
        println!("Installed Commands:");
        for command in list_commands(config) {
            println!("    {}", command);
        }
        return Ok(());
    }

    if let Some(ref code) = flags.flag_explain {
        let mut procss = config.rustc()?.process();
        procss.arg("--explain").arg(code).exec()?;
        return Ok(());
    }

    let args = match &flags.arg_command[..] {
        // For the commands `cargo` and `cargo help`, re-execute ourselves as
        // `cargo -h` so we can go through the normal process of printing the
        // help message.
        "" | "help" if flags.arg_args.is_empty() => {
            config.shell().set_verbosity(Verbosity::Verbose);
            let args = &["cargo".to_string(), "-h".to_string()];
            return cargo::call_main_without_stdin(execute, config, USAGE, args, false);
        }

        // For `cargo help -h` and `cargo help --help`, print out the help
        // message for `cargo help`
        "help" if flags.arg_args[0] == "-h" || flags.arg_args[0] == "--help" => {
            vec!["cargo".to_string(), "help".to_string(), "-h".to_string()]
        }

        // For `cargo help foo`, print out the usage message for the specified
        // subcommand by executing the command with the `-h` flag.
        "help" => vec!["cargo".to_string(), flags.arg_args[0].clone(), "-h".to_string()],

        // For all other invocations, we're of the form `cargo foo args...`. We
        // use the exact environment arguments to preserve tokens like `--` for
        // example.
        _ => {
            let mut default_alias = HashMap::new();
            default_alias.insert("b", "build".to_string());
            default_alias.insert("t", "test".to_string());
            default_alias.insert("r", "run".to_string());
            let mut args: Vec<String> = env::args().collect();
            if let Some(new_command) = default_alias.get(&args[1][..]) {
                args[1] = new_command.clone();
            }
            args
        }
    };

    if let Some(r) = try_execute_builtin_command(&config, &args) {
        return r;
    }

    let alias_list = aliased_command(&config, &args[1])?;
    let args = match alias_list {
        Some(alias_command) => {
            let chain = args.iter()
                .take(1)
                .chain(alias_command.iter())
                .chain(args.iter().skip(2))
                .map(|s| s.to_string())
                .collect::<Vec<_>>();
            if let Some(r) = try_execute_builtin_command(&config, &chain) {
                return r;
            } else {
                chain
            }
        }
        None => args,
    };

    execute_external_subcommand(config, &args[1], &args)
}

fn try_execute_builtin_command(config: &Config, args: &[String]) -> Option<CliResult> {
    macro_rules! cmd {
        ($name:ident) => (if args[1] == stringify!($name).replace("_", "-") {
            config.shell().set_verbosity(Verbosity::Verbose);
            let r = cargo::call_main_without_stdin($name::execute, config,
                                                   $name::USAGE,
                                                   &args,
                                                   false);
            return Some(r);
        })
    }
    each_subcommand!(cmd);

    None
}

fn aliased_command(config: &Config, command: &String) -> CargoResult<Option<Vec<String>>> {
    let alias_name = format!("alias.{}", command);
    let mut result = Ok(None);
    match config.get_string(&alias_name) {
        Ok(value) => {
            if let Some(record) = value {
                let alias_commands = record.val
                    .split_whitespace()
                    .map(|s| s.to_string())
                    .collect();
                result = Ok(Some(alias_commands));
            }
        }
        Err(_) => {
            let value = config.get_list(&alias_name)?;
            if let Some(record) = value {
                let alias_commands: Vec<String> = record.val
                    .iter()
                    .map(|s| s.0.to_string())
                    .collect();
                result = Ok(Some(alias_commands));
            }
        }
    }
    result
}

fn find_closest(config: &Config, cmd: &str) -> Option<String> {
    let cmds = list_commands(config);
    // Only consider candidates with a lev_distance of 3 or less so we don't
    // suggest out-of-the-blue options.
    let mut filtered = cmds.iter()
        .map(|c| (lev_distance(&c, cmd), c))
        .filter(|&(d, _)| d < 4)
        .collect::<Vec<_>>();
    filtered.sort_by(|a, b| a.0.cmp(&b.0));
    filtered.get(0).map(|slot| slot.1.clone())
}

fn execute_external_subcommand(config: &Config, cmd: &str, args: &[String]) -> CliResult {
    let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
    let path = search_directories(config)
        .iter()
        .map(|dir| dir.join(&command_exe))
        .find(|file| is_executable(file));
    let command = match path {
        Some(command) => command,
        None => {
            return Err(CargoError::from(match find_closest(config, cmd) {
                    Some(closest) => {
                        format!("no such subcommand: `{}`\n\n\tDid you mean `{}`?\n",
                                cmd,
                                closest)
                    }
                    None => format!("no such subcommand: `{}`", cmd),
                })
                .into())
        }
    };

    let cargo_exe = config.cargo_exe()?;
    let err = match util::process(&command)
        .env(cargo::CARGO_ENV, cargo_exe)
        .args(&args[1..])
        .exec_replace() {
        Ok(()) => return Ok(()),
        Err(e) => e,
    };

    if let &CargoErrorKind::ProcessErrorKind(ref perr) = err.kind() {
        if let Some(code) = perr.exit.as_ref().and_then(|c| c.code()) {
            return Err(CliError::code(code));
        }
    }
    Err(CliError::new(err, 101))
}

/// List all runnable commands
fn list_commands(config: &Config) -> BTreeSet<String> {
    let prefix = "cargo-";
    let suffix = env::consts::EXE_SUFFIX;
    let mut commands = BTreeSet::new();
    for dir in search_directories(config) {
        let entries = match fs::read_dir(dir) {
            Ok(entries) => entries,
            _ => continue,
        };
        for entry in entries.filter_map(|e| e.ok()) {
            let path = entry.path();
            let filename = match path.file_name().and_then(|s| s.to_str()) {
                Some(filename) => filename,
                _ => continue,
            };
            if !filename.starts_with(prefix) || !filename.ends_with(suffix) {
                continue;
            }
            if is_executable(entry.path()) {
                let end = filename.len() - suffix.len();
                commands.insert(filename[prefix.len()..end].to_string());
            }
        }
    }

    macro_rules! add_cmd {
        ($cmd:ident) => ({ commands.insert(stringify!($cmd).replace("_", "-")); })
    }
    each_subcommand!(add_cmd);
    commands
}

#[cfg(unix)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    use std::os::unix::prelude::*;
    fs::metadata(path)
        .map(|metadata| metadata.is_file() && metadata.permissions().mode() & 0o111 != 0)
        .unwrap_or(false)
}
#[cfg(windows)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    fs::metadata(path).map(|metadata| metadata.is_file()).unwrap_or(false)
}

fn search_directories(config: &Config) -> Vec<PathBuf> {
    let mut dirs = vec![config.home().clone().into_path_unlocked().join("bin")];
    if let Some(val) = env::var_os("PATH") {
        dirs.extend(env::split_paths(&val));
    }
    dirs
}

fn init_git_transports(config: &Config) {
    // Only use a custom transport if a proxy is configured, right now libgit2
    // doesn't support proxies and we have to use a custom transport in this
    // case. The custom transport, however, is not as well battle-tested.
    match cargo::ops::http_proxy_exists(config) {
        Ok(true) => {}
        _ => return,
    }

    let handle = match cargo::ops::http_handle(config) {
        Ok(handle) => handle,
        Err(..) => return,
    };

    // The unsafety of the registration function derives from two aspects:
    //
    // 1. This call must be synchronized with all other registration calls as
    //    well as construction of new transports.
    // 2. The argument is leaked.
    //
    // We're clear on point (1) because this is only called at the start of this
    // binary (we know what the state of the world looks like) and we're mostly
    // clear on point (2) because we'd only free it after everything is done
    // anyway
    unsafe {
        git2_curl::register(handle);
    }
}
<commit_msg>Add "uninstall" command to cargo --help<commit_after>extern crate cargo;
extern crate url;
extern crate env_logger;
extern crate git2_curl;
extern crate toml;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

use std::collections::BTreeSet;
use std::collections::HashMap;
use std::env;
use std::fs;
use std::path::{Path, PathBuf};

use cargo::core::shell::{Shell, Verbosity};
use cargo::util::{self, CliResult, lev_distance, Config, CargoResult, CargoError, CargoErrorKind};
use cargo::util::CliError;

#[derive(Deserialize)]
pub struct Flags {
    flag_list: bool,
    flag_version: bool,
    flag_verbose: u32,
    flag_quiet: Option<bool>,
    flag_color: Option<String>,
    flag_explain: Option<String>,
    arg_command: String,
    arg_args: Vec<String>,
    flag_locked: bool,
    flag_frozen: bool,
}

const USAGE: &'static str = "
Rust's package manager

Usage:
    cargo <command> [<args>...]
    cargo [options]

Options:
    -h, --help          Display this message
    -V, --version       Print version info and exit
    --list              List installed commands
    --explain CODE      Run `rustc --explain CODE`
    -v, --verbose ...   Use verbose output (-vv very verbose/build.rs output)
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never
    --frozen            Require Cargo.lock and cache are up to date
    --locked            Require Cargo.lock is up to date

Some common cargo commands are (see all commands with --list):
    build       Compile the current project
    check       Analyze the current project and report errors, but don't build object files
    clean       Remove the target directory
    doc         Build this project's and its dependencies' documentation
    new         Create a new cargo project
    init        Create a new cargo project in an existing directory
    run         Build and execute src/main.rs
    test        Run the tests
    bench       Run the benchmarks
    update      Update dependencies listed in Cargo.lock
    search      Search registry for crates
    publish     Package and upload this project to the registry
    install     Install a Rust binary
    uninstall   Uninstall a Rust binary

See 'cargo help <command>' for more information on a specific command.
";

fn main() {
    env_logger::init().unwrap();

    let config = match Config::default() {
        Ok(cfg) => cfg,
        Err(e) => {
            let mut shell = Shell::new();
            cargo::exit_with_error(e.into(), &mut shell)
        }
    };

    let result = (|| {
        let args: Vec<_> = try!(env::args_os()
            .map(|s| {
                s.into_string().map_err(|s| {
                    CargoError::from(format!("invalid unicode in argument: {:?}", s))
                })
            })
            .collect());
        let rest = &args;
        cargo::call_main_without_stdin(execute, &config, USAGE, rest, true)
    })();

    match result {
        Err(e) => cargo::exit_with_error(e, &mut *config.shell()),
        Ok(()) => {}
    }
}

macro_rules! each_subcommand{
    ($mac:ident) => {
        $mac!(bench);
        $mac!(build);
        $mac!(check);
        $mac!(clean);
        $mac!(doc);
        $mac!(fetch);
        $mac!(generate_lockfile);
        $mac!(git_checkout);
        $mac!(help);
        $mac!(init);
        $mac!(install);
        $mac!(locate_project);
        $mac!(login);
        $mac!(metadata);
        $mac!(new);
        $mac!(owner);
        $mac!(package);
        $mac!(pkgid);
        $mac!(publish);
        $mac!(read_manifest);
        $mac!(run);
        $mac!(rustc);
        $mac!(rustdoc);
        $mac!(search);
        $mac!(test);
        $mac!(uninstall);
        $mac!(update);
        $mac!(verify_project);
        $mac!(version);
        $mac!(yank);
    }
}

macro_rules! declare_mod {
    ($name:ident) => ( pub mod $name; )
}
each_subcommand!(declare_mod);

/**
  The top-level `cargo` command handles configuration and project location
  because they are fundamental (and intertwined). Other commands can rely
  on this top-level information.
*/
fn execute(flags: Flags, config: &Config) -> CliResult {
    config.configure(flags.flag_verbose,
                   flags.flag_quiet,
                   &flags.flag_color,
                   flags.flag_frozen,
                   flags.flag_locked)?;

    init_git_transports(config);
    let _token = cargo::util::job::setup();

    if flags.flag_version {
        let version = cargo::version();
        println!("{}", version);
        if flags.flag_verbose > 0 {
            println!("release: {}.{}.{}",
                     version.major,
                     version.minor,
                     version.patch);
            if let Some(ref cfg) = version.cfg_info {
                if let Some(ref ci) = cfg.commit_info {
                    println!("commit-hash: {}", ci.commit_hash);
                    println!("commit-date: {}", ci.commit_date);
                }
            }
        }
        return Ok(());
    }

    if flags.flag_list {
        println!("Installed Commands:");
        for command in list_commands(config) {
            println!("    {}", command);
        }
        return Ok(());
    }

    if let Some(ref code) = flags.flag_explain {
        let mut procss = config.rustc()?.process();
        procss.arg("--explain").arg(code).exec()?;
        return Ok(());
    }

    let args = match &flags.arg_command[..] {
        // For the commands `cargo` and `cargo help`, re-execute ourselves as
        // `cargo -h` so we can go through the normal process of printing the
        // help message.
        "" | "help" if flags.arg_args.is_empty() => {
            config.shell().set_verbosity(Verbosity::Verbose);
            let args = &["cargo".to_string(), "-h".to_string()];
            return cargo::call_main_without_stdin(execute, config, USAGE, args, false);
        }

        // For `cargo help -h` and `cargo help --help`, print out the help
        // message for `cargo help`
        "help" if flags.arg_args[0] == "-h" || flags.arg_args[0] == "--help" => {
            vec!["cargo".to_string(), "help".to_string(), "-h".to_string()]
        }

        // For `cargo help foo`, print out the usage message for the specified
        // subcommand by executing the command with the `-h` flag.
        "help" => vec!["cargo".to_string(), flags.arg_args[0].clone(), "-h".to_string()],

        // For all other invocations, we're of the form `cargo foo args...`. We
        // use the exact environment arguments to preserve tokens like `--` for
        // example.
        _ => {
            let mut default_alias = HashMap::new();
            default_alias.insert("b", "build".to_string());
            default_alias.insert("t", "test".to_string());
            default_alias.insert("r", "run".to_string());
            let mut args: Vec<String> = env::args().collect();
            if let Some(new_command) = default_alias.get(&args[1][..]) {
                args[1] = new_command.clone();
            }
            args
        }
    };

    if let Some(r) = try_execute_builtin_command(&config, &args) {
        return r;
    }

    let alias_list = aliased_command(&config, &args[1])?;
    let args = match alias_list {
        Some(alias_command) => {
            let chain = args.iter()
                .take(1)
                .chain(alias_command.iter())
                .chain(args.iter().skip(2))
                .map(|s| s.to_string())
                .collect::<Vec<_>>();
            if let Some(r) = try_execute_builtin_command(&config, &chain) {
                return r;
            } else {
                chain
            }
        }
        None => args,
    };

    execute_external_subcommand(config, &args[1], &args)
}

fn try_execute_builtin_command(config: &Config, args: &[String]) -> Option<CliResult> {
    macro_rules! cmd {
        ($name:ident) => (if args[1] == stringify!($name).replace("_", "-") {
            config.shell().set_verbosity(Verbosity::Verbose);
            let r = cargo::call_main_without_stdin($name::execute, config,
                                                   $name::USAGE,
                                                   &args,
                                                   false);
            return Some(r);
        })
    }
    each_subcommand!(cmd);

    None
}

fn aliased_command(config: &Config, command: &String) -> CargoResult<Option<Vec<String>>> {
    let alias_name = format!("alias.{}", command);
    let mut result = Ok(None);
    match config.get_string(&alias_name) {
        Ok(value) => {
            if let Some(record) = value {
                let alias_commands = record.val
                    .split_whitespace()
                    .map(|s| s.to_string())
                    .collect();
                result = Ok(Some(alias_commands));
            }
        }
        Err(_) => {
            let value = config.get_list(&alias_name)?;
            if let Some(record) = value {
                let alias_commands: Vec<String> = record.val
                    .iter()
                    .map(|s| s.0.to_string())
                    .collect();
                result = Ok(Some(alias_commands));
            }
        }
    }
    result
}

fn find_closest(config: &Config, cmd: &str) -> Option<String> {
    let cmds = list_commands(config);
    // Only consider candidates with a lev_distance of 3 or less so we don't
    // suggest out-of-the-blue options.
    let mut filtered = cmds.iter()
        .map(|c| (lev_distance(&c, cmd), c))
        .filter(|&(d, _)| d < 4)
        .collect::<Vec<_>>();
    filtered.sort_by(|a, b| a.0.cmp(&b.0));
    filtered.get(0).map(|slot| slot.1.clone())
}

fn execute_external_subcommand(config: &Config, cmd: &str, args: &[String]) -> CliResult {
    let command_exe = format!("cargo-{}{}", cmd, env::consts::EXE_SUFFIX);
    let path = search_directories(config)
        .iter()
        .map(|dir| dir.join(&command_exe))
        .find(|file| is_executable(file));
    let command = match path {
        Some(command) => command,
        None => {
            return Err(CargoError::from(match find_closest(config, cmd) {
                    Some(closest) => {
                        format!("no such subcommand: `{}`\n\n\tDid you mean `{}`?\n",
                                cmd,
                                closest)
                    }
                    None => format!("no such subcommand: `{}`", cmd),
                })
                .into())
        }
    };

    let cargo_exe = config.cargo_exe()?;
    let err = match util::process(&command)
        .env(cargo::CARGO_ENV, cargo_exe)
        .args(&args[1..])
        .exec_replace() {
        Ok(()) => return Ok(()),
        Err(e) => e,
    };

    if let &CargoErrorKind::ProcessErrorKind(ref perr) = err.kind() {
        if let Some(code) = perr.exit.as_ref().and_then(|c| c.code()) {
            return Err(CliError::code(code));
        }
    }
    Err(CliError::new(err, 101))
}

/// List all runnable commands
fn list_commands(config: &Config) -> BTreeSet<String> {
    let prefix = "cargo-";
    let suffix = env::consts::EXE_SUFFIX;
    let mut commands = BTreeSet::new();
    for dir in search_directories(config) {
        let entries = match fs::read_dir(dir) {
            Ok(entries) => entries,
            _ => continue,
        };
        for entry in entries.filter_map(|e| e.ok()) {
            let path = entry.path();
            let filename = match path.file_name().and_then(|s| s.to_str()) {
                Some(filename) => filename,
                _ => continue,
            };
            if !filename.starts_with(prefix) || !filename.ends_with(suffix) {
                continue;
            }
            if is_executable(entry.path()) {
                let end = filename.len() - suffix.len();
                commands.insert(filename[prefix.len()..end].to_string());
            }
        }
    }

    macro_rules! add_cmd {
        ($cmd:ident) => ({ commands.insert(stringify!($cmd).replace("_", "-")); })
    }
    each_subcommand!(add_cmd);
    commands
}

#[cfg(unix)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    use std::os::unix::prelude::*;
    fs::metadata(path)
        .map(|metadata| metadata.is_file() && metadata.permissions().mode() & 0o111 != 0)
        .unwrap_or(false)
}
#[cfg(windows)]
fn is_executable<P: AsRef<Path>>(path: P) -> bool {
    fs::metadata(path).map(|metadata| metadata.is_file()).unwrap_or(false)
}

fn search_directories(config: &Config) -> Vec<PathBuf> {
    let mut dirs = vec![config.home().clone().into_path_unlocked().join("bin")];
    if let Some(val) = env::var_os("PATH") {
        dirs.extend(env::split_paths(&val));
    }
    dirs
}

fn init_git_transports(config: &Config) {
    // Only use a custom transport if a proxy is configured, right now libgit2
    // doesn't support proxies and we have to use a custom transport in this
    // case. The custom transport, however, is not as well battle-tested.
    match cargo::ops::http_proxy_exists(config) {
        Ok(true) => {}
        _ => return,
    }

    let handle = match cargo::ops::http_handle(config) {
        Ok(handle) => handle,
        Err(..) => return,
    };

    // The unsafety of the registration function derives from two aspects:
    //
    // 1. This call must be synchronized with all other registration calls as
    //    well as construction of new transports.
    // 2. The argument is leaked.
    //
    // We're clear on point (1) because this is only called at the start of this
    // binary (we know what the state of the world looks like) and we're mostly
    // clear on point (2) because we'd only free it after everything is done
    // anyway
    unsafe {
        git2_curl::register(handle);
    }
}
<|endoftext|>


<commit_before>#![feature(core)]
#![feature(collections)]
#![feature(io)]
#![feature(os)]
#![feature(path)]
#![feature(plugin)]
#[plugin] #[no_link]
extern crate regex_macros;
extern crate regex;

use std::old_io::fs::PathExtensions;
use std::old_io;
use std::os;

const TOP:&'static str = "
#![crate_type = \"dylib\"]
extern crate libc;

use libc::*;
use std::io::stdio::*;
use std::collections::HashMap;

const NOOP_FUNC:&'static WashFunc = &(noop as WashFunc);

pub type WashFunc = fn(&Vec<String>, &mut WashEnv) -> Vec<String>;
pub type VarTable = HashMap<String, String>;
pub type FuncTable = HashMap<String, WashFunc>;
pub type ScriptTable = HashMap<Path, WashScript>;

pub struct WashEnv {
    variables: VarTable,
    functions: FuncTable,
    scripts: ScriptTable,
    controls: Controls
}

pub struct WashScript {
    path: Path,
    hash: String,
    controls: Controls,
    handle: *const c_void,
    run_ptr: *const c_void,
    load_ptr: *const c_void,
    loaded: bool
}

pub struct Controls {
    stdin: StdinReader,
    stdout: StdWriter,
    stderr: StdWriter
}

impl WashEnv {
    pub fn hasv(&self, name:String) -> bool {
        self.variables.contains_key(&name)
    }

    pub fn hasf(&self, name:String) -> bool {
        self.functions.contains_key(&name)
    }

    pub fn insv(&mut self, name:String, val:String) {
        self.variables.insert(name, val);
    }

    pub fn insf(&mut self, name:String, func:WashFunc) {
        self.functions.insert(name, func);
    }

    pub fn getv(u_env:*const WashEnv, name:String) -> String {
        let env = unsafe{u_env.as_ref()}.unwrap();
        return match env.variables.get(&name) {
            None => \"\".to_string(),
            Some(val) => val.clone()
        };
    }

    pub fn getf<'a>(u_env:*const WashEnv, name:String) -> &'a WashFunc {
        let env = unsafe{u_env.as_ref()}.unwrap();
        return match env.functions.get(&name) {
            None => NOOP_FUNC,
            Some(ptr) => ptr
        }
    }
}

fn noop(args:&Vec<String>, env:&mut WashEnv) -> Vec<String> {
    return vec![];
}

fn sgetenv(name:&str) -> String {
    return std::os::getenv(name).unwrap_or(\"\".to_string()).to_string();
}";

const RUN_TOP:&'static str = "
#[no_mangle]
pub extern fn wash_run(u_args:*const Vec<String>, u_env:*mut WashEnv) {
    let args = unsafe{u_args.as_ref()}.unwrap();
    let mut env = unsafe{u_env.as_mut()}.unwrap();
";

const RUN_BOTTOM:&'static str = "
}";

fn process_line(line:String) -> String {
    if regex!("=").is_match(line.as_slice()) {
        let parts = regex!("=").splitn(line.as_slice(), 2).collect::<Vec<&str>>();
        return process_lvalue(parts[0].to_string()).connect(process_rvalue(parts[1].to_string()).as_slice());
    } else {
        return process_rvalue(line);
    }
}

fn process_lvalue(val:String) -> Vec<String> {
    if regex!("\\$([^ \t\n\r,\"()]+):([^ \t\n\r,\"()]+)").is_match(val.as_slice()) {
        let caps = regex!("\\$([^ \t\n\r,\"()]+):([^ \t\n\r,\"()]+)").captures(val.as_slice()).unwrap();
        match caps.at(1).unwrap() {
            "env" => {
                let val = caps.at(2).unwrap();
                let pre = format!("std::os::setenv(\"{}\", ", val).to_string();
                return vec![pre, ".as_slice());".to_string()];
            },
            _ => panic!("Unknown variable identifier")
        }
    } else if regex!("\\$([^ \t\n\r,\"()]+)").is_match(val.as_slice()) {
        let val = regex!("\\$([^ \t\n\r,\"()]+)").captures(val.as_slice()).unwrap().at(1).unwrap();
        let pre = format!("env.insv(\"{}\".to_string(), ", val).to_string();
        return vec![pre, ");".to_string()];
    } else {
        return vec![];
    }
}

fn process_rvalue(val:String) -> String {
    if regex!("^\\s*\"[^\"]*\"\\s*$").is_match(val.as_slice()) {
        let val = regex!("\"[^\"]*\"").captures(val.as_slice()).unwrap().at(0).unwrap();
        return format!("{}.to_string()", val.to_string());
    } if regex!("^\\s*\\$([^ \t\n\r,\"()]+):([^ \t\n\r,\"()]+)\\s*$").is_match(val.as_slice()) {
        let caps = regex!("\\$([^ \t\n\r,\"()]+):([^ \t\n\r,\"()]+)").captures(val.as_slice()).unwrap();
        match caps.at(1).unwrap() {
            "env" => {
                let val = caps.at(2).unwrap();
                return format!("sgetenv(\"{}\")", val).to_string();
            },
            _ => panic!("Unknown variable identifier")
        }
    } else if regex!("^\\s*\\$([^ \t\n\r,\"()]+)\\s*$").is_match(val.as_slice()) {
        let val = regex!("\\$([^ \t\n\r,\"()]+)").captures(val.as_slice()).unwrap().at(1).unwrap();
        return format!("WashEnv::getv(env, \"{}\".to_string())", val).to_string();
    } else if regex!("^\\s*([^ \t\n\r,\"()]+)\\((.*)\\)\\s*$").is_match(val.as_slice()) {
        let caps = regex!("([^ \t\n\r,\"()]+)\\((.*)\\)").captures(val.as_slice()).unwrap();
        let name = caps.at(1).unwrap();
        let re = regex!("(\".+\"|[^ \t\n\r,\"()]+)");
        let args_cap = caps.at(2).unwrap();
        let mut args = Vec::<String>::new();
        for cap in re.captures_iter(args_cap) {
            args.push(process_rvalue(cap.at(1).unwrap().to_string()));
        }
        return format!("WashEnv::getf(env, \"{}\".to_string())(&vec![{}], env);", name, args.connect(", ")).to_string()
    } else {
        return "".to_string();
    }
}

pub fn main() {
    let args = os::args();
    if args.len() == 1 {
        panic!("No arguments given");
    }
    let inp = Path::new(args[1].to_string());
    if !inp.exists() {
        panic!("File does not exist");
    }
    let mut stdout = old_io::stdout();
    let mut inf = old_io::BufferedReader::new(old_io::File::open(&inp));
    stdout.write_str(TOP).unwrap();
    stdout.write_str(RUN_TOP).unwrap();
    loop {
        match inf.read_line() {
            Err(_) => break,
            Ok(line) => {
                stdout.write_str(process_line(line).as_slice()).unwrap();
                stdout.write_str("\n").unwrap();
            }
        }
    }
    stdout.write_str(RUN_BOTTOM).unwrap();
    stdout.write_str("\n").unwrap();
}

<commit_msg>Update for rust nightlies<commit_after>#![feature(core)]
#![feature(io)]
#![feature(os)]
#![feature(path)]
#![feature(plugin)]
#[plugin] #[no_link]
extern crate regex_macros;
extern crate regex;

use std::old_io::fs::PathExtensions;
use std::old_io;
use std::os;

const TOP:&'static str = "
#![crate_type = \"dylib\"]
extern crate libc;

use libc::*;
use std::io::stdio::*;
use std::collections::HashMap;

const NOOP_FUNC:&'static WashFunc = &(noop as WashFunc);

pub type WashFunc = fn(&Vec<String>, &mut WashEnv) -> Vec<String>;
pub type VarTable = HashMap<String, String>;
pub type FuncTable = HashMap<String, WashFunc>;
pub type ScriptTable = HashMap<Path, WashScript>;

pub struct WashEnv {
    variables: VarTable,
    functions: FuncTable,
    scripts: ScriptTable,
    controls: Controls
}

pub struct WashScript {
    path: Path,
    hash: String,
    controls: Controls,
    handle: *const c_void,
    run_ptr: *const c_void,
    load_ptr: *const c_void,
    loaded: bool
}

pub struct Controls {
    stdin: StdinReader,
    stdout: StdWriter,
    stderr: StdWriter
}

impl WashEnv {
    pub fn hasv(&self, name:String) -> bool {
        self.variables.contains_key(&name)
    }

    pub fn hasf(&self, name:String) -> bool {
        self.functions.contains_key(&name)
    }

    pub fn insv(&mut self, name:String, val:String) {
        self.variables.insert(name, val);
    }

    pub fn insf(&mut self, name:String, func:WashFunc) {
        self.functions.insert(name, func);
    }

    pub fn getv(u_env:*const WashEnv, name:String) -> String {
        let env = unsafe{u_env.as_ref()}.unwrap();
        return match env.variables.get(&name) {
            None => \"\".to_string(),
            Some(val) => val.clone()
        };
    }

    pub fn getf<'a>(u_env:*const WashEnv, name:String) -> &'a WashFunc {
        let env = unsafe{u_env.as_ref()}.unwrap();
        return match env.functions.get(&name) {
            None => NOOP_FUNC,
            Some(ptr) => ptr
        }
    }
}

fn noop(args:&Vec<String>, env:&mut WashEnv) -> Vec<String> {
    return vec![];
}

fn sgetenv(name:&str) -> String {
    return std::os::getenv(name).unwrap_or(\"\".to_string()).to_string();
}";

const RUN_TOP:&'static str = "
#[no_mangle]
pub extern fn wash_run(u_args:*const Vec<String>, u_env:*mut WashEnv) {
    let args = unsafe{u_args.as_ref()}.unwrap();
    let mut env = unsafe{u_env.as_mut()}.unwrap();
";

const RUN_BOTTOM:&'static str = "
}";

fn process_line(line:String) -> String {
    if regex!("=").is_match(line.as_slice()) {
        let parts = regex!("=").splitn(line.as_slice(), 2).collect::<Vec<&str>>();
        return process_lvalue(parts[0].to_string()).connect(process_rvalue(parts[1].to_string()).as_slice());
    } else {
        return process_rvalue(line);
    }
}

fn process_lvalue(val:String) -> Vec<String> {
    if regex!("\\$([^ \t\n\r,\"()]+):([^ \t\n\r,\"()]+)").is_match(val.as_slice()) {
        let caps = regex!("\\$([^ \t\n\r,\"()]+):([^ \t\n\r,\"()]+)").captures(val.as_slice()).unwrap();
        match caps.at(1).unwrap() {
            "env" => {
                let val = caps.at(2).unwrap();
                let pre = format!("std::os::setenv(\"{}\", ", val).to_string();
                return vec![pre, ".as_slice());".to_string()];
            },
            _ => panic!("Unknown variable identifier")
        }
    } else if regex!("\\$([^ \t\n\r,\"()]+)").is_match(val.as_slice()) {
        let val = regex!("\\$([^ \t\n\r,\"()]+)").captures(val.as_slice()).unwrap().at(1).unwrap();
        let pre = format!("env.insv(\"{}\".to_string(), ", val).to_string();
        return vec![pre, ");".to_string()];
    } else {
        return vec![];
    }
}

fn process_rvalue(val:String) -> String {
    if regex!("^\\s*\"[^\"]*\"\\s*$").is_match(val.as_slice()) {
        let val = regex!("\"[^\"]*\"").captures(val.as_slice()).unwrap().at(0).unwrap();
        return format!("{}.to_string()", val.to_string());
    } if regex!("^\\s*\\$([^ \t\n\r,\"()]+):([^ \t\n\r,\"()]+)\\s*$").is_match(val.as_slice()) {
        let caps = regex!("\\$([^ \t\n\r,\"()]+):([^ \t\n\r,\"()]+)").captures(val.as_slice()).unwrap();
        match caps.at(1).unwrap() {
            "env" => {
                let val = caps.at(2).unwrap();
                return format!("sgetenv(\"{}\")", val).to_string();
            },
            _ => panic!("Unknown variable identifier")
        }
    } else if regex!("^\\s*\\$([^ \t\n\r,\"()]+)\\s*$").is_match(val.as_slice()) {
        let val = regex!("\\$([^ \t\n\r,\"()]+)").captures(val.as_slice()).unwrap().at(1).unwrap();
        return format!("WashEnv::getv(env, \"{}\".to_string())", val).to_string();
    } else if regex!("^\\s*([^ \t\n\r,\"()]+)\\((.*)\\)\\s*$").is_match(val.as_slice()) {
        let caps = regex!("([^ \t\n\r,\"()]+)\\((.*)\\)").captures(val.as_slice()).unwrap();
        let name = caps.at(1).unwrap();
        let re = regex!("(\".+\"|[^ \t\n\r,\"()]+)");
        let args_cap = caps.at(2).unwrap();
        let mut args = Vec::<String>::new();
        for cap in re.captures_iter(args_cap) {
            args.push(process_rvalue(cap.at(1).unwrap().to_string()));
        }
        return format!("WashEnv::getf(env, \"{}\".to_string())(&vec![{}], env);", name, args.connect(", ")).to_string()
    } else {
        return "".to_string();
    }
}

pub fn main() {
    let args = os::args();
    if args.len() == 1 {
        panic!("No arguments given");
    }
    let inp = Path::new(args[1].to_string());
    if !inp.exists() {
        panic!("File does not exist");
    }
    let mut stdout = old_io::stdout();
    let mut inf = old_io::BufferedReader::new(old_io::File::open(&inp));
    stdout.write_str(TOP).unwrap();
    stdout.write_str(RUN_TOP).unwrap();
    loop {
        match inf.read_line() {
            Err(_) => break,
            Ok(line) => {
                stdout.write_str(process_line(line).as_slice()).unwrap();
                stdout.write_str("\n").unwrap();
            }
        }
    }
    stdout.write_str(RUN_BOTTOM).unwrap();
    stdout.write_str("\n").unwrap();
}

<|endoftext|>


<commit_before>//! Quicksort algorithm.
//!
//! The `efficient` module contains the efficient sorting algorithm "Quicksort".
//!
//! Source: https://en.wikipedia.org/wiki/Quicksort

extern crate libc;

use std::fmt::Debug;
use std::slice;

/// Quicksort
///
/// # Details
///
///
///
/// # Scaling
///
///
///
/// # Optimizations
///
/// None
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let mut data: Vec<i32> = vec![4, 2, 3, 1, 5];
/// sorting::efficientsorts::quick::sort(&mut data);
/// assert_eq!(vec![1, 2, 3, 4, 5], data);
/// ```
///
// pub fn sort<T: PartialOrd>(array: &mut Vec<T>) {
pub fn sort<T: PartialOrd + Debug>(array: &mut [T]) {
    let n = array.len();

    if n <= 1 {
        // Don't do anything
    } else if n == 2 {
        if array.first() > array.last() {
            array.swap(0, 1);
        }
    } else {
        // Pick a pivot: Pick the middle element by skipping half the length and keeping just one.
        // let it_pivot = array.iter().skip(n / 2).take(1);
        // Take the first element as the pivot.
        // let it_pivot = array.iter().take(1);
        //
        // for it in it_pivot {
        //     println!("  0. it: {:?}", it);
        // }

        // Loop over array, finding smaller elements than the pivot.
        // for it in array.iter().skip(1) {
        //     //println!("  1. it: {:?}", it);
        //     if it < it_pivot {
        //         println!("  1. it: {:?} smaller than pivot!", it);
        //     }
        // }
        // array.swap(0,1);

        // array.iter().enumerate().map(|(i,x)| {});

        // // Take the first element as pivot.
        // let a = array.iter_mut().skip(1).enumerate().fold(
        //     (0, array[0]), |acc, item| {
        //         if acc.1 > item.1 {
        //             // Element is smaller than pivot; swap them!
        //             array.swap(acc.0, item.0);
        //             // Return the accumulator as being the new index of pivot (which is now at
        //             // at the location of the fold()) with the pivot value which shouldn't change.
        //             (item.0, acc.1)
        //         } else {
        //             // Nothing to do as element is larger than pivot. Just return new accumulator.
        //             (acc.0, acc.1)
        //         }
        //     }
        // );

        // Use the first element as the pivot, and loop over the rest of the vector.
        let mut pivot = 0;
        for i in 1..n {
            // The loop element is smaller than the pivot. Shuffle things around to place that
            // element before the pivot.
            if array[pivot] > array[i] {
                // First, let's swap the element and the pivot.
                array.swap(pivot, i);
                // Two cases are possible here:
                //     1) The element was the one next to the pivot in the vector. As such, the
                //        new pivot's location is the index "i".
                //     2) The element swaped was further down the vector. If we just swap the pivot
                //        and that element, we are sending the pivot _after_ larger elements,
                //        breaking the ordering! Additionally to the first swap, the pivot (now
                //        being at index "i" after the first swap) is again swapped with the
                //        element that was next to it before (index "pivot+1").
                if i == pivot+1 {
                    pivot = i;
                } else {
                    array.swap(i, pivot+1);
                    pivot = pivot+1;
                }
            }
        }

        // Recursively call the function on slices of the vector.
        sort(&mut array[0..pivot+1]);
        sort(&mut array[pivot+1..n]);
    }
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_i8(array_pointer: *const libc::int8_t, n: libc::size_t) {
    let array = unsafe {
        slice::from_raw_parts(array_pointer as *const i8, n as usize)
    };
    println!("Rust: n     = {:?}", n);
    println!("Rust: array = {:?}", array);
    unimplemented!();
}
<commit_msg>Created external interfaces for Quicksort for every types.<commit_after>//! Quicksort algorithm.
//!
//! The `efficient` module contains the efficient sorting algorithm "Quicksort".
//!
//! Source: https://en.wikipedia.org/wiki/Quicksort

extern crate libc;

use std::fmt::Debug;
use std::slice;

/// Quicksort
///
/// # Details
///
///
///
/// # Scaling
///
///
///
/// # Optimizations
///
/// None
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let mut data: Vec<i32> = vec![4, 2, 3, 1, 5];
/// sorting::efficientsorts::quick::sort(&mut data);
/// assert_eq!(vec![1, 2, 3, 4, 5], data);
/// ```
///
// pub fn sort<T: PartialOrd>(array: &mut Vec<T>) {
pub fn sort<T: PartialOrd + Debug>(array: &mut [T]) {
    let n = array.len();

    if n <= 1 {
        // Don't do anything
    } else if n == 2 {
        if array.first() > array.last() {
            array.swap(0, 1);
        }
    } else {
        // Pick a pivot: Pick the middle element by skipping half the length and keeping just one.
        // let it_pivot = array.iter().skip(n / 2).take(1);
        // Take the first element as the pivot.
        // let it_pivot = array.iter().take(1);
        //
        // for it in it_pivot {
        //     println!("  0. it: {:?}", it);
        // }

        // Loop over array, finding smaller elements than the pivot.
        // for it in array.iter().skip(1) {
        //     //println!("  1. it: {:?}", it);
        //     if it < it_pivot {
        //         println!("  1. it: {:?} smaller than pivot!", it);
        //     }
        // }
        // array.swap(0,1);

        // array.iter().enumerate().map(|(i,x)| {});

        // // Take the first element as pivot.
        // let a = array.iter_mut().skip(1).enumerate().fold(
        //     (0, array[0]), |acc, item| {
        //         if acc.1 > item.1 {
        //             // Element is smaller than pivot; swap them!
        //             array.swap(acc.0, item.0);
        //             // Return the accumulator as being the new index of pivot (which is now at
        //             // at the location of the fold()) with the pivot value which shouldn't change.
        //             (item.0, acc.1)
        //         } else {
        //             // Nothing to do as element is larger than pivot. Just return new accumulator.
        //             (acc.0, acc.1)
        //         }
        //     }
        // );

        // Use the first element as the pivot, and loop over the rest of the vector.
        let mut pivot = 0;
        for i in 1..n {
            // The loop element is smaller than the pivot. Shuffle things around to place that
            // element before the pivot.
            if array[pivot] > array[i] {
                // First, let's swap the element and the pivot.
                array.swap(pivot, i);
                // Two cases are possible here:
                //     1) The element was the one next to the pivot in the vector. As such, the
                //        new pivot's location is the index "i".
                //     2) The element swaped was further down the vector. If we just swap the pivot
                //        and that element, we are sending the pivot _after_ larger elements,
                //        breaking the ordering! Additionally to the first swap, the pivot (now
                //        being at index "i" after the first swap) is again swapped with the
                //        element that was next to it before (index "pivot+1").
                if i == pivot+1 {
                    pivot = i;
                } else {
                    array.swap(i, pivot+1);
                    pivot = pivot+1;
                }
            }
        }

        // Recursively call the function on slices of the vector.
        sort(&mut array[0..pivot+1]);
        sort(&mut array[pivot+1..n]);
    }
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_i8(array_pointer: *const libc::int8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i8, n as usize)
    };

    println!("Rust: n = {:?}        to_sort = {:?}", n, to_sort);

    sort(&mut to_sort);

    println!("Rust:         sorted array = {:?}", to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i16(array_pointer: *const libc::int16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i32(array_pointer: *const libc::int32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i64(array_pointer: *const libc::int64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_u8(array_pointer: *const libc::uint8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u8, n as usize)
    };

    println!("Rust: n = {:?}        to_sort = {:?}", n, to_sort);

    sort(&mut to_sort);

    println!("Rust:         sorted array = {:?}", to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u16(array_pointer: *const libc::uint16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u32(array_pointer: *const libc::uint32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u64(array_pointer: *const libc::uint64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_f32(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_f64(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i64, n as usize)
    };
    sort(&mut to_sort);
}
<|endoftext|>


<commit_before>use basenum::BaseFloat;
use builtin::{ cross, dot, normalize };
use traits::GenFloat;
use num;
use mat::mat::{ Matrix3, Matrix4 };
use vec::vec::{ Vector3, Vector4 };

/// Builds a translation 4 * 4 matrix created from a vector of 3 components.
///
/// Uses input matrix `m` and translation vector coordinates `v`.
///
/// # Example
///
/// ```rust
/// # extern crate num;
/// # extern crate glm;
/// # fn main() {
/// use glm::*;
/// use glm::ext::*;
///
/// let matrix = translate(&num::one(), vec3(1., 2., 3.));
/// assert_eq!(matrix[3], vec4(1., 2., 3., 1.));
/// # }
/// ```
#[inline]
pub fn translate<T>(
    m: &Matrix4<T>,
    v: Vector3<T>
) -> Matrix4<T>
where
    T : BaseFloat
{
    Matrix4::new(
        m.c0, m.c1, m.c2,
        m.c0 * v.x + m.c1 * v.y + m.c2 * v.z + m.c3)
}

/// Creates a matrix for a symetric perspective-view frustum based on the default handedness.
///
/// `fov_y` is the field of view angle in the y direction in radians.
/// The `aspect` ratio determines the field of view in the x direction.
/// `near_z` is the distance from the viewer to the near clipping plane (always positive) and
/// `far_z` is the distance from the viewer to the far clipping plane (always positive).
#[inline]
pub fn perspective<T>(
    fov_y: T,
    aspect: T,
    z_near: T,
    z_far: T
) -> Matrix4<T>
where
    T : BaseFloat
{
    // TODO: make this a compile option
    perspective_rh(fov_y, aspect, z_near, z_far)
}

/// Creates a matrix for a right handed, symetric perspective-view frustum.
///
/// `fov_y` is the field of view angle in the y direction in radians.
/// The `aspect` ratio determines the field of view in the x direction.
/// `near_z` is the distance from the viewer to the near clipping plane (always positive) and
/// `far_z` is the distance from the viewer to the far clipping plane (always positive).
#[inline]
pub fn perspective_rh<T>(
    fov_y: T,
    aspect: T,
    z_near: T,
    z_far: T
) -> Matrix4<T>
where
    T : BaseFloat
{
    let zero = num::zero::<T>();
    let one = num::one::<T>();
    let two = one + one;
    let q = one / (fov_y / two).tan();
    let a = q / aspect;
    let b = (z_near + z_far) / (z_near - z_far);
    let c = (two * z_near * z_far) / (z_near - z_far);

    Matrix4::new(
        Vector4::new(   a, zero, zero, zero),
        Vector4::new(zero,    q, zero, zero),
        Vector4::new(zero, zero,    b, zero - one),
        Vector4::new(zero, zero,    c, zero)
    )
}

/// Builds a rotation 4 * 4 matrix created from an axis vector and an angle.
///
/// `m` as the input matrix multiplied by this rotation matrix.
/// `angle` is the rotation angle expressed in radians.
/// Rotation `axis` is recommended to be normalized.
#[inline]
pub fn rotate<T>(
    m: &Matrix4<T>,
    angle: T,
    v: Vector3<T>
) -> Matrix4<T>
where
    T : BaseFloat + GenFloat<T>
{
    let zero = num::zero::<T>();
    let one = num::one::<T>();

    let a = angle;
    let (s, c) = a.sin_cos();
    let axis = normalize(v);
    let temp = axis * (one - c);

    let rotate = Matrix3::new(
        Vector3::new(
            c + temp.x * axis.x,
            temp.x * axis.y + s * axis.z,
            temp.x * axis.z - s * axis.y),
        Vector3::new(
            temp.y * axis.x - s * axis.z,
            c + temp.y * axis.y,
            temp.y * axis.z + s * axis.x),
        Vector3::new(
            temp.z * axis.x + s * axis.y,
            temp.z * axis.y - s * axis.x,
            c + temp.z * axis.z)
        );

    Matrix4::new(
		m.c0 * rotate.c0.x + m.c1 * rotate.c0.y + m.c2 * rotate.c0.z,
		m.c0 * rotate.c1.x + m.c1 * rotate.c1.y + m.c2 * rotate.c1.z,
		m.c0 * rotate.c2.x + m.c1 * rotate.c2.y + m.c2 * rotate.c2.z,
		m.c3
        )
}

/// Builds a scale 4 * 4 matrix created from 3 scalars.
///
/// `m` is the input matrix multiplied by this scale matrix.
/// `v` is the ratio of scaling for each axis.
#[inline]
pub fn scale<T>(
    m: &Matrix4<T>,
    v: Vector3<T>
) -> Matrix4<T>
where
    T : BaseFloat + GenFloat<T>
{
    Matrix4::new(
        m.c0 * v.x,
        m.c1 * v.y,
        m.c2 * v.z,
        m.c3)
}

/// Build a look at view matrix based on the default handedness.
///
/// View matrix is based on the `eye` position of the camera, `center` position where the camera is
/// looking at and a normalized `up` vector, how the camera is oriented. Typically (0, 0, 1)
#[inline]
pub fn look_at<T>(
    eye: Vector3<T>,
    center: Vector3<T>,
    up: Vector3<T>
) -> Matrix4<T>
where
    T : BaseFloat + GenFloat<T>
{
    // TODO: make handedness configurable
    look_at_rh::<T>(eye, center, up)
}

/// Build a right handed look at view matrix.
///
/// View matrix is based on the `eye` position of the camera, `center` position where the camera is
/// looking at and a normalized `up` vector, how the camera is oriented. Typically (0, 0, 1)
#[inline]
pub fn look_at_rh<T>(
    eye: Vector3<T>,
    center: Vector3<T>,
    up: Vector3<T>
) -> Matrix4<T>
where
    T : BaseFloat + GenFloat<T>
{
    let zero = num::zero::<T>();
    let one = num::one::<T>();
    let f = normalize(center - eye);
    let up_n = normalize(up);
    let s = cross(f, up_n);
    let u = cross(s, f);
    Matrix4::new(
        Vector4::new(s.x, u.x,-f.x, zero),
        Vector4::new(s.y, u.y,-f.y, zero),
        Vector4::new(s.z, u.z,-f.z, zero),
        Vector4::new(-dot(s, eye), -dot(u, eye), dot(f, eye), one)
    )
}

#[cfg(test)]
mod test {
    use num;
    use std::f32;
    use vec::vec::{ vec3, vec4 };
    use ext::{ perspective, translate };

    #[test]
    fn test_translate() {
        let v = vec3(1.0, 3.0, 2.0);
        let m = num::one();
        let t = translate(&m, v);
        assert_eq!(t[0], vec4(1., 0., 0., 0.));
        assert_eq!(t[1], vec4(0., 1., 0., 0.));
        assert_eq!(t[2], vec4(0., 0., 1., 0.));
        assert_eq!(t[3], v.extend(1.));
    }

    #[test]
    fn test_perspective() {
        let p = perspective(f32::consts::PI * 2.0 * 45.0 / 360.0, 1920.0 / 1080.0, 0.1, 100.0);
    }
}
<commit_msg>fix look_at function<commit_after>use basenum::BaseFloat;
use builtin::{ cross, dot, normalize };
use traits::GenFloat;
use num;
use mat::mat::{ Matrix3, Matrix4 };
use vec::vec::{ Vector3, Vector4 };

/// Builds a translation 4 * 4 matrix created from a vector of 3 components.
///
/// Uses input matrix `m` and translation vector coordinates `v`.
///
/// # Example
///
/// ```rust
/// # extern crate num;
/// # extern crate glm;
/// # fn main() {
/// use glm::*;
/// use glm::ext::*;
///
/// let matrix = translate(&num::one(), vec3(1., 2., 3.));
/// assert_eq!(matrix[3], vec4(1., 2., 3., 1.));
/// # }
/// ```
#[inline]
pub fn translate<T>(
    m: &Matrix4<T>,
    v: Vector3<T>
) -> Matrix4<T>
where
    T : BaseFloat
{
    Matrix4::new(
        m.c0, m.c1, m.c2,
        m.c0 * v.x + m.c1 * v.y + m.c2 * v.z + m.c3)
}

/// Creates a matrix for a symetric perspective-view frustum based on the default handedness.
///
/// `fov_y` is the field of view angle in the y direction in radians.
/// The `aspect` ratio determines the field of view in the x direction.
/// `near_z` is the distance from the viewer to the near clipping plane (always positive) and
/// `far_z` is the distance from the viewer to the far clipping plane (always positive).
#[inline]
pub fn perspective<T>(
    fov_y: T,
    aspect: T,
    z_near: T,
    z_far: T
) -> Matrix4<T>
where
    T : BaseFloat
{
    // TODO: make this a compile option
    perspective_rh(fov_y, aspect, z_near, z_far)
}

/// Creates a matrix for a right handed, symetric perspective-view frustum.
///
/// `fov_y` is the field of view angle in the y direction in radians.
/// The `aspect` ratio determines the field of view in the x direction.
/// `near_z` is the distance from the viewer to the near clipping plane (always positive) and
/// `far_z` is the distance from the viewer to the far clipping plane (always positive).
#[inline]
pub fn perspective_rh<T>(
    fov_y: T,
    aspect: T,
    z_near: T,
    z_far: T
) -> Matrix4<T>
where
    T : BaseFloat
{
    let zero = num::zero::<T>();
    let one = num::one::<T>();
    let two = one + one;
    let q = one / (fov_y / two).tan();
    let a = q / aspect;
    let b = (z_near + z_far) / (z_near - z_far);
    let c = (two * z_near * z_far) / (z_near - z_far);

    Matrix4::new(
        Vector4::new(   a, zero, zero, zero),
        Vector4::new(zero,    q, zero, zero),
        Vector4::new(zero, zero,    b, zero - one),
        Vector4::new(zero, zero,    c, zero)
    )
}

/// Builds a rotation 4 * 4 matrix created from an axis vector and an angle.
///
/// `m` as the input matrix multiplied by this rotation matrix.
/// `angle` is the rotation angle expressed in radians.
/// Rotation `axis` is recommended to be normalized.
#[inline]
pub fn rotate<T>(
    m: &Matrix4<T>,
    angle: T,
    v: Vector3<T>
) -> Matrix4<T>
where
    T : BaseFloat + GenFloat<T>
{
    let zero = num::zero::<T>();
    let one = num::one::<T>();

    let a = angle;
    let (s, c) = a.sin_cos();
    let axis = normalize(v);
    let temp = axis * (one - c);

    let rotate = Matrix3::new(
        Vector3::new(
            c + temp.x * axis.x,
            temp.x * axis.y + s * axis.z,
            temp.x * axis.z - s * axis.y),
        Vector3::new(
            temp.y * axis.x - s * axis.z,
            c + temp.y * axis.y,
            temp.y * axis.z + s * axis.x),
        Vector3::new(
            temp.z * axis.x + s * axis.y,
            temp.z * axis.y - s * axis.x,
            c + temp.z * axis.z)
        );

    Matrix4::new(
		m.c0 * rotate.c0.x + m.c1 * rotate.c0.y + m.c2 * rotate.c0.z,
		m.c0 * rotate.c1.x + m.c1 * rotate.c1.y + m.c2 * rotate.c1.z,
		m.c0 * rotate.c2.x + m.c1 * rotate.c2.y + m.c2 * rotate.c2.z,
		m.c3
        )
}

/// Builds a scale 4 * 4 matrix created from 3 scalars.
///
/// `m` is the input matrix multiplied by this scale matrix.
/// `v` is the ratio of scaling for each axis.
#[inline]
pub fn scale<T>(
    m: &Matrix4<T>,
    v: Vector3<T>
) -> Matrix4<T>
where
    T : BaseFloat + GenFloat<T>
{
    Matrix4::new(
        m.c0 * v.x,
        m.c1 * v.y,
        m.c2 * v.z,
        m.c3)
}

/// Build a look at view matrix based on the default handedness.
///
/// View matrix is based on the `eye` position of the camera, `center` position where the camera is
/// looking at and a normalized `up` vector, how the camera is oriented. Typically (0, 0, 1)
#[inline]
pub fn look_at<T>(
    eye: Vector3<T>,
    center: Vector3<T>,
    up: Vector3<T>
) -> Matrix4<T>
where
    T : BaseFloat + GenFloat<T>
{
    // TODO: make handedness configurable
    look_at_rh::<T>(eye, center, up)
}

/// Build a right handed look at view matrix.
///
/// View matrix is based on the `eye` position of the camera, `center` position where the camera is
/// looking at and a normalized `up` vector, how the camera is oriented. Typically (0, 0, 1)
#[inline]
pub fn look_at_rh<T>(
    eye: Vector3<T>,
    center: Vector3<T>,
    up: Vector3<T>
) -> Matrix4<T>
where
    T : BaseFloat + GenFloat<T>
{
    let zero = num::zero::<T>();
    let one = num::one::<T>();
    let f = normalize(center - eye);
    let s = normalize(cross(f, up));
    let u = cross(s, f);
    Matrix4::new(
        Vector4::new(s.x, u.x,-f.x, zero),
        Vector4::new(s.y, u.y,-f.y, zero),
        Vector4::new(s.z, u.z,-f.z, zero),
        Vector4::new(-dot(s, eye), -dot(u, eye), dot(f, eye), one)
    )
}

#[cfg(test)]
mod test {
    use num;
    use std::f32;
    use vec::vec::{ vec3, vec4 };
    use ext::{ perspective, translate };

    #[test]
    fn test_translate() {
        let v = vec3(1.0, 3.0, 2.0);
        let m = num::one();
        let t = translate(&m, v);
        assert_eq!(t[0], vec4(1., 0., 0., 0.));
        assert_eq!(t[1], vec4(0., 1., 0., 0.));
        assert_eq!(t[2], vec4(0., 0., 1., 0.));
        assert_eq!(t[3], v.extend(1.));
    }

    #[test]
    fn test_perspective() {
        let p = perspective(f32::consts::PI * 2.0 * 45.0 / 360.0, 1920.0 / 1080.0, 0.1, 100.0);
    }
}
<|endoftext|>


<commit_before>use parking_lot::Mutex;
use std::cmp::{max, min};
use std::sync::Arc;

use driver::cmd::Args;
use gc::swiper::large::LargeSpace;
use gc::swiper::old::OldGen;
use gc::swiper::young::YoungGen;
use gc::swiper::CollectionKind;
use gc::{align_gen, formatted_size, GEN_SIZE, M};
use timer;

pub fn choose_collection_kind(config: &SharedHeapConfig, young: &YoungGen) -> CollectionKind {
    let (eden_size, semi_size) = young.committed_size();
    let young_size = eden_size + semi_size;

    let rest = {
        let config = config.lock();
        config.old_limit - config.old_size
    };

    if rest < young_size {
        CollectionKind::Full
    } else {
        CollectionKind::Minor
    }
}

const MAX_YOUNG_SIZE: usize = 20 * M;

const INIT_HEAP_SIZE_RATIO: usize = 2;
const INIT_YOUNG_RATIO: usize = 4;
const INIT_SEMI_RATIO: usize = 3;

pub fn init(config: &mut HeapConfig, args: &Args) {
    assert!(config.min_heap_size <= config.max_heap_size);

    let young_size = if let Some(young_ratio) = args.flag_gc_young_ratio {
        assert!(young_ratio >= 1);
        align_gen(config.max_heap_size / young_ratio)
    } else {
        let young_size = align_gen(config.max_heap_size / INIT_YOUNG_RATIO);
        min(MAX_YOUNG_SIZE, young_size)
    };
    let young_size = max(young_size, GEN_SIZE);

    let semi_ratio = args.flag_gc_semi_ratio.unwrap_or(INIT_SEMI_RATIO);
    let semi_size = if semi_ratio == 0 {
        0
    } else {
        align_gen(young_size / semi_ratio)
    };
    let semi_size = max(semi_size, GEN_SIZE);
    let eden_size = young_size - semi_size;

    config.eden_size = eden_size;
    config.semi_size = semi_size;

    let max_old_limit = config.max_heap_size - young_size;
    let min_old_limit = if config.min_heap_size > young_size {
        config.min_heap_size - young_size
    } else {
        0
    };

    let old_limit = align_gen(config.max_heap_size / INIT_HEAP_SIZE_RATIO);
    let old_limit = min(old_limit, max_old_limit);
    let old_limit = max(old_limit, min_old_limit);

    config.old_size = 0;
    config.old_limit = old_limit;
}

pub fn start(config: &SharedHeapConfig, young: &YoungGen, old: &OldGen, large: &LargeSpace) {
    let mut config = config.lock();

    config.gc_start = timer::timestamp();
    config.start_object_size = object_size(young, old, large);
    config.start_memory_size = memory_size(young, old, large);
}

pub fn stop(
    config: &SharedHeapConfig,
    kind: CollectionKind,
    young: &YoungGen,
    old: &OldGen,
    large: &LargeSpace,
    verbose: bool,
) {
    let mut config = config.lock();

    let gc_end = timer::timestamp();
    config.gc_duration = timer::in_ms(gc_end - config.gc_start);

    config.end_object_size = object_size(young, old, large);
    config.end_memory_size = memory_size(young, old, large);

    assert!(young.eden_active().empty());
    let (eden_size, semi_size) = young.committed_size();
    let young_size = eden_size + semi_size;

    let old_size = old.committed_size() + large.committed_size();
    config.old_size = old_size;

    let max_old_limit = config.max_heap_size - young_size;
    config.old_limit = max_old_limit;

    match kind {
        CollectionKind::Minor => {
            config.total_minor_collections += 1;
            config.total_minor_pause += config.gc_duration;
        }

        CollectionKind::Full => {
            config.total_full_collections += 1;
            config.total_full_pause += config.gc_duration;
        }
    }

    if verbose {
        print(&*config, kind);
    }
}

fn print(config: &HeapConfig, kind: CollectionKind) {
    match kind {
        CollectionKind::Minor => {
            println!(
                "GC: {} {}/{} -> {}/{}; {:.2} ms; {} promoted; {} copied",
                kind,
                formatted_size(config.start_object_size),
                formatted_size(config.start_memory_size),
                formatted_size(config.end_object_size),
                formatted_size(config.end_memory_size),
                config.gc_duration,
                formatted_size(config.minor_promoted),
                formatted_size(config.minor_copied),
            );
        }

        CollectionKind::Full => {
            println!(
                "GC: {} {}/{} -> {}/{}; {:.2} ms",
                kind,
                formatted_size(config.start_object_size),
                formatted_size(config.start_memory_size),
                formatted_size(config.end_object_size),
                formatted_size(config.end_memory_size),
                config.gc_duration,
            );
        }
    }
}

fn object_size(young: &YoungGen, old: &OldGen, large: &LargeSpace) -> usize {
    young.active_size() + old.active_size() + large.committed_size()
}

fn memory_size(young: &YoungGen, old: &OldGen, large: &LargeSpace) -> usize {
    let (eden_size, semi_size) = young.committed_size();
    let young_size = eden_size + semi_size;

    young_size + old.committed_size() + large.committed_size()
}

pub struct HeapConfig {
    min_heap_size: usize,
    max_heap_size: usize,

    pub eden_size: usize,
    pub semi_size: usize,
    pub old_size: usize,
    pub old_limit: usize,

    gc_start: u64,
    gc_duration: f32,

    start_object_size: usize,
    start_memory_size: usize,
    end_object_size: usize,
    end_memory_size: usize,

    pub minor_promoted: usize,
    pub minor_copied: usize,

    pub total_minor_collections: usize,
    pub total_minor_pause: f32,
    pub total_full_collections: usize,
    pub total_full_pause: f32,
}

impl HeapConfig {
    pub fn new(min_heap_size: usize, max_heap_size: usize) -> HeapConfig {
        assert!(min_heap_size <= max_heap_size);

        HeapConfig {
            min_heap_size: min_heap_size,
            max_heap_size: max_heap_size,

            eden_size: 0,
            semi_size: 0,
            old_size: 0,
            old_limit: 0,

            gc_start: 0,
            gc_duration: 0f32,

            start_object_size: 0,
            start_memory_size: 0,
            end_object_size: 0,
            end_memory_size: 0,

            minor_promoted: 0,
            minor_copied: 0,

            total_minor_collections: 0,
            total_minor_pause: 0f32,
            total_full_collections: 0,
            total_full_pause: 0f32,
        }
    }

    pub fn grow_old(&mut self, size: usize) -> bool {
        if self.old_size + size <= self.old_limit {
            self.old_size += size;
            true
        } else {
            false
        }
    }
}

pub type SharedHeapConfig = Arc<Mutex<HeapConfig>>;
<commit_msg>swiper: guarantee max_heap_size<commit_after>use parking_lot::Mutex;
use std::cmp::{max, min};
use std::sync::Arc;

use driver::cmd::Args;
use gc::swiper::large::LargeSpace;
use gc::swiper::old::OldGen;
use gc::swiper::young::YoungGen;
use gc::swiper::CollectionKind;
use gc::{align_gen, formatted_size, GEN_SIZE, M};
use timer;

pub fn choose_collection_kind(config: &SharedHeapConfig, young: &YoungGen) -> CollectionKind {
    let (eden_size, semi_size) = young.committed_size();
    let young_size = eden_size + semi_size;

    let rest = {
        let config = config.lock();
        config.old_limit - config.old_size
    };

    if rest < young_size {
        CollectionKind::Full
    } else {
        CollectionKind::Minor
    }
}

const MAX_YOUNG_SIZE: usize = 20 * M;

const INIT_HEAP_SIZE_RATIO: usize = 2;
const INIT_YOUNG_RATIO: usize = 4;
const INIT_SEMI_RATIO: usize = 3;

pub fn init(config: &mut HeapConfig, args: &Args) {
    assert!(config.min_heap_size <= config.max_heap_size);

    let young_size = if let Some(young_ratio) = args.flag_gc_young_ratio {
        assert!(young_ratio >= 1);
        align_gen(config.max_heap_size / young_ratio)
    } else {
        let young_size = align_gen(config.max_heap_size / INIT_YOUNG_RATIO);
        min(MAX_YOUNG_SIZE, young_size)
    };
    let young_size = max(young_size, GEN_SIZE);

    let semi_ratio = args.flag_gc_semi_ratio.unwrap_or(INIT_SEMI_RATIO);
    let semi_size = if semi_ratio == 0 {
        0
    } else {
        align_gen(young_size / semi_ratio)
    };
    let semi_size = max(semi_size, GEN_SIZE);
    let eden_size = young_size - semi_size;

    config.eden_size = eden_size;
    config.semi_size = semi_size;

    let max_old_limit = config.max_heap_size - young_size;
    let min_old_limit = if config.min_heap_size > young_size {
        config.min_heap_size - young_size
    } else {
        0
    };

    let old_limit = align_gen(config.max_heap_size / INIT_HEAP_SIZE_RATIO);
    let old_limit = min(old_limit, max_old_limit);
    let old_limit = max(old_limit, min_old_limit);

    config.old_size = 0;
    config.old_limit = old_limit;
}

pub fn start(config: &SharedHeapConfig, young: &YoungGen, old: &OldGen, large: &LargeSpace) {
    let mut config = config.lock();

    config.gc_start = timer::timestamp();
    config.start_object_size = object_size(young, old, large);
    config.start_memory_size = memory_size(young, old, large);
}

pub fn stop(
    config: &SharedHeapConfig,
    kind: CollectionKind,
    young: &YoungGen,
    old: &OldGen,
    large: &LargeSpace,
    verbose: bool,
) {
    let mut config = config.lock();

    let gc_end = timer::timestamp();
    config.gc_duration = timer::in_ms(gc_end - config.gc_start);

    config.end_object_size = object_size(young, old, large);
    config.end_memory_size = memory_size(young, old, large);

    assert!(young.eden_active().empty());
    let (eden_size, semi_size) = young.committed_size();
    let young_size = eden_size + semi_size;

    let old_size = old.committed_size() + large.committed_size();
    config.old_size = old_size;

    let old_limit = config.max_heap_size - young_size;
    let old_limit = max(old_limit, old_size);
    config.old_limit = old_limit;

    assert!(young_size + old_limit <= config.max_heap_size);

    match kind {
        CollectionKind::Minor => {
            config.total_minor_collections += 1;
            config.total_minor_pause += config.gc_duration;
        }

        CollectionKind::Full => {
            config.total_full_collections += 1;
            config.total_full_pause += config.gc_duration;
        }
    }

    if verbose {
        print(&*config, kind);
    }
}

fn print(config: &HeapConfig, kind: CollectionKind) {
    match kind {
        CollectionKind::Minor => {
            println!(
                "GC: {} {}/{} -> {}/{}; {:.2} ms; {} promoted; {} copied",
                kind,
                formatted_size(config.start_object_size),
                formatted_size(config.start_memory_size),
                formatted_size(config.end_object_size),
                formatted_size(config.end_memory_size),
                config.gc_duration,
                formatted_size(config.minor_promoted),
                formatted_size(config.minor_copied),
            );
        }

        CollectionKind::Full => {
            println!(
                "GC: {} {}/{} -> {}/{}; {:.2} ms",
                kind,
                formatted_size(config.start_object_size),
                formatted_size(config.start_memory_size),
                formatted_size(config.end_object_size),
                formatted_size(config.end_memory_size),
                config.gc_duration,
            );
        }
    }
}

fn object_size(young: &YoungGen, old: &OldGen, large: &LargeSpace) -> usize {
    young.active_size() + old.active_size() + large.committed_size()
}

fn memory_size(young: &YoungGen, old: &OldGen, large: &LargeSpace) -> usize {
    let (eden_size, semi_size) = young.committed_size();
    let young_size = eden_size + semi_size;

    young_size + old.committed_size() + large.committed_size()
}

pub struct HeapConfig {
    min_heap_size: usize,
    max_heap_size: usize,

    pub eden_size: usize,
    pub semi_size: usize,
    pub old_size: usize,
    pub old_limit: usize,

    gc_start: u64,
    gc_duration: f32,

    start_object_size: usize,
    start_memory_size: usize,
    end_object_size: usize,
    end_memory_size: usize,

    pub minor_promoted: usize,
    pub minor_copied: usize,

    pub total_minor_collections: usize,
    pub total_minor_pause: f32,
    pub total_full_collections: usize,
    pub total_full_pause: f32,
}

impl HeapConfig {
    pub fn new(min_heap_size: usize, max_heap_size: usize) -> HeapConfig {
        assert!(min_heap_size <= max_heap_size);

        HeapConfig {
            min_heap_size: min_heap_size,
            max_heap_size: max_heap_size,

            eden_size: 0,
            semi_size: 0,
            old_size: 0,
            old_limit: 0,

            gc_start: 0,
            gc_duration: 0f32,

            start_object_size: 0,
            start_memory_size: 0,
            end_object_size: 0,
            end_memory_size: 0,

            minor_promoted: 0,
            minor_copied: 0,

            total_minor_collections: 0,
            total_minor_pause: 0f32,
            total_full_collections: 0,
            total_full_pause: 0f32,
        }
    }

    pub fn grow_old(&mut self, size: usize) -> bool {
        if self.old_size + size <= self.old_limit {
            self.old_size += size;
            true
        } else {
            false
        }
    }
}

pub type SharedHeapConfig = Arc<Mutex<HeapConfig>>;
<|endoftext|>