<commit_before>extern crate crowe;
extern crate rustc_serialize;
use crowe::actor::{Role, Message};
use crowe::actor_system::ActorSystem;
use rustc_serialize::Decodable;
use std::thread;
use std::sync::mpsc::{Sender, Receiver, channel};
use std::fmt::Debug;
use std::thread::sleep;
use std::time::Duration;

#[derive(Debug, RustcDecodable, Clone)]
struct MyMessage {
    content: String
}

impl Message for MyMessage {
    fn content(&self) -> String {
        return self.content.clone();
    }
}

#[derive(Clone)]
struct Russel {
    first_name: String
}

#[derive(Clone)]
struct Joaquin {
    last_name: String
}

impl Role for Russel {
    fn receive<M>(message: M) where M: Send + Decodable + Message {

        fn add_exclamation(content: String) -> String {
            return content + "!"
        }

        let content = message.content();
        let exclamated = add_exclamation(content);
        // sleep(Duration::from_millis(2));

        println!("{:?}", exclamated);
    }

}

impl Role for Joaquin {
    fn receive<M>(message: M) where M: Send + Decodable + Message {

        fn add_exclamation(content: String) -> String {
            return content + "!"
        }

        let content = message.content();
        let exclamated = add_exclamation(content);

        println!("{:?}", exclamated);
    }

}

#[derive(Clone)]
enum Cast {
    Role1(Russel),
    Role2(Joaquin)
}

fn main() {
    // Spawing Actor system with a threadpool of 4
    let mut system = ActorSystem::new(4);

    let actor = Cast::Role1(Russel{first_name: "Russel".to_string()});
    let actor2 = Cast::Role2(Joaquin{last_name: "Russel".to_string()});

    {
        // Spawn as many actors as you want
        let act_ref = &mut system.spawn_actor("Crowe".to_string(), actor);
    }

    {
        // Spawn as many actors as you want
        let act_ref = &mut system.spawn_actor("Joaquin".to_string(), actor2);
    }

    let crowe = system.actor_refs.borrow().get("Crowe").unwrap().clone();
    let joaquin = system.actor_refs.borrow().get("Joaquin").unwrap().clone();

    let message = MyMessage{content: "Are you not entertained?".to_string()};
    let message2 = MyMessage{content: "No, I am not entertained".to_string()};

    let response = crowe.send(Russel::receive, message.clone());
    let response2 = joaquin.send(Joaquin::receive, message2.clone());

}
<commit_msg>latest<commit_after>extern crate crowe;
extern crate rustc_serialize;
use crowe::actor::{Role, Message};
use crowe::actor_system::ActorSystem;
use rustc_serialize::Decodable;
use std::thread;
use std::sync::mpsc::{Sender, Receiver, channel};
use std::fmt::Debug;
use std::thread::sleep;
use std::time::Duration;

#[derive(Debug, RustcDecodable, Clone)]
struct MyMessage {
    content: String
}

impl Message for MyMessage {
    fn content(&self) -> String {
        return self.content.clone();
    }
}

#[derive(Clone)]
struct Russel {
    first_name: String
}

#[derive(Clone)]
struct Joaquin {
    last_name: String
}

impl Role for Russel {
    fn receive<M>(message: M) where M: Send + Decodable + Message {

        fn add_exclamation(content: String) -> String {
            return content + "!"
        }

        let content = message.content();
        let exclamated = add_exclamation(content);
        // sleep(Duration::from_millis(2));

        println!("{:?}", exclamated);
    }

}

impl Role for Joaquin {
    fn receive<M>(message: M) where M: Send + Decodable + Message {

        fn add_exclamation(content: String) -> String {
            return content + "!"
        }

        let content = message.content();
        let exclamated = add_exclamation(content);

        println!("{:?}", exclamated);
    }

}

#[derive(Clone)]
enum Cast {
    Role1(Russel),
    Role2(Joaquin)
}

fn main() {
    // Spawing Actor system with a threadpool of 4
    let mut system = ActorSystem::new(4);

    let actor = Cast::Role1(Russel{first_name: "Russel".to_string()});
    let actor2 = Cast::Role2(Joaquin{last_name: "Russel".to_string()});

    {
        // Spawn as many actors as you want
        let act_ref = &mut system.spawn_actor("Crowe".to_string(), actor);
    }

    {
        // Spawn as many actors as you want
        let act_ref = &mut system.spawn_actor("Joaquin".to_string(), actor2);
    }

    let crowe = system.actor_refs.borrow().get("Crowe").unwrap().clone();
    let joaquin = system.actor_refs.borrow().get("Joaquin").unwrap().clone();

    let message = MyMessage{content: "Are you not entertained?".to_string()};
    let message2 = MyMessage{content: "No, I am not entertained".to_string()};

    let response = crowe.send(Russel::receive, message.clone());
    let response2 = joaquin.send(Joaquin::receive, message2.clone());

}
<|endoftext|>


<commit_before>use std::ops::{Add, Sub, Mul, Div};

fn do_operation<F, V>(f: F, v1: V, v2: V) -> V
    where
        F: Fn(V, V) -> V,
        V: Add + Sub + Mul + Div {
    f(v1, v2)
}

pub fn rpn(raw: &str) -> f64 {
    let mut stack = Vec::new();

    for c in raw.split(' ') {
        if let Some(i) = c.parse::<f64>().ok() {
            stack.push(i);
            continue;
        }

        let msg = "Invalid equation. No numbers left in stack for the left side of the operation";
        let r = stack.pop().expect(msg);
        let l = stack.pop().expect(msg);

        let result = match c {
            "+" => do_operation(|l, r| l + r, l, r),
            "-" => do_operation(|l, r| l - r, l, r),
            "*" => do_operation(|l, r| l * r, l, r),
            "/" =>
            {
                if r == 0.0
                {
                    panic!("Division by zero not allowed");
                }

                do_operation(|l, r| l / r, l, r)
            },
            _ => panic!("Unknown character {:?}", c),
        };

        stack.push(result);
    }

    if stack.len() != 1
    {
        panic!("Invalid equation. Wrong number of elements left in stack. Expected left: 1, actual: {:?}", stack.len());
    }

    stack.pop().unwrap()
}

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

    #[test]
    fn basic_integer() {
        assert_eq!(0.25, rpn("14 4 6 8 + * /"));
        assert_eq!(14.0, rpn("5 1 2 + 4 * + 3 -"));
        assert_eq!(0.5, rpn("5 4 6 + /"));
        assert_eq!(2.0, rpn("2 5 * 4 + 3 2 * 1 + /"));
    }

    #[test]
    fn basic_floating_point() {
        assert_eq!(20.04, rpn("5.5 1.3 2.3 + 4.9 * + 3.1 -"));
        assert_eq!(11.25, rpn("1.5 3.0 4.5 + *"));
    }

    #[test]
    fn negative() {
        assert_eq!(-2503.0, rpn("-4 -9 -33 -76 * + -"));
        assert_eq!(2653660.0, rpn("-56 -34 + -54 * 43 23 54 + * -800 * -"));
    }

    #[test]
    #[should_panic]
    fn divide_by_zero() {
        assert_eq!(-2503.0, rpn("2 0 /"));
    }

    #[test]
    fn long_equation() {
        let mut eq = "2 ".to_string();
        for _ in 0..2000000 {
            eq.push_str("2 + ");
        }

        eq.push_str("1 +");

        assert_eq!(4000003.0, rpn(&eq));
    }
}<commit_msg>Add invalid input tests<commit_after>use std::ops::{Add, Sub, Mul, Div};

fn do_operation<F, V>(f: F, v1: V, v2: V) -> V
    where
        F: Fn(V, V) -> V,
        V: Add + Sub + Mul + Div {
    f(v1, v2)
}

pub fn rpn(raw: &str) -> f64 {
    let mut stack = Vec::new();

    for c in raw.split(' ') {
        if let Some(i) = c.parse::<f64>().ok() {
            stack.push(i);
            continue;
        }

        let msg = "Invalid equation. No numbers left in stack for the left side of the operation";
        let r = stack.pop().expect(msg);
        let l = stack.pop().expect(msg);

        let result = match c {
            "+" => do_operation(|l, r| l + r, l, r),
            "-" => do_operation(|l, r| l - r, l, r),
            "*" => do_operation(|l, r| l * r, l, r),
            "/" =>
            {
                if r == 0.0
                {
                    panic!("Division by zero not allowed");
                }

                do_operation(|l, r| l / r, l, r)
            },
            _ => panic!("Unknown character {:?}", c),
        };

        stack.push(result);
    }

    if stack.len() != 1
    {
        panic!("Invalid equation. Wrong number of elements left in stack. Expected left: 1, actual: {:?}", stack.len());
    }

    stack.pop().unwrap()
}

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

    #[test]
    fn basic_integer() {
        assert_eq!(0.25, rpn("14 4 6 8 + * /"));
        assert_eq!(14.0, rpn("5 1 2 + 4 * + 3 -"));
        assert_eq!(0.5, rpn("5 4 6 + /"));
        assert_eq!(2.0, rpn("2 5 * 4 + 3 2 * 1 + /"));
    }

    #[test]
    fn basic_floating_point() {
        assert_eq!(20.04, rpn("5.5 1.3 2.3 + 4.9 * + 3.1 -"));
        assert_eq!(11.25, rpn("1.5 3.0 4.5 + *"));
    }

    #[test]
    fn negative() {
        assert_eq!(-2503.0, rpn("-4 -9 -33 -76 * + -"));
        assert_eq!(2653660.0, rpn("-56 -34 + -54 * 43 23 54 + * -800 * -"));
    }

    #[test]
    #[should_panic]
    fn divide_by_zero() {
        assert_eq!(-2503.0, rpn("2 0 /"));
    }

    #[test]
    #[should_panic]
    fn invalid_input_1() {
        rpn("");
    }

    #[test]
    #[should_panic]
    fn invalid_input_2() {
        rpn("14 4 6 8 + . /");
    }

    #[test]
    #[should_panic]
    fn invalid_input_3() {
        rpn("POTATO");
    }

    #[test]
    #[should_panic]
    fn invalid_input_4() {
        rpn("54 4 6 O + \\ /");
    }

    #[test]
    fn long_equation() {
        let mut eq = "2 ".to_string();
        for _ in 0..2000000 {
            eq.push_str("2 + ");
        }

        eq.push_str("1 +");

        assert_eq!(4000003.0, rpn(&eq));
    }
}<|endoftext|>


<commit_before>extern crate nix;
extern crate libc;
extern crate docopt;
extern crate cargo;
extern crate rustc_serialize;

use std::ffi::CString;
use docopt::Docopt;
use std::path::{Path, PathBuf};
use rustc_serialize::json::Json;
use nix::sys::signal::*;
use nix::unistd::*;
use cargo::util::Config;
use cargo::core::Workspace;
use cargo::ops;

const USAGE: &'static str = "
Tarpaulin - a cargo code coverage tool

Usage:
    cargo-tarpaulin [options]
    cargo-tarpaulin (-h | --help)

Options:
    -h, --help                  Show this message.
    -l, --line                  Collect line coverage.
    -b, --branch                Collect branch coverage.
    -c, --condition             Collect condition coverage.
    --out ARG                   Specify output type [default: Report].
    -v, --verbose               Show extra output.
    -m ARG, --manifest ARG      Path to a cargo.toml to execute tarpaulin on.
                                Default is current directory

";

#[derive(RustcDecodable, Debug)]
enum Out {
    Json,
    Toml,
    Report
}

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_line: bool,
    flag_branch: bool,
    flag_condition:bool,
    flag_verbose: bool,
    flag_out: Option<Out>,
    flag_manifest: Option<String>,
}

fn main() {
    let args:Args = Docopt::new(USAGE)
                           .and_then(|d| d.decode())
                           .unwrap_or_else(|e| e.exit());

    let mut path = std::env::current_dir().unwrap();

    if let Some(p) = args.flag_manifest {
        path.push(p);
    };
    path.push("Cargo.toml");

    let config = Config::default().unwrap();
    let workspace =match  Workspace::new(path.as_path(), &config) {
        Ok(w) => w,
        Err(_) => panic!("Invalid project directory specified"),
    };

    let filter = ops::CompileFilter::Everything;

    let copt = ops::CompileOptions {
        config: &config,
        jobs: None,
        target: None,
        features: &[],
        all_features: true,
        no_default_features:false ,
        spec: ops::Packages::All,
        release: false,
        mode: ops::CompileMode::Test,
        filter: filter,
        message_format: ops::MessageFormat::Human,
        target_rustdoc_args: None,
        target_rustc_args: None,
    };
    // Do I need to clean beforehand?
    if let Ok(comp) = ops::compile(&workspace, &copt) {

        for c in comp.tests.iter() {
            analyse_coverage(c.2.as_path());
        }
    }
}

fn analyse_coverage(test: &Path) {
    let mut executable = test.to_str()
                             .unwrap()
                             .as_bytes()
                             .to_vec();
    executable.insert(0, '.' as u8);
    let exec_path = &CString::new(executable).unwrap();
    execve(exec_path, &[], &[]);
}
<commit_msg>Implemented more of test running.<commit_after>extern crate nix;
extern crate docopt;
extern crate cargo;
extern crate rustc_serialize;

use std::ffi::CString;
use docopt::Docopt;
use std::path::Path;
use nix::sys::signal;
use nix::unistd::*;
use nix::libc::pid_t;
use nix::sys::wait::*;
use nix::sys::ptrace::*;
use nix::sys::ptrace::ptrace::*;
use cargo::util::Config;
use cargo::core::Workspace;
use cargo::ops;
use std::ptr;

const USAGE: &'static str = "
Tarpaulin - a cargo code coverage tool

Usage:
    cargo-tarpaulin [options]
    cargo-tarpaulin (-h | --help)

Options:
    -h, --help                  Show this message.
    -l, --line                  Collect line coverage.
    -b, --branch                Collect branch coverage.
    -c, --condition             Collect condition coverage.
    --out ARG                   Specify output type [default: Report].
    -v, --verbose               Show extra output.
    -m ARG, --manifest ARG      Path to a cargo.toml to execute tarpaulin on.
                                Default is current directory

";

#[derive(RustcDecodable, Debug)]
enum Out {
    Json,
    Toml,
    Report
}

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_line: bool,
    flag_branch: bool,
    flag_condition:bool,
    flag_verbose: bool,
    flag_out: Option<Out>,
    flag_manifest: Option<String>,
}

fn main() {
    let args:Args = Docopt::new(USAGE)
                           .and_then(|d| d.decode())
                           .unwrap_or_else(|e| e.exit());

    let mut path = std::env::current_dir().unwrap();

    if let Some(p) = args.flag_manifest {
        path.push(p);
    };
    path.push("Cargo.toml");

    let config = Config::default().unwrap();
    let workspace =match  Workspace::new(path.as_path(), &config) {
        Ok(w) => w,
        Err(_) => panic!("Invalid project directory specified"),
    };

    let filter = ops::CompileFilter::Everything;

    let copt = ops::CompileOptions {
        config: &config,
        jobs: None,
        target: None,
        features: &[],
        all_features: true,
        no_default_features:false ,
        spec: ops::Packages::All,
        release: false,
        mode: ops::CompileMode::Test,
        filter: filter,
        message_format: ops::MessageFormat::Human,
        target_rustdoc_args: None,
        target_rustc_args: None,
    };
    // Do I need to clean beforehand?
    if let Ok(comp) = ops::compile(&workspace, &copt) {

        for c in comp.tests.iter() {
            match fork() {
                Ok(ForkResult::Parent{ child }) => {
                    println!("Parent. Child pid = {}", child);
                    collect_coverage(child);
                }
                Ok(ForkResult::Child) => {
                    println!("Child");
                    execute_test(c.2.as_path(), true);
                }
                Err(err) => {
                    println!("Failed to run {}", c.2.display());
                    println!("Error {}", err);
                }
            }
        }
    }
}

fn collect_coverage(test: pid_t) {

    match waitpid(test, None) {
        Ok(WaitStatus::Stopped(child, signal::SIGTRAP)) => {
            println!("Got her, continuing run");
            ptrace(PTRACE_CONT, child, ptr::null_mut(), ptr::null_mut())
                .ok()
                .expect("Failed to continue test");
        }
        Ok(_) => {
            println!("Unexpected grab");
        }
        Err(err) => println!("{}", err)
    }
}

fn execute_test(test: &Path, backtrace_on: bool) {

    let exec_path = &CString::new(test.to_str().unwrap()).unwrap();

    ptrace(PTRACE_TRACEME, 0, ptr::null_mut(), ptr::null_mut())
        .ok()
        .expect("Failed to trace");

    let envars: Vec<CString> = if backtrace_on {
        vec![CString::new("RUST_BACKTRACE=1").unwrap()]
    } else {
        vec![]
    };
    execve(exec_path, &[], envars.as_slice())
        .unwrap();
}
<|endoftext|>


<commit_before>extern crate iron;
#[macro_use]
extern crate router;
extern crate logger;
extern crate rustc_serialize;
extern crate walkdir;
#[macro_use]
extern crate horrorshow;
#[macro_use]
extern crate mopa;
extern crate docopt;

mod scripts;
mod mainpage_generator;
mod handlers;
mod constants;

use iron::prelude::*;
use iron::status;
use iron::mime::Mime;
use router::Router;
use logger::Logger;

use walkdir::WalkDir;

use docopt::Docopt;

use std::env;
use std::io;
use std::thread;
use std::time::Duration;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
use rustc_serialize::json;
use std::str::FromStr;

use scripts::Script;
use mainpage_generator::MainPageHtml;

static DEFAULT_SERVER_HOSTNAME: &'static str = "localhost:3000";

#[cfg_attr(rustfmt, rustfmt_skip)]
const USAGE: &'static str = "
Articulator
A small server program that can run arbitrary scripts on the hosting server.

Usage:
    articulator.exe [<hostname>]
    articulator.exe (-h | --help)

Options:
    hostname        (Optional) An IPv4-compatible hostname string.
    -h --help       Show this screen.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_hostname: Option<String>,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| {
                             println!("Invalid input. Terminating.");
                             e.exit();
                         });

    println!("Args: {:?}", args);
    let hostname = match args.arg_hostname {
        Some(name) => name,
        None => String::from(DEFAULT_SERVER_HOSTNAME),
    };

    let (logger_before, logger_after) = Logger::new(None);
    let router = router!(get "/" => show_mainpage_handler,
                         get "/scr" => show_scripts_handler,
                         get "/scr/:scriptName" => script_handler);

    let mut chain = Chain::new(router);

    chain.link_after(logger_after); //this seems incredibly prone to breaking for no good reason
    chain.link_before(logger_before);

    Iron::new(chain).http(hostname.as_str()).unwrap();
}

fn show_mainpage_handler(_: &mut Request) -> IronResult<Response> {
    if let Ok(scripts) = get_script_list() {
        let mainpage = MainPageHtml::new(scripts);
        let content_type = "text/html".parse::<Mime>().unwrap();
        return Ok(Response::with((content_type, status::Ok, mainpage.html_string)));
    } else {
        script_error_handler()
    }
}

fn show_scripts_handler(_: &mut Request) -> IronResult<Response> {
    println!("Getting scripts...");
    if let Ok(scripts) = get_script_list() {
        let scripts = json::encode(&scripts).unwrap();
        Ok(Response::with((status::Ok, scripts)))
    } else {
        script_error_handler()
    }
}

fn script_handler(req: &mut Request) -> IronResult<Response> {
    let ref query = req.extensions.get::<Router>().unwrap().find("scriptName").unwrap_or("/");
    let script = get_script(query);
    if script.is_err() {
        return script_error_handler();
    }
    let script = script.unwrap();
    let script_path = script.get_full_path();

    match script_path {
        Ok(path) => {
            if path.to_string_lossy().contains(constants::IMMEDIATE_RET_PATH) {
                run_early_return_script(script)
            } else {
                script.run()
            }
        }
        Err(_) => {
            println!("Could not find script.");
            script_error_handler()
        }
    }
}

fn run_early_return_script(script: Box<Script>) -> IronResult<Response> {
    thread::spawn(move || {
        thread::sleep(Duration::from_millis(500));
        script.run().ok();
    });
    Ok(Response::with((status::Ok, "Attempted to kick off early-return script.")))
}

fn script_error_handler() -> IronResult<Response> {
    Ok(Response::with(status::InternalServerError))
}

fn get_script_folder() -> io::Result<PathBuf> {
    let current_exe = try!(env::current_exe());
    match current_exe.parent() {
        Some(parent_dir) => Ok(parent_dir.join("scripts")),
        None => Err(io::Error::new(io::ErrorKind::NotFound, "Unable to find scripts folder.")),
    }
}

// todo: fix unwrap infestation in here
fn get_script_list() -> io::Result<Vec<Box<Script>>> {
    let folder = try!(get_script_folder());
    let paths = WalkDir::new(&folder);

    let mut scripts = Vec::new();
    for p in paths {
        let p: walkdir::DirEntry = p.unwrap();
        if !p.file_type().is_file() {
            continue;
        };
        let split_str = String::from(p.file_name().to_str().unwrap());
        let split_str: Vec<&str> = split_str.split('.').collect();
        let name = *split_str.first().unwrap();

        let mut path = PathBuf::new();
        path.push(p.path());
        let path_root = Path::new(path.strip_prefix(folder.as_path().parent().unwrap())
                                      .unwrap());
        let rel_path = String::from(path_root.to_str().unwrap()).replace("\\", "/");

        let path_ext = p.path()
                        .extension()
                        .unwrap_or_else(|| OsStr::new(""))
                        .to_str()
                        .unwrap_or_else(|| "");
        if let Some(boxed_script) = scripts::construct_script(String::from_str(name).unwrap(),
                                                              String::from(rel_path),
                                                              String::from(path_ext)) {
            scripts.push(boxed_script);
        } else {
            return Err(io::Error::new(io::ErrorKind::InvalidInput,
                                      format!("Unable to determine file type for script {:?}",
                                              p.path())));
        }
    }
    return Ok(scripts);
}

fn get_script(name: &str) -> io::Result<Box<Script>> {
    let script_list: Vec<Box<Script>> = try!(get_script_list());
    if let Some(script) = script_list.into_iter().find(|s| s.get_name() == name) {
        Ok(script)
    } else {
        Err(io::Error::new(io::ErrorKind::NotFound,
                           format!("Script with name {} not found.", name)))
    }
}
<commit_msg>Add startup message to show hostname we're binding to<commit_after>extern crate iron;
#[macro_use]
extern crate router;
extern crate logger;
extern crate rustc_serialize;
extern crate walkdir;
#[macro_use]
extern crate horrorshow;
#[macro_use]
extern crate mopa;
extern crate docopt;

mod scripts;
mod mainpage_generator;
mod handlers;
mod constants;

use iron::prelude::*;
use iron::status;
use iron::mime::Mime;
use router::Router;
use logger::Logger;

use walkdir::WalkDir;

use docopt::Docopt;

use std::env;
use std::io;
use std::thread;
use std::time::Duration;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
use rustc_serialize::json;
use std::str::FromStr;

use scripts::Script;
use mainpage_generator::MainPageHtml;

static DEFAULT_SERVER_HOSTNAME: &'static str = "localhost:3000";

#[cfg_attr(rustfmt, rustfmt_skip)]
const USAGE: &'static str = "
Articulator
A small server program that can run arbitrary scripts on the hosting server.

Usage:
    articulator.exe [<hostname>]
    articulator.exe (-h | --help)

Options:
    hostname        (Optional) An IPv4-compatible hostname string.
    -h --help       Show this screen.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_hostname: Option<String>,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| {
                             println!("Invalid input. Terminating.");
                             e.exit();
                         });

    let hostname = match args.arg_hostname {
        Some(name) => {
            println!("Staring server on {}", &name);
            name
        }
        None => {
            println!("Starting server on {}", &DEFAULT_SERVER_HOSTNAME);
            String::from(DEFAULT_SERVER_HOSTNAME)
        }
    };

    let (logger_before, logger_after) = Logger::new(None);
    let router = router!(get "/" => show_mainpage_handler,
                         get "/scr" => show_scripts_handler,
                         get "/scr/:scriptName" => script_handler);

    let mut chain = Chain::new(router);

    chain.link_after(logger_after); //this seems incredibly prone to breaking for no good reason
    chain.link_before(logger_before);

    Iron::new(chain).http(hostname.as_str()).unwrap();
}

fn show_mainpage_handler(_: &mut Request) -> IronResult<Response> {
    if let Ok(scripts) = get_script_list() {
        let mainpage = MainPageHtml::new(scripts);
        let content_type = "text/html".parse::<Mime>().unwrap();
        return Ok(Response::with((content_type, status::Ok, mainpage.html_string)));
    } else {
        script_error_handler()
    }
}

fn show_scripts_handler(_: &mut Request) -> IronResult<Response> {
    println!("Getting scripts...");
    if let Ok(scripts) = get_script_list() {
        let scripts = json::encode(&scripts).unwrap();
        Ok(Response::with((status::Ok, scripts)))
    } else {
        script_error_handler()
    }
}

fn script_handler(req: &mut Request) -> IronResult<Response> {
    let ref query = req.extensions.get::<Router>().unwrap().find("scriptName").unwrap_or("/");
    let script = get_script(query);
    if script.is_err() {
        return script_error_handler();
    }
    let script = script.unwrap();
    let script_path = script.get_full_path();

    match script_path {
        Ok(path) => {
            if path.to_string_lossy().contains(constants::IMMEDIATE_RET_PATH) {
                run_early_return_script(script)
            } else {
                script.run()
            }
        }
        Err(_) => {
            println!("Could not find script.");
            script_error_handler()
        }
    }
}

fn run_early_return_script(script: Box<Script>) -> IronResult<Response> {
    thread::spawn(move || {
        thread::sleep(Duration::from_millis(500));
        script.run().ok();
    });
    Ok(Response::with((status::Ok, "Attempted to kick off early-return script.")))
}

fn script_error_handler() -> IronResult<Response> {
    Ok(Response::with(status::InternalServerError))
}

fn get_script_folder() -> io::Result<PathBuf> {
    let current_exe = try!(env::current_exe());
    match current_exe.parent() {
        Some(parent_dir) => Ok(parent_dir.join("scripts")),
        None => Err(io::Error::new(io::ErrorKind::NotFound, "Unable to find scripts folder.")),
    }
}

// todo: fix unwrap infestation in here
fn get_script_list() -> io::Result<Vec<Box<Script>>> {
    let folder = try!(get_script_folder());
    let paths = WalkDir::new(&folder);

    let mut scripts = Vec::new();
    for p in paths {
        let p: walkdir::DirEntry = p.unwrap();
        if !p.file_type().is_file() {
            continue;
        };
        let split_str = String::from(p.file_name().to_str().unwrap());
        let split_str: Vec<&str> = split_str.split('.').collect();
        let name = *split_str.first().unwrap();

        let mut path = PathBuf::new();
        path.push(p.path());
        let path_root = Path::new(path.strip_prefix(folder.as_path().parent().unwrap())
                                      .unwrap());
        let rel_path = String::from(path_root.to_str().unwrap()).replace("\\", "/");

        let path_ext = p.path()
                        .extension()
                        .unwrap_or_else(|| OsStr::new(""))
                        .to_str()
                        .unwrap_or_else(|| "");
        if let Some(boxed_script) = scripts::construct_script(String::from_str(name).unwrap(),
                                                              String::from(rel_path),
                                                              String::from(path_ext)) {
            scripts.push(boxed_script);
        } else {
            return Err(io::Error::new(io::ErrorKind::InvalidInput,
                                      format!("Unable to determine file type for script {:?}",
                                              p.path())));
        }
    }
    return Ok(scripts);
}

fn get_script(name: &str) -> io::Result<Box<Script>> {
    let script_list: Vec<Box<Script>> = try!(get_script_list());
    if let Some(script) = script_list.into_iter().find(|s| s.get_name() == name) {
        Ok(script)
    } else {
        Err(io::Error::new(io::ErrorKind::NotFound,
                           format!("Script with name {} not found.", name)))
    }
}
<|endoftext|>


<commit_before>use name::*;
use art::*;

/// Nominal, artful lists: Lists with names and articulation points
#[deriving(Show,Hash,PartialEq,Eq)]
pub enum List<'x,T> {
    Nil,
    Cons(T, Box<List<'x,T>>),
    Name(Name, Box<List<'x,T>>),
    Art(Art<'x, Box<List<'x,T>>>)
}

pub fn copy<'x,T:'x>(list:List<'x,T>) -> List<'x,T> {
    match list {
        List::Nil         => List::Nil,
        List::Cons(hd,tl) => List::Cons(hd, box copy(*tl)),
        List::Art(art)    => copy(*force(art)),
        List::Name(nm,tl) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box copy(*tl)) ;
            List::Name(nm2, box List::Art(art))
        }
    }
}

pub fn map<'x,T:'x,S:'x,F> (f:&'static F, list:List<'x,T>) -> List<'x,S>
where F:Fn(T) -> S
{
    match list {
        List::Nil         => List::Nil,
        List::Cons(hd,tl) => List::Cons((*f)(hd), box map(f,*tl)),
        // - - - - - boilerplate cases - - - - - -
        List::Art(art)    => map(f,*force(art)),
        List::Name(nm,tl) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box map(f,*tl)) ;
            List::Name(nm2, box List::Art(art))
        }
    }
}

pub fn contract<'x,F,G,T:'x> (f:&'static F, g:&'static G, list:List<'x,T>) -> List<'x,T>
where F:Fn(&T,&T) -> bool,
      G:Fn(T,T) -> T
{
    match list {
        List::Nil => List::Nil,
        List::Cons(hd1, box list) => {
            match list {
                List::Nil => List::Cons(hd1, box List::Nil),
                List::Cons(hd2, tl) => {
                    if (*f)(&hd1,&hd2) {
                        List::Cons((*g)(hd1,hd2), box contract(f,g,*tl))
                    } else {
                        List::Cons(hd1, box contract(f, g, List::Cons(hd2, tl)))
                    } },
                // - - - - - boilerplate cases - - - - - -
                List::Art(art) => contract(f,g,List::Cons(hd1,force(art))),
                List::Name(nm, tl) => {
                    let (nm1,nm2) = fork(nm) ;
                    let art = nart!(nm1, box contract(f,g,List::Cons(hd1,tl))) ;
                    List::Name(nm2, box List::Art(art))
                }
            }
        },
        // - - - - - boilerplate cases - - - - - -
        List::Art(art)    => contract(f,g,*force(art)),
        List::Name(nm,tl) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box contract(f,g,*tl)) ;
            List::Name(nm2, box List::Art(art))
        },
    }
}

pub fn reduce<'x,F,G,T:'x> (f:&'static F, g:&'static G, list:List<'x,T>) -> Option<T>
where F: Fn(&T,&T) -> bool + 'static,
      G: Fn(T, T) -> T + 'static
{
    match list {
        List::Nil => None,
        List::Cons(hd, box list) => {
            match list {
                List::Nil => Some(hd),
                List::Cons(hd2, tl) => {
                    let hd3 = (*g)(hd,hd2) ;
                    let list = contract(f, g, List::Cons(hd3, tl)) ;
                    reduce (f, g, list)
                },
                // - - - - - boilerplate cases - - - - - -
                List::Name(_,tl) => reduce (f, g, *tl),
                List::Art(art)   => reduce (f, g, *force(art)),
            }},
        // - - - - - boilerplate cases - - - - - -
        List::Name(_,tl) => reduce(f, g, *tl),
        List::Art(art)   => reduce(f, g, *force(art)),
    }
}

pub fn merge<'x,T:'x,Ord> (ord:Ord, list1:List<'x,T>, list2:List<'x,T>) -> List<'x,T>
where Ord: Fn(&T,&T) -> bool + 'static
{
    match (list1, list2) {
        (List::Nil, list2) => list2,
        (list1, List::Nil) => list1,
        (List::Cons(hd1,tl1),
         List::Cons(hd2,tl2)) =>
            if ord(&hd1,&hd2) {
                List::Cons(hd1, box merge(ord, *tl1, List::Cons(hd2,tl2)))
            } else {
                List::Cons(hd2, box merge(ord, List::Cons(hd1,tl1), *tl2))
            },
        // - - - - - boilerplate cases - - - - -
        (List::Name(nm,tl), list2) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box merge(ord, *tl, list2)) ;
            List::Name(nm2, box List::Art(art))
        },
        (list1, List::Name(nm,tl)) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box merge(ord, list1, *tl)) ;
            List::Name(nm2, box List::Art(art))
        },
        (List::Art(art), list2) => merge(ord, *force(art), list2),
        (list1, List::Art(art)) => merge(ord, list1, *force(art)),
    }
}

pub fn singletons<'x,T:'x> (list:List<'x,T>) -> List<'x,List<'x,T>>
{
    match list {
        List::Nil => List::Nil,
        List::Cons(hd, tl) => {
            List::Cons( List::Cons(hd, box List::Nil),
                        box singletons(*tl) )
        },
        List::Art(art) => singletons(*force(art)),
        List::Name(nm, tl) => {
            let (nm1, nm2) = fork(nm) ;
            let art = nart!(nm2, box singletons(*tl)) ;
            List::Name(nm1, box List::Art(art))
        }
    }
}

// pub fn mergesort<'x,F,G,T:'x> (ord:&'static Ord, list:List<'x,T>) -> List<'x,T>
//     where Ord: Fn(&List<T>, &List<T>) -> bool + 'x,
// {
//     let c = |list1:List<T>,list2:List<T>| false ; // TODO
//     let m = |list1:List<T>,list2:List<T>| merge(ord,list1,list2) ;
//     let r = reduce(&c, &m, singletons(list)) ;
//     match r {
//         None => List::Nil,
//         Some(list) => list
//     }
// }

#[test]
pub fn construct_list () {
    let z : List<int> = List::Nil;
    let y : List<int> = List::Cons(1, box z);
    let x : List<int> = List::Art(cell(symbol(format!("two")), box y));
    let l : List<int> = List::Name(symbol(format!("one")), box x);
    println!("constructed list: {}", l);
}

// impl<T> List<T> {
//     /// Construct a new, empty list.
//     #[inline]
//     pub fn new() -> List<T> { Nil }
// }

// impl<T: Send + Sync> List<T> {
//     /// Create a list with one element in it.
//     #[inline]
//     pub fn singleton(n:Name,val: T) -> List<T> { Cons(val, Art::new(Nil)) }

//     /// Get the head of a list.
//     pub fn head(&self) -> Option<&T> {
//         match *self {
//             Nil => None,
//             Cons(ref head, _) => Some(head)
//         }
//     }

//     /// Get the tail of a list.
//     pub fn tail(&self) -> Option<Art<List<T>>> {
//         match *self {
//             Nil => None,
//             Cons(_, ref tail) => Some(tail.clone())
//         }
//     }

//     /// Get an iterator over the items in a list.
//     pub fn iter<'a>(&'a self) -> ListItems<'a, T> {
//         ListItems {
//             list: self
//         }
//     }
// }

// /// An iterator over the items in a list.
// pub struct ListItems<'a, T: 'a> {
//     list: &'a List<T>
// }

// impl<'a, T: Send + Sync> Iterator<&'a T> for ListItems<'a, T> {
//     fn next(&mut self) -> Option<&'a T> {
//         match *self.list {
//             Cons(ref head, ref tail) => {
//                 self.list = &**tail;
//                 Some(head)
//             },
//             Nil => None
//         }
//     }
// }

<commit_msg>dropping uses of 'static<commit_after>use name::*;
use art::*;

/// Nominal, artful lists: Lists with names and articulation points
#[deriving(Show,Hash,PartialEq,Eq)]
pub enum List<'x,T> {
    Nil,
    Cons(T, Box<List<'x,T>>),
    Name(Name, Box<List<'x,T>>),
    Art(Art<'x, Box<List<'x,T>>>)
}

pub fn copy<'x,T:'x>(list:List<'x,T>) -> List<'x,T> {
    match list {
        List::Nil         => List::Nil,
        List::Cons(hd,tl) => List::Cons(hd, box copy(*tl)),
        List::Art(art)    => copy(*force(art)),
        List::Name(nm,tl) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box copy(*tl)) ;
            List::Name(nm2, box List::Art(art))
        }
    }
}

pub fn map<'x,T:'x,S:'x,F> (f:&'static F, list:List<'x,T>) -> List<'x,S>
where F:Fn(T) -> S
{
    match list {
        List::Nil         => List::Nil,
        List::Cons(hd,tl) => List::Cons((*f)(hd), box map(f,*tl)),
        // - - - - - boilerplate cases - - - - - -
        List::Art(art)    => map(f,*force(art)),
        List::Name(nm,tl) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box map(f,*tl)) ;
            List::Name(nm2, box List::Art(art))
        }
    }
}

pub fn contract<'x,F,G,T:'x> (f:&'x F, g:&'x G, list:List<'x,T>) -> List<'x,T>
where F:Fn(&T,&T) -> bool + 'x,
      G:Fn(T,T) -> T + 'x
{
    match list {
        List::Nil => List::Nil,
        List::Cons(hd1, box list) => {
            match list {
                List::Nil => List::Cons(hd1, box List::Nil),
                List::Cons(hd2, tl) => {
                    if (*f)(&hd1,&hd2) {
                        List::Cons((*g)(hd1,hd2), box contract(f,g,*tl))
                    } else {
                        List::Cons(hd1, box contract(f, g, List::Cons(hd2, tl)))
                    } },
                // - - - - - boilerplate cases - - - - - -
                List::Art(art) => contract(f,g,List::Cons(hd1,force(art))),
                List::Name(nm, tl) => {
                    let (nm1,nm2) = fork(nm) ;
                    let art = nart!(nm1, box contract(f,g,List::Cons(hd1,tl))) ;
                    List::Name(nm2, box List::Art(art))
                }
            }
        },
        // - - - - - boilerplate cases - - - - - -
        List::Art(art)    => contract(f,g,*force(art)),
        List::Name(nm,tl) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box contract(f,g,*tl)) ;
            List::Name(nm2, box List::Art(art))
        },
    }
}

pub fn reduce<'x,F:'x,G:'x,T:'x> (f:&'x F, g:&'x G, list:List<'x,T>) -> Option<T>
where F: Fn(&T,&T) -> bool,
      G: Fn(T, T) -> T,
{
    match list {
        List::Nil => None,
        List::Cons(hd, box list) => {
            match list {
                List::Nil => Some(hd),
                List::Cons(hd2, tl) => {
                    let hd3 = (*g)(hd,hd2) ;
                    let list = contract(f, g, List::Cons(hd3, tl)) ;
                    reduce (f, g, list)
                },
                // - - - - - boilerplate cases - - - - - -
                List::Name(_,tl) => reduce (f, g, *tl),
                List::Art(art)   => reduce (f, g, *force(art)),
            }},
        // - - - - - boilerplate cases - - - - - -
        List::Name(_,tl) => reduce(f, g, *tl),
        List::Art(art)   => reduce(f, g, *force(art)),
    }
}

pub fn merge<'x,T:'x,Ord:'x> (ord:Ord, list1:List<'x,T>, list2:List<'x,T>) -> List<'x,T>
where Ord: Fn(&T,&T) -> bool
{
    match (list1, list2) {
        (List::Nil, list2) => list2,
        (list1, List::Nil) => list1,
        (List::Cons(hd1,tl1),
         List::Cons(hd2,tl2)) =>
            if ord(&hd1,&hd2) {
                List::Cons(hd1, box merge(ord, *tl1, List::Cons(hd2,tl2)))
            } else {
                List::Cons(hd2, box merge(ord, List::Cons(hd1,tl1), *tl2))
            },
        // - - - - - boilerplate cases - - - - -
        (List::Name(nm,tl), list2) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box merge(ord, *tl, list2)) ;
            List::Name(nm2, box List::Art(art))
        },
        (list1, List::Name(nm,tl)) => {
            let (nm1,nm2) = fork(nm) ;
            let art = nart!(nm1, box merge(ord, list1, *tl)) ;
            List::Name(nm2, box List::Art(art))
        },
        (List::Art(art), list2) => merge(ord, *force(art), list2),
        (list1, List::Art(art)) => merge(ord, list1, *force(art)),
    }
}

pub fn singletons<'x,T:'x> (list:List<'x,T>) -> List<'x,List<'x,T>>
{
    match list {
        List::Nil => List::Nil,
        List::Cons(hd, tl) => {
            List::Cons( List::Cons(hd, box List::Nil),
                        box singletons(*tl) )
        },
        List::Art(art) => singletons(*force(art)),
        List::Name(nm, tl) => {
            let (nm1, nm2) = fork(nm) ;
            let art = nart!(nm2, box singletons(*tl)) ;
            List::Name(nm1, box List::Art(art))
        }
    }
}

pub fn mergesort<'x,F,G,T:'x,Ord:'x> (ord:Ord, list:List<'x,T>) -> List<'x,T>
where Ord: Fn(&T,&T) -> bool
{
    panic!("not implemented")

//     let c = |list1:List<T>,list2:List<T>| false ; // TODO
//     let m = |list1:List<T>,list2:List<T>| merge(ord,list1,list2) ;
//     let r = reduce(&c, &m, singletons(list)) ;
//     match r {
//         None => List::Nil,
//         Some(list) => list
//     }
}

#[test]
pub fn construct_list () {
    let z : List<int> = List::Nil;
    let y : List<int> = List::Cons(1, box z);
    let x : List<int> = List::Art(cell(symbol(format!("two")), box y));
    let l : List<int> = List::Name(symbol(format!("one")), box x);
    println!("constructed list: {}", l);
}

// impl<T> List<T> {
//     /// Construct a new, empty list.
//     #[inline]
//     pub fn new() -> List<T> { Nil }
// }

// impl<T: Send + Sync> List<T> {
//     /// Create a list with one element in it.
//     #[inline]
//     pub fn singleton(n:Name,val: T) -> List<T> { Cons(val, Art::new(Nil)) }

//     /// Get the head of a list.
//     pub fn head(&self) -> Option<&T> {
//         match *self {
//             Nil => None,
//             Cons(ref head, _) => Some(head)
//         }
//     }

//     /// Get the tail of a list.
//     pub fn tail(&self) -> Option<Art<List<T>>> {
//         match *self {
//             Nil => None,
//             Cons(_, ref tail) => Some(tail.clone())
//         }
//     }

//     /// Get an iterator over the items in a list.
//     pub fn iter<'a>(&'a self) -> ListItems<'a, T> {
//         ListItems {
//             list: self
//         }
//     }
// }

// /// An iterator over the items in a list.
// pub struct ListItems<'a, T: 'a> {
//     list: &'a List<T>
// }

// impl<'a, T: Send + Sync> Iterator<&'a T> for ListItems<'a, T> {
//     fn next(&mut self) -> Option<&'a T> {
//         match *self.list {
//             Cons(ref head, ref tail) => {
//                 self.list = &**tail;
//                 Some(head)
//             },
//             Nil => None
//         }
//     }
// }

<|endoftext|>


<commit_before>extern crate clap;
use clap::{Arg, App};
use std::path::Path;
use std::process::Command;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

fn do_link(existing_file: &str, new_link:&str, force:bool) -> () {
    //println!("Linking {} to {}", existing_file, new_link);

    let mut vec = vec!["-s"];
    if force { vec.push("-f"); }

    let status = Command::new("ln")
        .args(&vec[..])
        .arg(existing_file)
        .arg(new_link)
        .status().unwrap_or_else(|e| {
        panic!("failed to execute process, bad process! {}", e)
    });

    match status.code() {
        Some(c) => std::process::exit(c),
        // not sure if I care about the signal info here, do you?
        None => panic!("Empty status code, killed by a signal? Ouch!")
    };
}

fn link(existing_file: &str, new_link:&str) -> () {
    do_link(existing_file, new_link, false);
}

fn link_with_force(existing_file: &str, new_link:&str) -> () {
    do_link(existing_file, new_link, true);
}

fn repoint_existing_link(sa: &Path, sb: &Path) -> () {
    let metas = (sa.symlink_metadata(), sb.symlink_metadata());
    match metas {
        (Ok(a), Ok(b)) => {
            let links = (a.file_type().is_symlink(), b.file_type().is_symlink());
            match links {
                (true, false) => link_with_force(sb.to_str().unwrap(), sa.to_str().unwrap()),
                (false, true) => link_with_force(sa.to_str().unwrap(), sb.to_str().unwrap()),
                (true, true) => exit_for_humans("Both paths are symlinks!", -1),
                (false, false) => exit_for_humans("Both paths are files!", -1)
            };
        },
        (Err(_a), Ok(_b)) => exit_for_humans("Failed to get metadata for <A>", -1),
        (Ok(_a), Err(_b)) => exit_for_humans("Failed to get metadata for <B>", -1),
        (Err(_a), Err(_b)) => exit_for_humans("Failed to get metadata for <A> and <B>", -1)
    };
}

fn exit_for_humans(msg: &str, status: i32) -> () {
    // ie, don't print panic() garbage
    println!("{}", msg);
    std::process::exit(status);
}

fn main() {

    let matches = App::new("simlink")
                      .version(VERSION)
                      .about("ln -s, meow/miaow")
                      .arg(Arg::with_name("A")
                               .help("Maybe a file, maybe a link you want to make?")
                               .required(true)
                               .index(1))
                      .arg(Arg::with_name("B")
                               .help("Maybe a file, maybe a link you want to make?")
                               .required(true)
                               .index(2))
                      .arg(Arg::with_name("force")
                               .help("Repoint an existing link")
                               .short("f")
                               .takes_value(false))
                      .get_matches();

    // A + B are required, clap will exit before unwrap() might fail
    let file_a = matches.value_of("A").unwrap();
    let file_b = matches.value_of("B").unwrap();
    let force = matches.is_present("force");

    let path_a = Path::new(file_a);
    let path_b = Path::new(file_b);

    if let None = path_a.to_str() {
        exit_for_humans("Invalid filename for <A>", -1);
    };

    if let None = path_b.to_str() {
        exit_for_humans("Invalid filename for <B>", -1);
    };

    let sa = path_a.to_str().unwrap();
    let sb = path_b.to_str().unwrap();

    let paths = (path_a.exists(), path_b.exists(), force);
    match paths {
        (true, false, _) => link(sa, sb),
        (false, true, _) => link(sb, sa),
        (true, true, true) => repoint_existing_link(path_a, path_b),
        (true, true, false) => exit_for_humans("Both paths exist (use -f to override)", -1),
        (false, false, _) => exit_for_humans("Neither path exists", -1)
    };

}
<commit_msg>cleanup<commit_after>extern crate clap;
use clap::{Arg, App};
use std::path::Path;
use std::process::Command;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

fn do_link(existing_file: &str, new_link:&str, force:bool) -> () {
    //println!("Linking {} to {}", existing_file, new_link);

    let mut params = vec!["-s"];
    if force { params.push("-f"); }

    let status = Command::new("ln")
        .args(&params[..])
        .arg(existing_file)
        .arg(new_link)
        .status().unwrap_or_else(|e| {
        panic!("failed to execute process, bad process! {}", e)
    });

    match status.code() {
        Some(c) => std::process::exit(c),
        // not sure if I care about the signal info here, do you?
        None => panic!("Empty status code, killed by a signal? Ouch!")
    };
}

fn link(existing_file: &str, new_link:&str) -> () {
    do_link(existing_file, new_link, false);
}

fn link_with_force(existing_file: &str, new_link:&str) -> () {
    do_link(existing_file, new_link, true);
}

fn repoint_existing_link(sa: &Path, sb: &Path) -> () {
    let metas = (sa.symlink_metadata(), sb.symlink_metadata());
    match metas {
        (Ok(a), Ok(b)) => {
            let links = (a.file_type().is_symlink(), b.file_type().is_symlink());
            match links {
                (true, false) => link_with_force(sb.to_str().unwrap(), sa.to_str().unwrap()),
                (false, true) => link_with_force(sa.to_str().unwrap(), sb.to_str().unwrap()),
                (true, true) => exit_for_humans("Both paths are symlinks!", -1),
                (false, false) => exit_for_humans("Both paths are files!", -1)
            };
        },
        (Err(_a), Ok(_b)) => exit_for_humans("Failed to get metadata for <A>", -1),
        (Ok(_a), Err(_b)) => exit_for_humans("Failed to get metadata for <B>", -1),
        (Err(_a), Err(_b)) => exit_for_humans("Failed to get metadata for <A> and <B>", -1)
    };
}

fn exit_for_humans(msg: &str, status: i32) -> () {
    // ie, don't print panic() garbage
    println!("{}", msg);
    std::process::exit(status);
}

fn main() {

    let matches = App::new("simlink")
                      .version(VERSION)
                      .about("ln -s, meow/miaow")
                      .arg(Arg::with_name("A")
                               .help("Maybe a file, maybe a link you want to make?")
                               .required(true)
                               .index(1))
                      .arg(Arg::with_name("B")
                               .help("Maybe a file, maybe a link you want to make?")
                               .required(true)
                               .index(2))
                      .arg(Arg::with_name("force")
                               .help("Repoint an existing link")
                               .short("f")
                               .takes_value(false))
                      .get_matches();

    // A + B are required, clap will exit before unwrap() might fail
    let file_a = matches.value_of("A").unwrap();
    let file_b = matches.value_of("B").unwrap();
    let force = matches.is_present("force");

    let path_a = Path::new(file_a);
    let path_b = Path::new(file_b);

    if let None = path_a.to_str() {
        exit_for_humans("Invalid filename for <A>", -1);
    };

    if let None = path_b.to_str() {
        exit_for_humans("Invalid filename for <B>", -1);
    };

    let sa = path_a.to_str().unwrap();
    let sb = path_b.to_str().unwrap();

    let paths = (path_a.exists(), path_b.exists(), force);
    match paths {
        (true, false, _) => link(sa, sb),
        (false, true, _) => link(sb, sa),
        (true, true, true) => repoint_existing_link(path_a, path_b),
        (true, true, false) => exit_for_humans("Both paths exist (use -f to override)", -1),
        (false, false, _) => exit_for_humans("Neither path exists", -1)
    };

}
<|endoftext|>


<commit_before>#![feature(if_let, macro_rules)]

extern crate curl;
extern crate git;
extern crate serialize;
extern crate time;

use git::Result as GitResult;
use std::default::Default;
use std::io::IoResult;
use std::os::args;

use description::Description;

mod description;

fn main() {
    macro_rules! ok(
        ($result:expr) => (
            if let Err(e) = $result {
                error(e);
                std::os::set_exit_status(1);
                return;
            }
        );
    )

    let args = args();

    if args.len() != 3 {
        usage();
        return;
    }

    let (command, path) = (args[1].clone(), Path::new(args[2].clone()));

    match command.as_slice() {
        "status" => ok!(status(&mut std::io::stdio::stdout(), &path)),
        "push" => ok!(push(&path)),
        _ => usage(),
    }
}

fn error<T: std::fmt::Show>(e: T) {
    println!("{}", e);
}

fn usage() {
    println!("Usage: {} (status|push) <path>", args()[0]);
}

fn status<T: Writer>(writer: &mut T, path: &Path) -> IoResult<()> {
    #![allow(unused_assignments)]

    use std::io::MemWriter;
    use std::io::{IoError, OtherIoError};

    macro_rules! display(
        ($writer:expr, $title:expr, $paths:expr, $sep:expr) => {
            if !$paths.is_empty() {
                if $sep {
                    try!(writeln!($writer, ""));
                }
                $sep = try!(display($writer, $title, &$paths));
            }
        };
    )

    let (new, updated, removed) = match summarize(path) {
        Ok(result) => result,
        Err(error) => return Err(IoError {
            kind: OtherIoError,
            desc: "cannot check the status of the repository",
            detail: Some(error.to_string()),
        }),
    };

    let mut sep = false;
    let mut buffer = MemWriter::new();

    display!(&mut buffer, "New", new, sep);
    display!(&mut buffer, "Updated", updated, sep);
    display!(&mut buffer, "Deleted", removed, sep);

    let data = buffer.unwrap();

    if data.len() > 0 {
        try!(writeln!(writer, "### {}", timestamp()));
        try!(writeln!(writer, ""));
        try!(writer.write(data.as_slice()));
    }

    Ok(())
}

fn push(path: &Path) -> GitResult<()> {
    let mut git = try!(git::open(path));

    try!(git.add_all());
    try!(git.commit("Synchronized with the official repository"));
    try!(git.push());

    Ok(())
}

fn summarize(dir: &Path) -> GitResult<(Vec<Path>, Vec<Path>, Vec<Path>)> {
    use git::status;
    use git::status::Flags;

    macro_rules! equal(
        ($one:expr, $two:expr) => ($one.dir_path() == $two.dir_path());
    )

    macro_rules! find(
        ($vector:expr, $element:expr) => (
            $vector.iter().find(|p| equal!(p, $element))
        );
    )

    const NEW: Flags = Flags(status::IndexNew as u32 | status::WorkDirNew as u32);
    const UPDATED: Flags = Flags(status::IndexModified as u32 | status::WorkDirModified as u32);
    const REMOVED: Flags = Flags(status::IndexDeleted as u32 | status::WorkDirDeleted as u32);

    let repo = try!(git::Repository::open(dir));
    let list = try!(repo.status(&Default::default()));

    let mut new = vec![];
    let mut updated = vec![];
    let mut removed = vec![];

    fn push(vector: &mut Vec<Path>, path: &Path) {
        if find!(vector, path).is_none() {
            vector.push(path.clone());
        }
    }

    for entry in list.iter() {
        let status = entry.status();
        let path = dir.join(entry.new_path());

        if status.any(NEW) {
            push(&mut new, &path);
        } else if status.any(UPDATED) {
            push(&mut updated, &path);
        } else if status.any(REMOVED) {
            push(&mut removed, &path);
        }
    }

    let new = new.into_iter().filter(|path| {
        if find!(removed, path).is_some() {
            push(&mut updated, path);
            false
        } else {
            true
        }
    }).collect::<Vec<_>>();

    let removed = removed.into_iter().filter(|path| {
        (find!(updated, path).is_none())
    }).collect::<Vec<_>>();

    Ok((new, updated, removed))
}

fn display<T: Writer>(writer: &mut T, title: &str, paths: &Vec<Path>) -> IoResult<bool> {
    let lines = paths.iter().by_ref()
                     .map(|path| format(path))
                     .filter(|line| line.is_some())
                     .map(|line| line.unwrap())
                     .collect::<Vec<_>>();

    let len = lines.len();
    if len == 0 {
        return Ok(false);
    }

    try!(writeln!(writer, "{}:", title));
    try!(writeln!(writer, ""));

    for (i, line) in lines.iter().enumerate() {
        if i + 1 == len {
            try!(writeln!(writer, "* {}.", line));
        } else if i + 2 == len {
            if len == 2 {
                try!(writeln!(writer, "* {} and", line));
            } else {
                try!(writeln!(writer, "* {}, and", line));
            }
        } else {
            try!(writeln!(writer, " * {},", line));
        }
    }

    Ok(true)
}

fn format(path: &Path) -> Option<String> {
    let mut line = String::new();

    let desc = Description::load(path);

    match desc.name {
        Some(ref name) => line.push_str(name.as_slice()),
        None => return None,
    }

    match desc.url {
        Some(ref url) => {
            line.insert(0, '[');
            line.push_str("](");
            line.push_str(url.as_slice());
            line.push_str(")");
        },
        None => {},
    }

    match desc.designer {
        Some(ref designer) => {
            line.push_str(" by ");
            line.push_str(designer.as_slice());
        },
        None => {},
    }

    Some(line)
}

fn timestamp() -> String {
    let time = time::now();

    const MONTHS: [&'static str, ..12] = ["January", "February", "March", "April",
                                          "May", "June", "July", "August", "September",
                                          "October", "November", "December"];

    format!("{} {}, {}", MONTHS[time.tm_mon as uint], time.tm_mday, 1900 + time.tm_year)
}
<commit_msg>Simplified the logic in status<commit_after>#![feature(if_let, macro_rules)]

extern crate curl;
extern crate git;
extern crate serialize;
extern crate time;

use git::Result as GitResult;
use std::default::Default;
use std::io::IoResult;
use std::os::args;

use description::Description;

mod description;

fn main() {
    macro_rules! ok(
        ($result:expr) => (
            if let Err(e) = $result {
                error(e);
                std::os::set_exit_status(1);
                return;
            }
        );
    )

    let args = args();

    if args.len() != 3 {
        usage();
        return;
    }

    let (command, path) = (args[1].clone(), Path::new(args[2].clone()));

    match command.as_slice() {
        "status" => ok!(status(&mut std::io::stdio::stdout(), &path)),
        "push" => ok!(push(&path)),
        _ => usage(),
    }
}

fn error<T: std::fmt::Show>(e: T) {
    println!("{}", e);
}

fn usage() {
    println!("Usage: {} (status|push) <path>", args()[0]);
}

fn status<T: Writer>(writer: &mut T, path: &Path) -> IoResult<()> {
    use std::io::MemWriter;
    use std::io::{IoError, OtherIoError};

    macro_rules! display(
        ($writer:expr, $title:expr, $paths:expr) => {
            if !$paths.is_empty() {
                try!(display($writer, $title, &$paths));
            }
        };
    )

    let (new, updated, removed) = match summarize(path) {
        Ok(result) => result,
        Err(error) => return Err(IoError {
            kind: OtherIoError,
            desc: "cannot check the status of the repository",
            detail: Some(error.to_string()),
        }),
    };

    let mut buffer = MemWriter::new();

    display!(&mut buffer, "New", new);
    display!(&mut buffer, "Updated", updated);
    display!(&mut buffer, "Deleted", removed);

    let data = buffer.unwrap();

    if data.len() > 0 {
        try!(writeln!(writer, "### {}", timestamp()));
        try!(writeln!(writer, ""));
        try!(writer.write(data.as_slice()));
    }

    Ok(())
}

fn push(path: &Path) -> GitResult<()> {
    let mut git = try!(git::open(path));

    try!(git.add_all());
    try!(git.commit("Synchronized with the official repository"));
    try!(git.push());

    Ok(())
}

fn summarize(dir: &Path) -> GitResult<(Vec<Path>, Vec<Path>, Vec<Path>)> {
    use git::status;
    use git::status::Flags;

    macro_rules! equal(
        ($one:expr, $two:expr) => ($one.dir_path() == $two.dir_path());
    )

    macro_rules! find(
        ($vector:expr, $element:expr) => (
            $vector.iter().find(|p| equal!(p, $element))
        );
    )

    const NEW: Flags = Flags(status::IndexNew as u32 | status::WorkDirNew as u32);
    const UPDATED: Flags = Flags(status::IndexModified as u32 | status::WorkDirModified as u32);
    const REMOVED: Flags = Flags(status::IndexDeleted as u32 | status::WorkDirDeleted as u32);

    let repo = try!(git::Repository::open(dir));
    let list = try!(repo.status(&Default::default()));

    let mut new = vec![];
    let mut updated = vec![];
    let mut removed = vec![];

    fn push(vector: &mut Vec<Path>, path: &Path) {
        if find!(vector, path).is_none() {
            vector.push(path.clone());
        }
    }

    for entry in list.iter() {
        let status = entry.status();
        let path = dir.join(entry.new_path());

        if status.any(NEW) {
            push(&mut new, &path);
        } else if status.any(UPDATED) {
            push(&mut updated, &path);
        } else if status.any(REMOVED) {
            push(&mut removed, &path);
        }
    }

    let new = new.into_iter().filter(|path| {
        if find!(removed, path).is_some() {
            push(&mut updated, path);
            false
        } else {
            true
        }
    }).collect::<Vec<_>>();

    let removed = removed.into_iter().filter(|path| {
        (find!(updated, path).is_none())
    }).collect::<Vec<_>>();

    Ok((new, updated, removed))
}

fn display<T: Writer>(writer: &mut T, title: &str, paths: &Vec<Path>) -> IoResult<()> {
    let lines = paths.iter().by_ref()
                     .map(|path| format(path))
                     .filter(|line| line.is_some())
                     .map(|line| line.unwrap())
                     .collect::<Vec<_>>();

    let len = lines.len();
    if len == 0 {
        return Ok(());
    }

    try!(writeln!(writer, "{}:", title));
    try!(writeln!(writer, ""));
    for (i, line) in lines.iter().enumerate() {
        if i + 1 == len {
            try!(writeln!(writer, "* {}.", line));
        } else if i + 2 == len {
            if len == 2 {
                try!(writeln!(writer, "* {} and", line));
            } else {
                try!(writeln!(writer, "* {}, and", line));
            }
        } else {
            try!(writeln!(writer, " * {},", line));
        }
    }
    try!(writeln!(writer, ""));

    Ok(())
}

fn format(path: &Path) -> Option<String> {
    let mut line = String::new();

    let desc = Description::load(path);

    match desc.name {
        Some(ref name) => line.push_str(name.as_slice()),
        None => return None,
    }

    match desc.url {
        Some(ref url) => {
            line.insert(0, '[');
            line.push_str("](");
            line.push_str(url.as_slice());
            line.push_str(")");
        },
        None => {},
    }

    match desc.designer {
        Some(ref designer) => {
            line.push_str(" by ");
            line.push_str(designer.as_slice());
        },
        None => {},
    }

    Some(line)
}

fn timestamp() -> String {
    let time = time::now();

    const MONTHS: [&'static str, ..12] = ["January", "February", "March", "April",
                                          "May", "June", "July", "August", "September",
                                          "October", "November", "December"];

    format!("{} {}, {}", MONTHS[time.tm_mon as uint], time.tm_mday, 1900 + time.tm_year)
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate futures;
extern crate tokio_proto;
extern crate tokio_service;
extern crate tokio_core;
extern crate tokio_io;
extern crate bytes;

use std::{io, str};
use std::net::ToSocketAddrs;

use futures::{Future, Stream, Poll, Async};
use futures::{Sink, AsyncSink, StartSend};
use futures::future::{self, loop_fn, FutureResult, Loop, LoopFn};
use tokio_proto::TcpClient;
use tokio_proto::pipeline::ClientProto;
use tokio_service::Service;
use tokio_core::reactor::Core;
use tokio_io::codec::{Encoder, Decoder, Framed};
use tokio_io::{AsyncRead, AsyncWrite};
use bytes::BytesMut;

#[derive(Default)]
pub struct LineCodec;

impl Decoder for LineCodec {
    type Item = String;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<String>> {
        println!("Received: {:?}", std::str::from_utf8(buf));
        if let Some(i) = buf.iter().position(|&b| b == b'\n') {
            let line = buf.split_to(i);
            buf.split_to(1);
            match str::from_utf8(&line) {
                Ok(s) => Ok(Some(s.to_string())),
                Err(_) => Err(io::Error::new(io::ErrorKind::Other,
                                             "invalid UTF-8")),
            }
        } else {
            Ok(None)
        }
    }
}

impl Encoder for LineCodec {
    type Item = String;
    type Error = io::Error;

    fn encode(&mut self, msg: String, buf: &mut BytesMut) -> io::Result<()> {
        //println!("Sending: {}", msg);
        buf.extend(msg.as_bytes());
        buf.extend(b"\n");
        Ok(())
    }
}

pub struct PingPong<T> {
    upstream: T,
    response: Option<String>,
    // TODO: stuff like AWAY ?
}

impl<T> PingPong<T> {
    fn new(t: T) -> Self {
        PingPong {
            upstream: t,
            response: None,
        }
    }
}

impl<T> Stream for PingPong<T>
    where T: Stream<Item = String, Error = io::Error>,
          T: Sink<SinkItem = String, SinkError = io::Error>,
{
    type Item = String;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<String>, io::Error> {
        //loop {
        // Poll the upstream transport
        match try_ready!(self.upstream.poll()) {
            Some(ref msg) if msg.starts_with("PING ") => {
                // Intercept pings
                let resp = msg.replacen("PING", "PONG", 1);
                self.response = Some(resp);
                self.poll_complete()?;
                let _poll = try_ready!(self.upstream.poll());
                // Never hit:
                println!("UHHHH `{:?}`", _poll);
                unimplemented!();
                //Ok(Async::Ready(_poll))
            },
            // Final output:
            m => Ok(Async::Ready(m))
                //m => {
            //    self.upstream.foo();
            //},
        }
        //}
    }
}

impl<T> Sink for PingPong<T>
    where T: Sink<SinkItem = String, SinkError = io::Error>,
{
    type SinkItem = String;
    type SinkError = io::Error;

    fn start_send(&mut self, item: String) -> StartSend<String, io::Error> {
        // Only accept the write if there are no pending pongs
        if self.response.is_some() {
            return Ok(AsyncSink::NotReady(item));
        }
        self.upstream.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), io::Error> {
        if let Some(pong) = self.response.take() {
            self.upstream.start_send(pong)?;
        }
        self.upstream.poll_complete()
    }
}

pub struct LineProto;

impl<T: AsyncRead + AsyncWrite + 'static> ClientProto<T> for LineProto {
    type Request = String;
    type Response = String;
    type Transport = PingPong<Framed<T, LineCodec>>;
    type BindTransport = Result<Self::Transport, io::Error>;
    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(PingPong::new(io.framed(LineCodec)))
    }
}

fn main() {
    //let addr = "0.0.0.0:12345".parse().unwrap();
    //TcpServer::new(IntProto, addr)
    //    .serve(|| Ok(Doubler));
    let cm = "USER qj 0 * qjkx\r\nNICK qjk\r\nJOIN #test\r\n".to_string();

    //let addr = "irc.freenode.org:6697".to_socket_addrs().unwrap().next().unwrap();
    let addr = "0.0.0.0:12345".to_socket_addrs().unwrap().next().unwrap();

    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let tc = TcpClient::new(LineProto);
    /*
    let response = tc
        .connect(&addr, &handle)
        .and_then(|client| {
            client.call("ONE".to_string())
                .and_then(move |response| {
                    client.call("TWO".to_string())
                        .and_then(move |response| {
                            client.call("THREE".to_string())
                        })
                })
        });
        */
    let response = tc.connect(&addr, &handle)
        .and_then(|client| {
            client.call(cm)
                .and_then(move |r0| {
                    loop_fn(client, |c| {
                        c.call("ack".to_string())
                            .and_then(|ri| {
                                if ri == "DONE" {
                                    Ok(Loop::Break(c))
                                } else {
                                    Ok(Loop::Continue(c))
                                }
                            })
                    })
                })
        });
    //let socket = tc.connect(&addr, &handle);
    //let response = socket.and_then(|x| x.call(cm));

    let data = core.run(response);//.unwrap();
    //println!("{:?}", data);

    //let client = tc.and_then(|x| x.call(cm));
    //response.foo();
    //response.and_then(|x| future::ok(x).foo());
                    //client.call("BYE\r\n".to_string())

    //let listen = cli.connect(&addr, &handle).and_then(|r| { });
    //let listen = loop_fn(cli.connect(&addr, &handle), |msg| {
    //let listen = loop_fn(socket.and_then(|s| s.call(cm)), |msg| {

    //let listen: LoopFn<Result<_,io::Error>, _> = loop_fn(conn, |cli| {
        //cli.and_then(|x| cli.call());
        //cli.foo();
        //cli.and_then(|x| future::ok(x).foo())
        //let r = cli.and_then(|x| x.call("HI\r\n"));
        //let r = cli.call("HI\r\n");
        //r.foo();
    //});

    //let mut a = core.run(listen).unwrap();
    //a.poll();
        /*
    let listen: LoopFn<Result<_,io::Error>, _> = loop_fn(response, |x| {
        k
        x.and_then(|y| {
            //y.call("BAD\r\n").and_then(
            if y.contains("fuck") {
                //Ok(Loop::Break(y))
                Ok(Loop::Break(x))
            } else {
                Ok(Loop::Continue(x))
            }
        })
        */
    /*
        if true {
            Ok(Loop::Break(msg))
        } else {
            //Ok(Loop::Continue(msg))
            Ok(Loop::Break(msg))
        }
    });
        */

        /*
    let req = cli.connect(&addr, &handle)
        .and_then(|client| {
            client.call(cm)
                .and_then(move |response| {
                    println!("CLIENT: {:?}", response);
                    client.call("BYE\r\n".to_string())
                })
            .and_then(|response| {
                println!("CLIENT_: {:?}", response);
                Ok(())
            })
        });
        */

    //let response = socket.and_then(|x| x.call(cm));

    //let data = core.run(response);//.unwrap();
    //println!("{:?}", data);
    //let (_socket, data) = core.run(response).unwrap();
    //println!("{}", String::from_utf8_lossy(&data));
}
<commit_msg>Code cleaned up, client shouldn't die<commit_after>#[macro_use]
extern crate futures;
extern crate tokio_proto;
extern crate tokio_service;
extern crate tokio_core;
extern crate tokio_io;
extern crate bytes;

use std::{io, str};
use std::net::ToSocketAddrs;

use futures::{Future, Poll, StartSend};
use futures::{Async, Stream, Sink, AsyncSink};
use futures::future::{loop_fn, Loop};
use tokio_proto::TcpClient;
use tokio_proto::pipeline::{ClientProto, ClientService};
use tokio_service::Service;
use tokio_core::reactor::Core;
use tokio_core::net::TcpStream;
use tokio_io::codec::{Encoder, Decoder, Framed};
use tokio_io::{AsyncRead, AsyncWrite};
use bytes::BytesMut;

#[derive(Default)]
pub struct LineCodec;

impl Decoder for LineCodec {
    type Item = String;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> io::Result<Option<String>> {
        println!("Received: {:?}", std::str::from_utf8(buf));
        if let Some(i) = buf.iter().position(|&b| b == b'\n') {
            let line = buf.split_to(i);
            buf.split_to(1);
            match str::from_utf8(&line) {
                Ok(s) => Ok(Some(s.to_string())),
                Err(_) => Err(io::Error::new(io::ErrorKind::Other,
                                             "invalid UTF-8")),
            }
        } else {
            Ok(None)
        }
    }
}

impl Encoder for LineCodec {
    type Item = String;
    type Error = io::Error;

    fn encode(&mut self, msg: String, buf: &mut BytesMut) -> io::Result<()> {
        buf.extend(msg.as_bytes());
        buf.extend(b"\n");
        Ok(())
    }
}

pub struct PingPong<T> {
    upstream: T,
    response: Option<String>,
    // TODO: stuff like AWAY ?
}

impl<T> PingPong<T> {
    fn new(t: T) -> Self {
        PingPong {
            upstream: t,
            response: None,
        }
    }
}

impl<T> Stream for PingPong<T>
    where T: Stream<Item = String, Error = io::Error>,
          T: Sink<SinkItem = String, SinkError = io::Error>,
{
    type Item = String;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<String>, io::Error> {
        // Poll the upstream transport
        match try_ready!(self.upstream.poll()) {
            Some(ref msg) if msg.starts_with("PING ") => {
                // Intercept pings
                let resp = msg.replacen("PING", "PONG", 1);
                self.response = Some(resp);
                self.poll_complete()?;
                let _poll = try_ready!(self.upstream.poll());
                // Never hit:
                println!("UHHHH `{:?}`", _poll);
                unimplemented!();
                //Ok(Async::Ready(_poll))
            },
            // Final output:
            m => Ok(Async::Ready(m))
        }
    }
}

impl<T> Sink for PingPong<T>
    where T: Sink<SinkItem = String, SinkError = io::Error>,
{
    type SinkItem = String;
    type SinkError = io::Error;

    fn start_send(&mut self, item: String) -> StartSend<String, io::Error> {
        // Only accept the write if there are no pending pong
        if self.response.is_some() {
            return Ok(AsyncSink::NotReady(item));
        }
        self.upstream.start_send(item)
    }

    fn poll_complete(&mut self) -> Poll<(), io::Error> {
        if let Some(pong) = self.response.take() {
            self.upstream.start_send(pong)?;
        }
        self.upstream.poll_complete()
    }
}

pub struct LineProto;

impl<T: AsyncRead + AsyncWrite + 'static> ClientProto<T> for LineProto {
    type Request = String;
    type Response = String;
    type Transport = PingPong<Framed<T, LineCodec>>;
    type BindTransport = Result<Self::Transport, io::Error>;
    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(PingPong::new(io.framed(LineCodec)))
    }
}

fn main() {
    let cm = "USER qj 0 * qjkx\r\nNICK qjk\r\nJOIN #test\r\n".to_string();

    //let addr = "irc.freenode.org:6697".to_socket_addrs().unwrap().next().unwrap();
    let addr = "0.0.0.0:12345".to_socket_addrs().unwrap().next().unwrap();

    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let tc = TcpClient::new(LineProto);
    let response = tc.connect(&addr, &handle)
        .and_then(|client| client.call(cm)
            .and_then(move |_r0| loop_fn(client, |c| c.call("ACK".to_string())
                .and_then(|_ri| {
                    let lcs: Loop<ClientService<TcpStream,LineProto>,_>
                        = Loop::Continue(c);
                    Ok(lcs)
                })
            ))
        );

    core.run(response).unwrap();
}

<|endoftext|>


<commit_before>extern crate clap;
extern crate rukyll;

use clap::{App, Arg, AppSettings, SubCommand};
use rukyll::commands;

const VERSION_NUMBER: &'static str = "0.1.0";

fn main() {
    let matches = App::new("Rukyll")
                        .setting(AppSettings::ArgRequiredElseHelp)
                        .version(VERSION_NUMBER)
                        .about("Static site generator")
                        .subcommand(SubCommand::with_name("new")
                            .arg(Arg::with_name("project name")
                            .index(1)
                            .required(true)
                            )
                        )
                        .get_matches();

    match matches.subcommand() {
        ("new", Some(new)) => {
            // TODO: Better error handling
            let project_name = if new.is_present("project name") {
                new.value_of("project name").unwrap()
            } else {
                ""
            };

            commands::new_project(&project_name);
        },
        _ => {}
    }
}
<commit_msg>chore(exec): Refactor subcommand handling<commit_after>extern crate clap;
extern crate rukyll;

use clap::{App, Arg, AppSettings, SubCommand};
use rukyll::commands;

const VERSION_NUMBER: &'static str = "0.1.0";

fn main() {
    let matches = App::new("Rukyll")
        .setting(AppSettings::ArgRequiredElseHelp)
        .version(VERSION_NUMBER)
        .about("Static site generator")
        .subcommand(SubCommand::with_name("new").arg(Arg::with_name("project name")
            .index(1)
            .required(true)))
        .subcommand(SubCommand::with_name("build"))
        .get_matches();

    if let ("new", Some(new)) = matches.subcommand() {
        // TODO: Better error handling
        let project_name = if new.is_present("project name") {
            new.value_of("project name").unwrap()
        } else {
            ""
        };

        commands::new_project(&project_name);
    }
}
<|endoftext|>


<commit_before>#![feature(slice_patterns)]

use std::collections::BTreeMap;
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::thread;

#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Eq)]
enum Op {
    Add(u8),
    Mov(isize),
    In,
    Out,
    Loop(OpStream),

    // extra optimized ops
    Transfer(u8, Vec<(isize, u8)>),
}

use Op::*;

#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Eq)]
struct OpStream {
    ops: Vec<Op>,
}

impl OpStream {
    fn optimize(&mut self) {
        let mut i = 0;
        while i < self.ops.len() {
            match &self.ops[i..] {
                [Add(a), Add(b), ..] => {
                    self.ops[i] = Add(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Mov(a), Mov(b), ..] => {
                    self.ops[i] = Mov(a + b);
                    self.ops.remove(i + 1);
                }
                [Add(0), ..] | [Mov(0), ..] => {
                    self.ops.remove(i);
                    if i > 0 {
                        i -= 1;
                    }
                }
                [Loop(_), ..] => {
                    let maybe_new_op;

                    if let &mut Loop(ref mut stream) = &mut self.ops[i] {
                        stream.optimize();
                        maybe_new_op = stream.find_alternative();
                    } else {
                        unreachable!()
                    }

                    if let Some(new_op) = maybe_new_op {
                        self.ops[i] = new_op;
                    }

                    i += 1
                }
                _ => i += 1,
            }
        }
    }

    fn find_alternative(&self) -> Option<Op> {
        let mut map: BTreeMap<isize, u8> = BTreeMap::new();
        let mut rel_index = 0;

        for op in &self.ops[..] {
            match op {
                &Add(x) => {
                    let new_val = map.get(&rel_index).unwrap_or(&0).wrapping_add(x);
                    map.insert(rel_index, new_val);
                }
                &Mov(x) => {
                    rel_index += x;
                }
                _ => {
                    return None;
                }
            }
        }

        if rel_index != 0 {
            return None;
        }

        Some(Transfer(map.remove(&0).unwrap_or(0), map.into_iter().collect()))
    }

    fn get(&self) -> &[Op] {
        &self.ops[..]
    }
}

static ZERO: u8 = 0;

struct State {
    index: usize,
    memory: Vec<u8>,
}

impl State {
    fn new() -> State {
        State {
            index: 0,
            memory: vec![],
        }
    }

    fn rel_index(&self, relative: isize) -> usize {
        (self.index as isize + relative) as usize
    }

    fn step(&mut self, op: &Op) -> bool {
        match *op {
            Add(i) => {
                self[0] = self[0].wrapping_add(i);
            }
            Mov(n) => {
                self.index = self.rel_index(n);
            }
            In => {
                let mut c = [0u8];
                if io::stdin().read(&mut c).unwrap() == 0 {
                    return false;
                }
                self[0] = c[0];
            }
            Out => {
                io::stdout().write(&[self[0]]).unwrap();
            }
            Loop(ref ops) => {
                while self[0] != 0 {
                    if !self.run(ops.get()) {
                        return false;
                    }
                }
            }
            Transfer(d, ref map) => {
                if self[0] == 0 {
                    return true;
                }

                let mut _v = self[0];
                let mut _n = 0;

                while _v != 0 {
                    _v = _v.wrapping_add(d);
                    if _v == self[0] {
                        // stalled: the current transfer will never complete
                        loop {
                            thread::park()
                        }
                    }
                    _n += 1
                }

                self[0] = 0;
                for &(k, v) in &map[..] {
                    self[k] = self[k].wrapping_add(v.wrapping_mul(_n));
                }
            }
        }
        return true;
    }

    fn run(&mut self, ops: &[Op]) -> bool {
        for op in ops {
            if !self.step(op) {
                return false;
            }
        }
        return true;
    }
}

impl std::ops::Index<isize> for State {
    type Output = u8;
    fn index(&self, _index: isize) -> &u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            &ZERO
        } else {
            &self.memory[idx]
        }
    }
}

impl std::ops::IndexMut<isize> for State {
    fn index_mut(&mut self, _index: isize) -> &mut u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            self.memory.resize(idx * 2 + 1, 0);
        }
        &mut self.memory[idx]
    }
}

fn main() {
    let filenames: Vec<String> = std::iter::FromIterator::from_iter(std::env::args());

    for filename in &filenames[1..] {
        match fs::File::open(filename)
                  .map(|f| io::BufReader::new(f))
                  .and_then(|mut reader| {
                      let mut buffer = Vec::new();
                      reader.read_to_end(&mut buffer).map(|_| buffer)
                  })
                  .map_err(|e| format!("{}", e))
                  .and_then(|buffer| parse(&buffer[..])) {
            Ok(ops) => {
                let mut opstream = OpStream { ops: ops };
                opstream.optimize();
                State::new().run(opstream.get());
            }
            Err(e) => {
                writeln!(&mut io::stderr(),
                         "Error while processing {}: {}",
                         filename,
                         e)
                    .unwrap();
            }
        }
    }
}

fn parse(text: &[u8]) -> Result<Vec<Op>, String> {
    let mut stack = vec![];
    let mut current = vec![];

    for c in text {
        match *c as char {
            '+' => current.push(Add(0x01)),
            '-' => current.push(Add(0xff)),
            '>' => current.push(Mov(1)),
            '<' => current.push(Mov(-1)),
            '.' => current.push(Out),
            ',' => current.push(In),
            '[' => {
                stack.push(current);
                current = vec![];
            }
            ']' => {
                let opstream = OpStream { ops: current };
                current = match stack.pop() {
                    Some(v) => v,
                    None => return Err("Stray ]".to_string()),
                };
                current.push(Loop(opstream));
            }
            _ => {}
        }
    }
    if !stack.is_empty() {
        return Err("Missing ]".to_string());
    }
    Ok(current)
}

#[cfg(test)]
mod tests {
    use super::{parse, State, OpStream};
    use super::Op::*;

    #[test]
    fn test_state_index() {
        let mut state = State {
            index: 0,
            memory: vec![23, 0, 0, 0, 0, 42],
        };
        assert_eq!(23, state[0]);
        state.index = 5;
        assert_eq!(42, state[0]);
    }

    #[test]
    fn test_state_index_mut() {
        let mut state = State::new();
        state[0] = 23;
        assert_eq!(23, state.memory[state.index]);
        state.index = 5;
        state[0] = 42;
        assert_eq!(42, state.memory[state.index]);
    }

    #[test]
    fn test_state_step_add() {
        let mut state = State::new();
        state.step(&Add(23));
        assert_eq!(23, state[0]);
        state.step(&Add(42));
        assert_eq!(65, state[0]);
        state.step(&Add(190));
        assert_eq!(255, state[0]);
    }

    #[test]
    fn test_state_step_mov() {
        let mut state = State::new();
        state.step(&Mov(1));
        assert_eq!(1, state.index);
        state.step(&Mov(42));
        assert_eq!(43, state.index);
        state.step(&Mov(-1));
        assert_eq!(42, state.index);
    }

    #[test]
    fn test_state_step_loop() {
        let mut state = State::new();
        state[0] = 23;
        state.step(&Loop(OpStream { ops: vec![Add(1)] }));
        assert_eq!(0, state[0]);
    }

    #[test]
    fn test_state_step_transfer() {
        let mut state = State::new();
        state[0] = 15;
        state[1] = 7;
        state.step(&Transfer(5, vec![(1, 2)]));
        assert_eq!(0, state[0]);
        assert_eq!(1, state[1]);
    }

    #[test]
    fn test_opstream_optimize() {
        let mut opstream = OpStream {
            ops: vec![Mov(1),
                      Mov(1),
                      Add(0x01),
                      Add(0x0ff),
                      Add(0x0ff),
                      Mov(1),
                      Mov(-1),
                      Loop(OpStream { ops: vec![Mov(2), Mov(3)] })],
        };
        opstream.optimize();

        assert_eq!(opstream,
                   OpStream { ops: vec![Mov(2), Add(0xff), Loop(OpStream { ops: vec![Mov(5)] })] });
    }

    #[test]
    fn test_opstream_optimize_transfer() {
        let mut opstream = OpStream {
            ops: vec![Loop(OpStream { ops: vec![Add(0x01), Mov(3), Add(0xff), Mov(-3)] })],
        };
        opstream.optimize();

        assert_eq!(opstream,
                   OpStream { ops: vec![Transfer(1, vec![(3, 255)])] });
    }

    #[test]
    fn test_parse() {
        let input = b"+-[+.,]+";
        assert_eq!(parse(&input[..]),
                   Ok(vec![Add(0x01),
                           Add(0xff),
                           Loop(OpStream { ops: vec![Add(1), Out, In] }),
                           Add(0x01)]));
    }
}
<commit_msg>feat: show line and column in error messages<commit_after>#![feature(slice_patterns)]

use std::collections::BTreeMap;
use std::fs;
use std::io;
use std::io::{Read, Write};
use std::thread;

#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Eq)]
enum Op {
    Add(u8),
    Mov(isize),
    In,
    Out,
    Loop(OpStream),

    // extra optimized ops
    Transfer(u8, Vec<(isize, u8)>),
}

use Op::*;

#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Eq)]
struct OpStream {
    ops: Vec<Op>,
}

impl OpStream {
    fn optimize(&mut self) {
        let mut i = 0;
        while i < self.ops.len() {
            match &self.ops[i..] {
                [Add(a), Add(b), ..] => {
                    self.ops[i] = Add(a.wrapping_add(b));
                    self.ops.remove(i + 1);
                }
                [Mov(a), Mov(b), ..] => {
                    self.ops[i] = Mov(a + b);
                    self.ops.remove(i + 1);
                }
                [Add(0), ..] | [Mov(0), ..] => {
                    self.ops.remove(i);
                    if i > 0 {
                        i -= 1;
                    }
                }
                [Loop(_), ..] => {
                    let maybe_new_op;

                    if let &mut Loop(ref mut stream) = &mut self.ops[i] {
                        stream.optimize();
                        maybe_new_op = stream.find_alternative();
                    } else {
                        unreachable!()
                    }

                    if let Some(new_op) = maybe_new_op {
                        self.ops[i] = new_op;
                    }

                    i += 1
                }
                _ => i += 1,
            }
        }
    }

    fn find_alternative(&self) -> Option<Op> {
        let mut map: BTreeMap<isize, u8> = BTreeMap::new();
        let mut rel_index = 0;

        for op in &self.ops[..] {
            match op {
                &Add(x) => {
                    let new_val = map.get(&rel_index).unwrap_or(&0).wrapping_add(x);
                    map.insert(rel_index, new_val);
                }
                &Mov(x) => {
                    rel_index += x;
                }
                _ => {
                    return None;
                }
            }
        }

        if rel_index != 0 {
            return None;
        }

        Some(Transfer(map.remove(&0).unwrap_or(0), map.into_iter().collect()))
    }

    fn get(&self) -> &[Op] {
        &self.ops[..]
    }
}

static ZERO: u8 = 0;

struct State {
    index: usize,
    memory: Vec<u8>,
}

impl State {
    fn new() -> State {
        State {
            index: 0,
            memory: vec![],
        }
    }

    fn rel_index(&self, relative: isize) -> usize {
        (self.index as isize + relative) as usize
    }

    fn step(&mut self, op: &Op) -> bool {
        match *op {
            Add(i) => {
                self[0] = self[0].wrapping_add(i);
            }
            Mov(n) => {
                self.index = self.rel_index(n);
            }
            In => {
                let mut c = [0u8];
                if io::stdin().read(&mut c).unwrap() == 0 {
                    return false;
                }
                self[0] = c[0];
            }
            Out => {
                io::stdout().write(&[self[0]]).unwrap();
            }
            Loop(ref ops) => {
                while self[0] != 0 {
                    if !self.run(ops.get()) {
                        return false;
                    }
                }
            }
            Transfer(d, ref map) => {
                if self[0] == 0 {
                    return true;
                }

                let mut _v = self[0];
                let mut _n = 0;

                while _v != 0 {
                    _v = _v.wrapping_add(d);
                    if _v == self[0] {
                        // stalled: the current transfer will never complete
                        loop {
                            thread::park()
                        }
                    }
                    _n += 1
                }

                self[0] = 0;
                for &(k, v) in &map[..] {
                    self[k] = self[k].wrapping_add(v.wrapping_mul(_n));
                }
            }
        }
        return true;
    }

    fn run(&mut self, ops: &[Op]) -> bool {
        for op in ops {
            if !self.step(op) {
                return false;
            }
        }
        return true;
    }
}

impl std::ops::Index<isize> for State {
    type Output = u8;
    fn index(&self, _index: isize) -> &u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            &ZERO
        } else {
            &self.memory[idx]
        }
    }
}

impl std::ops::IndexMut<isize> for State {
    fn index_mut(&mut self, _index: isize) -> &mut u8 {
        let idx = self.rel_index(_index);
        if idx >= self.memory.len() {
            self.memory.resize(idx * 2 + 1, 0);
        }
        &mut self.memory[idx]
    }
}

fn main() {
    let filenames: Vec<String> = std::iter::FromIterator::from_iter(std::env::args());

    for filename in &filenames[1..] {
        match fs::File::open(filename)
                  .map(|f| io::BufReader::new(f))
                  .and_then(|mut reader| {
                      let mut buffer = Vec::new();
                      reader.read_to_end(&mut buffer).map(|_| buffer)
                  })
                  .map_err(|e| format!("{}", e))
                  .and_then(|buffer| parse(&buffer[..])) {
            Ok(ops) => {
                let mut opstream = OpStream { ops: ops };
                opstream.optimize();
                State::new().run(opstream.get());
            }
            Err(e) => {
                writeln!(&mut io::stderr(),
                         "Error while processing {}: {}",
                         filename,
                         e)
                    .unwrap();
            }
        }
    }
}

fn parse(text: &[u8]) -> Result<Vec<Op>, String> {
    let mut stack = vec![];
    let mut current = vec![];
    let mut line = 1;
    let mut column = 1;

    for c in text {
        match *c as char {
            '+' => current.push(Add(0x01)),
            '-' => current.push(Add(0xff)),
            '>' => current.push(Mov(1)),
            '<' => current.push(Mov(-1)),
            '.' => current.push(Out),
            ',' => current.push(In),
            '[' => {
                stack.push(current);
                current = vec![];
            }
            ']' => {
                let opstream = OpStream { ops: current };
                current = match stack.pop() {
                    Some(v) => v,
                    None => return Err(format!("Stray ] in line {}, column {}", line, column))
                };
                current.push(Loop(opstream));
            }
            _ => {}
        }
        if *c as char == '\n' {
            line += 1;
            column = 1;
        } else {
            column += 1;
        }
    }
    if !stack.is_empty() {
        return Err(format!("Missing ] in line {}, column {}", line, column));
    }
    Ok(current)
}

#[cfg(test)]
mod tests {
    use super::{parse, State, OpStream};
    use super::Op::*;

    #[test]
    fn test_state_index() {
        let mut state = State {
            index: 0,
            memory: vec![23, 0, 0, 0, 0, 42],
        };
        assert_eq!(23, state[0]);
        state.index = 5;
        assert_eq!(42, state[0]);
    }

    #[test]
    fn test_state_index_mut() {
        let mut state = State::new();
        state[0] = 23;
        assert_eq!(23, state.memory[state.index]);
        state.index = 5;
        state[0] = 42;
        assert_eq!(42, state.memory[state.index]);
    }

    #[test]
    fn test_state_step_add() {
        let mut state = State::new();
        state.step(&Add(23));
        assert_eq!(23, state[0]);
        state.step(&Add(42));
        assert_eq!(65, state[0]);
        state.step(&Add(190));
        assert_eq!(255, state[0]);
    }

    #[test]
    fn test_state_step_mov() {
        let mut state = State::new();
        state.step(&Mov(1));
        assert_eq!(1, state.index);
        state.step(&Mov(42));
        assert_eq!(43, state.index);
        state.step(&Mov(-1));
        assert_eq!(42, state.index);
    }

    #[test]
    fn test_state_step_loop() {
        let mut state = State::new();
        state[0] = 23;
        state.step(&Loop(OpStream { ops: vec![Add(1)] }));
        assert_eq!(0, state[0]);
    }

    #[test]
    fn test_state_step_transfer() {
        let mut state = State::new();
        state[0] = 15;
        state[1] = 7;
        state.step(&Transfer(5, vec![(1, 2)]));
        assert_eq!(0, state[0]);
        assert_eq!(1, state[1]);
    }

    #[test]
    fn test_opstream_optimize() {
        let mut opstream = OpStream {
            ops: vec![Mov(1),
                      Mov(1),
                      Add(0x01),
                      Add(0x0ff),
                      Add(0x0ff),
                      Mov(1),
                      Mov(-1),
                      Loop(OpStream { ops: vec![Mov(2), Mov(3)] })],
        };
        opstream.optimize();

        assert_eq!(opstream,
                   OpStream { ops: vec![Mov(2), Add(0xff), Loop(OpStream { ops: vec![Mov(5)] })] });
    }

    #[test]
    fn test_opstream_optimize_transfer() {
        let mut opstream = OpStream {
            ops: vec![Loop(OpStream { ops: vec![Add(0x01), Mov(3), Add(0xff), Mov(-3)] })],
        };
        opstream.optimize();

        assert_eq!(opstream,
                   OpStream { ops: vec![Transfer(1, vec![(3, 255)])] });
    }

    #[test]
    fn test_parse() {
        let input = b"+-[+.,]+";
        assert_eq!(parse(&input[..]),
                   Ok(vec![Add(0x01),
                           Add(0xff),
                           Loop(OpStream { ops: vec![Add(1), Out, In] }),
                           Add(0x01)]));
    }
}
<|endoftext|>