<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_id="html5-macros"]
#![crate_type="dylib"]

#![feature(macro_rules, macro_registrar, quote, managed_boxes)]

extern crate syntax;
extern crate serialize;
extern crate collections;

use syntax::ast::Name;
use syntax::parse::token;
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT};

// Internal macros for use in defining other macros.

#[macro_escape]
macro_rules! bail ( ($msg:expr) => ({
    cx.span_err(sp, $msg);
    return DummyResult::any(sp);
}))

#[macro_escape]
macro_rules! bail_if ( ($e:expr, $msg:expr) => (
    if $e { bail!($msg) }
))

#[macro_escape]
macro_rules! expect ( ($e:expr, $msg:expr) => (
    match $e {
        Some(x) => x,
        None => bail!($msg),
    }
))

mod named_entities;
mod atom;

#[macro_export]
macro_rules! unwrap_or_return( ($opt:expr, $retval:expr) => (
    match $opt {
        None => return $retval,
        Some(x) => x,
    }
))

#[macro_export]
macro_rules! test_eq( ($name:ident, $left:expr, $right:expr) => (
    #[test]
    fn $name() {
        assert_eq!($left, $right);
    }
))

// Wrap the procedural macro match_atom_impl! so that the
// scrutinee expression is always a single token tree.
#[macro_export]
macro_rules! match_atom( ($scrutinee:expr $body:tt) => (
    match_atom_impl!(($scrutinee) $body)
))

macro_rules! register( ($name:expr, $expand:expr) => (
    register(token::intern($name),
        NormalTT(box BasicMacroExpander {
            expander: $expand,
            span: None
        },
        None));
))

// NB: This needs to be public or we get a linker error.
#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
    register!("named_entities", named_entities::expand);
    register!("static_atom_map", atom::expand_static_atom_map);
    register!("static_atom_array", atom::expand_static_atom_array);
    register!("atom", atom::expand_atom);
    register!("match_atom_impl", atom::expand_match_atom_impl);
}
<commit_msg>Be more consistent about macro_rules! formatting<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_id="html5-macros"]
#![crate_type="dylib"]

#![feature(macro_rules, macro_registrar, quote, managed_boxes)]

extern crate syntax;
extern crate serialize;
extern crate collections;

use syntax::ast::Name;
use syntax::parse::token;
use syntax::ext::base::{SyntaxExtension, BasicMacroExpander, NormalTT};

// Internal macros for use in defining other macros.

#[macro_escape]
macro_rules! bail ( ($msg:expr) => ({
    cx.span_err(sp, $msg);
    return DummyResult::any(sp);
}))

#[macro_escape]
macro_rules! bail_if ( ($e:expr, $msg:expr) => (
    if $e { bail!($msg) }
))

#[macro_escape]
macro_rules! expect ( ($e:expr, $msg:expr) => (
    match $e {
        Some(x) => x,
        None => bail!($msg),
    }
))

mod named_entities;
mod atom;

#[macro_export]
macro_rules! unwrap_or_return ( ($opt:expr, $retval:expr) => (
    match $opt {
        None => return $retval,
        Some(x) => x,
    }
))

#[macro_export]
macro_rules! test_eq ( ($name:ident, $left:expr, $right:expr) => (
    #[test]
    fn $name() {
        assert_eq!($left, $right);
    }
))

// Wrap the procedural macro match_atom_impl! so that the
// scrutinee expression is always a single token tree.
#[macro_export]
macro_rules! match_atom ( ($scrutinee:expr $body:tt) => (
    match_atom_impl!(($scrutinee) $body)
))

macro_rules! register ( ($name:expr, $expand:expr) => (
    register(token::intern($name),
        NormalTT(box BasicMacroExpander {
            expander: $expand,
            span: None
        },
        None));
))

// NB: This needs to be public or we get a linker error.
#[macro_registrar]
pub fn macro_registrar(register: |Name, SyntaxExtension|) {
    register!("named_entities", named_entities::expand);
    register!("static_atom_map", atom::expand_static_atom_map);
    register!("static_atom_array", atom::expand_static_atom_array);
    register!("atom", atom::expand_atom);
    register!("match_atom_impl", atom::expand_match_atom_impl);
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate rand;

use libc::funcs::posix88::unistd;
use std::ffi::CString;
use std::cmp;
use std::env;
use std::os;
use std::ptr;
use rand::Rng;

static VERSION: &'static str = "0.1.0";

fn main() {
    let maybe_args: Option<Vec<String>> = env::args().skip(1).map(|s| { s.into_string().ok() }).collect();
    maybe_args.map_or_else(|| { die_usage() }, |args| {
        match parse_args(&args[]) {
            Err(Exit::Usage) => {
                die_usage();
            }
            Err(Exit::Help) =>
                print_usage(),
            Err(Exit::Version) =>
                print_version(),
            Ok(opts) => {
                if whack(&opts) {
                    env::set_exit_status(1);
                } else {
                    opts.exe.map_or((), |exe| {
                        execvp(exe.name, exe.args)
                    });
                }
            }
        }
    })
}

type ArgParse<T> = Result<T, Exit>;

#[derive(Debug)]
struct Options<'a> {
    chance: i32,
    exe: Option<Exe<'a>>,
}

#[derive(Debug)]
struct Exe<'a> {
    name: &'a str,
    args: &'a[String],
}

#[derive(Debug)]
enum Exit {
    Usage,
    Help,
    Version,
}

fn parse_args(args: &[String]) -> ArgParse<Options> {
    args.uncons().map_or(Err(Exit::Usage), |(s, args)| {
        match &s[] {
            "--help"    | "-h" => Err(Exit::Help),
            "--version" | "-v" => Err(Exit::Version),
            "--chance"  | "-c" => {
                args.uncons().map_or(Err(Exit::Usage), |(s, args)| {
                    s.parse().ok().map_or(Err(Exit::Usage), |val| {
                        args.skip("--").uncons().map_or(
                            Ok(Options {
                                chance: val,
                                exe: None
                            }), |(exe, args)| {
                                Ok(Options {
                                    chance: val,
                                    exe: Some(Exe {
                                        name: &exe[],
                                        args: args,
                                    })
                                })
                            })
                        })
                    })
                }
            _ => Err(Exit::Usage),
        }
    })
}

trait Uncons<'a, A> { fn uncons(&self) -> Option<(&'a A, &'a [A])>; }
trait Skip<'a, A, B> { fn skip(&self, x: A) -> &'a [B]; }

impl<'a, A> Uncons<'a, A> for &'a [A] {
    fn uncons(&self) -> Option<(&'a A, &'a [A])> {
        self.first().map(|x| (x, self.tail()))
    }
}

impl<'a > Skip<'a, &'a str, String> for &'a [String] {
    fn skip(&self, x: &'a str) -> &'a [String] {
        self.uncons().map_or(*self, |(y, ys)| { if x == &y[] { ys } else { *self } })
    }
}

fn whack(opts: &Options) -> bool {
    rand::thread_rng().gen_range(0, 100) > cmp::min(cmp::max(opts.chance, 0), 100)
}

fn execvp(name: &str, args: &[String]) {
    let c_name: CString = CString::from_slice(name.as_bytes());
    let c_args: Vec<CString> = args.iter().map(|tmp| CString::from_slice(tmp.as_bytes())).collect();

    let mut xs: Vec<*const libc::c_char> = Vec::with_capacity(args.len() + 2);

    xs.push(c_name.as_ptr());
    xs.extend(c_args.iter().map(|tmp| tmp.as_ptr()));
    xs.push(ptr::null());

    let c_arg0 = xs[0];
    let c_argv = xs.as_mut_ptr();

    unsafe {
        unistd::execvp(c_arg0, c_argv);
    };

    panic!("execvp(3) failed with: {}", os::last_os_error());
}

fn die_usage() {
    env::set_exit_status(1);
    print_usage();
}

fn print_usage() {
    print_version();
    println!("\n\
        Usage: whacky (-c PERCENTAGE|--chance PERCENTAGE) [[--] COMMAND]\n\
          whacky, yet another randomly failing program\n\
        \n\
        Available options:\n\
          -h,--help           show this help text\n\
          -c,--chance         set success chance");
}

fn print_version() {
    println!("whacky {}", VERSION);
}
<commit_msg>What was that?<commit_after>extern crate libc;
extern crate rand;

use libc::funcs::posix88::unistd;
use std::ffi::CString;
use std::cmp;
use std::env;
use std::os;
use std::ptr;
use rand::Rng;

static VERSION: &'static str = "0.1.0";

fn main() {
    let args: Vec<String> = env::args().skip(1).collect();
    match parse_args(&args[]) {
        Err(Exit::Usage) => {
            die_usage();
        }
        Err(Exit::Help) =>
            print_usage(),
        Err(Exit::Version) =>
            print_version(),
        Ok(opts) => {
            if whack(&opts) {
                env::set_exit_status(1);
            } else {
                opts.exe.map_or((), |exe| {
                    execvp(exe.name, exe.args)
                });
            }
        }
    }
}

type ArgParse<T> = Result<T, Exit>;

#[derive(Debug)]
struct Options<'a> {
    chance: i32,
    exe: Option<Exe<'a>>,
}

#[derive(Debug)]
struct Exe<'a> {
    name: &'a str,
    args: &'a[String],
}

#[derive(Debug)]
enum Exit {
    Usage,
    Help,
    Version,
}

fn parse_args(args: &[String]) -> ArgParse<Options> {
    args.uncons().map_or(Err(Exit::Usage), |(s, args)| {
        match &s[] {
            "--help"    | "-h" => Err(Exit::Help),
            "--version" | "-v" => Err(Exit::Version),
            "--chance"  | "-c" => {
                args.uncons().map_or(Err(Exit::Usage), |(s, args)| {
                    s.parse().ok().map_or(Err(Exit::Usage), |val| {
                        args.skip("--").uncons().map_or(
                            Ok(Options {
                                chance: val,
                                exe: None
                            }), |(exe, args)| {
                                Ok(Options {
                                    chance: val,
                                    exe: Some(Exe {
                                        name: &exe[],
                                        args: args,
                                    })
                                })
                            })
                        })
                    })
                }
            _ => Err(Exit::Usage),
        }
    })
}

trait Uncons<'a, A> { fn uncons(&self) -> Option<(&'a A, &'a [A])>; }
trait Skip<'a, A, B> { fn skip(&self, x: A) -> &'a [B]; }

impl<'a, A> Uncons<'a, A> for &'a [A] {
    fn uncons(&self) -> Option<(&'a A, &'a [A])> {
        self.first().map(|x| (x, self.tail()))
    }
}

impl<'a > Skip<'a, &'a str, String> for &'a [String] {
    fn skip(&self, x: &'a str) -> &'a [String] {
        self.uncons().map_or(*self, |(y, ys)| { if x == &y[] { ys } else { *self } })
    }
}

fn whack(opts: &Options) -> bool {
    rand::thread_rng().gen_range(0, 100) > cmp::min(cmp::max(opts.chance, 0), 100)
}

fn execvp(name: &str, args: &[String]) {
    let c_name: CString = CString::from_slice(name.as_bytes());
    let c_args: Vec<CString> = args.iter().map(|tmp| CString::from_slice(tmp.as_bytes())).collect();

    let mut xs: Vec<*const libc::c_char> = Vec::with_capacity(args.len() + 2);

    xs.push(c_name.as_ptr());
    xs.extend(c_args.iter().map(|tmp| tmp.as_ptr()));
    xs.push(ptr::null());

    let c_arg0 = xs[0];
    let c_argv = xs.as_mut_ptr();

    unsafe {
        unistd::execvp(c_arg0, c_argv);
    };

    panic!("execvp(3) failed with: {}", os::last_os_error());
}

fn die_usage() {
    env::set_exit_status(1);
    print_usage();
}

fn print_usage() {
    print_version();
    println!("\n\
        Usage: whacky (-c PERCENTAGE|--chance PERCENTAGE) [[--] COMMAND]\n\
          whacky, yet another randomly failing program\n\
        \n\
        Available options:\n\
          -h,--help           show this help text\n\
          -c,--chance         set success chance");
}

fn print_version() {
    println!("whacky {}", VERSION);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
use std::process::Command;

fn sc_do(do_matches: &clap::ArgMatches) {
    let mut verbose = false;
    if do_matches.is_present("verbose") {
	verbose = true;
    }
    if let Some(create_droplet_matches) = do_matches.subcommand_matches("create_droplet") {
	if let Some(name) = create_droplet_matches.value_of("name") {
            let config = create_droplet_matches.value_of("config").unwrap_or("small");
            println!("Creating a new droplet [{}] with config: {}", name, config);
            let create_str = format!("doctl compute droplet create {} --image=ubuntu-16-04-x64 --region=sfo1 --size=512mb --wait", name);
            println!("Running command:\n\t\t{}", create_str);
            // Create the actual droplet
            Command::new("sh")
                    .arg("-c")
                    .arg(create_str)
                    .output()
                    .expect("doctl create failed!");
            // Get the IP address!
            let droplet_list_output = Command::new("sh")
                                              .arg("-c")
                                              .arg("doctl compute droplet list --format Name,PublicIPv4,PublicIPv6,Status")
                                              .output()
                                              .expect("doctl create failed!");
            let output_raw = droplet_list_output.stdout;
            let output_str = String::from_utf8(output_raw).expect("Found invalid UTF-8 in droplet list output");
            let lines = output_str.lines();
            let mut ip_address = "";
            for line in lines {
                if line.starts_with(name) {
                    println!("Found: {}", line);
                    let fields : Vec<&str> = line.split_whitespace().collect();
                    if fields.len() < 2 {
                        println!("Couldn't find ip address in line: {}", line);
                        return;
                    }
                    ip_address = fields[1];
                    break;
                }
            }
            if ip_address.len() == 0 {
            	println!("Couldn't locate droplet in output:\n\n{}", output_str);
                return;
            }
            // Create a DNS record to point to the droplet
            let record_str = format!("doctl compute domain records create one.haus --record-type=A --record-data={} --record-name={}", ip_address, name);
            println!("Creating DNS record:\n\t\t{}", record_str);
            Command::new("sh")
                    .arg("-c")
                    .arg(record_str)
                    .output()
                    .expect("doctl create record failed failed!");
	    // Configure the droplet
	}
    }
}

fn main() {
    let matches = clap_app!(myapp =>
        (version: "0.0.1")
        (author: "Michael Xu <michaeljxu11@gmail.com>")
        (about: "One stop shop for common command line goodness")
        (@arg verbose: -v ... "Enable verbose output")
        (@subcommand do =>
            (about: "Doctl wrapper")
            (version: "0.0.0")
            (author: "Michael Xu <michaeljxu11@gmail.com>")
            (@arg verbose: -v --verbose "Print test information verbosely")
            (@subcommand create_droplet =>
                (about: "Create a new droplet")
                (@arg name: +required "Which configuration to use [small|medium|large]")
                (@arg config: -c "Which configuration to use [small|medium|large]")
            )
        )
    ).get_matches();

    // Vary the output based on how many times the user used the "verbose" flag
    // (i.e. 'myprog -v -v -v' or 'myprog -vvv' vs 'myprog -v'
    match matches.occurrences_of("v") {
        0 => println!("No verbose info"),
        1 => println!("Some verbose info"),
        2 => println!("Tons of verbose info"),
        3 | _ => println!("Don't be crazy"),
    }

    // You can handle information about subcommands by requesting their matches by name
    // (as below), requesting just the name used, or both at the same time
    if let Some(matches) = matches.subcommand_matches("do") {
	sc_do(matches);
    }
}
<commit_msg>fixed help strings<commit_after>#[macro_use]
extern crate clap;
use std::process::Command;

fn sc_do(do_matches: &clap::ArgMatches) {
    let mut verbose = false;
    if do_matches.is_present("verbose") {
	verbose = true;
    }
    if let Some(create_droplet_matches) = do_matches.subcommand_matches("create_droplet") {
	if let Some(name) = create_droplet_matches.value_of("name") {
            let config = create_droplet_matches.value_of("config").unwrap_or("small");
            println!("Creating a new droplet [{}] with config: {}", name, config);
            let create_str = format!("doctl compute droplet create {} --image=ubuntu-16-04-x64 --region=sfo1 --size=512mb --wait", name);
            println!("Running command:\n\t\t{}", create_str);
            // Create the actual droplet
            Command::new("sh")
                    .arg("-c")
                    .arg(create_str)
                    .output()
                    .expect("doctl create failed!");
            // Get the IP address!
            let droplet_list_output = Command::new("sh")
                                              .arg("-c")
                                              .arg("doctl compute droplet list --format Name,PublicIPv4,PublicIPv6,Status")
                                              .output()
                                              .expect("doctl create failed!");
            let output_raw = droplet_list_output.stdout;
            let output_str = String::from_utf8(output_raw).expect("Found invalid UTF-8 in droplet list output");
            let lines = output_str.lines();
            let mut ip_address = "";
            for line in lines {
                if line.starts_with(name) {
                    println!("Found: {}", line);
                    let fields : Vec<&str> = line.split_whitespace().collect();
                    if fields.len() < 2 {
                        println!("Couldn't find ip address in line: {}", line);
                        return;
                    }
                    ip_address = fields[1];
                    break;
                }
            }
            if ip_address.len() == 0 {
            	println!("Couldn't locate droplet in output:\n\n{}", output_str);
                return;
            }
            // Create a DNS record to point to the droplet
            let record_str = format!("doctl compute domain records create one.haus --record-type=A --record-data={} --record-name={}", ip_address, name);
            println!("Creating DNS record:\n\t\t{}", record_str);
            Command::new("sh")
                    .arg("-c")
                    .arg(record_str)
                    .output()
                    .expect("doctl create record failed failed!");
	    // Configure the droplet
	}
    }
}

fn main() {
    let matches = clap_app!(myapp =>
        (version: "0.0.1")
        (author: "Michael Xu <michaeljxu11@gmail.com>")
        (about: "One stop shop for common command line goodness")
        (@arg verbose: -v ... "Enable verbose output")
        (@subcommand do =>
            (about: "Doctl wrapper")
            (version: "0.0.0")
            (author: "Michael Xu <michaeljxu11@gmail.com>")
            (@arg verbose: -v --verbose "Print test information verbosely")
            (@subcommand create_droplet =>
                (about: "Create a new droplet")
                (@arg name: +required "Name of the droplet, must be unique")
                (@arg config: -c "Which configuration to use [small|medium|large]")
            )
            (@subcommand destroy_droplet =>
                (about: "Destroy a droplet by name")
                (@arg name: +required "Name of the droplet to destroy completely")
            )
        )
    ).get_matches();

    // Vary the output based on how many times the user used the "verbose" flag
    // (i.e. 'myprog -v -v -v' or 'myprog -vvv' vs 'myprog -v'
    match matches.occurrences_of("v") {
        0 => println!("No verbose info"),
        1 => println!("Some verbose info"),
        2 => println!("Tons of verbose info"),
        3 | _ => println!("Don't be crazy"),
    }

    // You can handle information about subcommands by requesting their matches by name
    // (as below), requesting just the name used, or both at the same time
    if let Some(matches) = matches.subcommand_matches("do") {
	sc_do(matches);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;
extern crate toml;
extern crate getopts;
use std::env;
use std::process;
use getopts::Options;
use getopts::ParsingStyle;

const DEFAULT_CONF_PATH: &str = "~/.config/openby/config";

#[allow(dead_code)]
#[derive(Deserialize)]
struct Config {
    version: toml::Value,
    tools: Vec<Tools>,
}

#[allow(dead_code)]
#[derive(Deserialize)]
struct Tools {
    command: toml::Value,
    extentions: toml::value::Array,
}

fn main() {
    let exit_code = match run() {
        Ok(_) => 0,
        Err(e) => e,
    };
    process::exit(exit_code);
}

fn run() -> Result<i32, i32> {
    let args: Vec<String> = env::args().collect();
    let args_str: Vec<&str> = args.iter().map(|s| s.as_str()).collect();
    let (file_name, conf_name) = parse_options(args_str)?;
    println!("Ok: {} {}", file_name, conf_name);
    Ok(0)
}

fn parse_options(args: Vec<&str>) -> Result<(String, String), i32> {
    let ref program = &args[0];

    let mut opts = Options::new();
    opts.parsing_style(ParsingStyle::FloatingFrees);
    opts.optopt("c", "config", "specify configure file name", "CONFIG");
    opts.optflag("h", "help", "print this help menu");

    let matches = opts.parse(&args[1..]).unwrap();

    if matches.opt_present("h") {
        print_usage(&program, &opts);
        return Err(0);
    }

    let file_name = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, &opts);
        return Err(1);
    };

    let conf_name = if let Some(c) = matches.opt_str("c") {
        c
    } else {
        DEFAULT_CONF_PATH.to_string()
    };

    Ok((file_name, conf_name))
}

fn print_usage(program: &str, opts: &Options) {
    let brief = format!("Usage: {} [options] FILE", program);
    print!("{}", opts.usage(&brief));
}

#[test]
fn test_parse_options() {
    let no_arguments = vec!["openby", "input.file", "-c", "configure.file"];

    assert_eq!(Err(1), parse_options(no_arguments[0..1]));
    assert_eq!(Ok(("input.file".to_string(), DEFAULT_CONF_PATH.to_string())),
               parse_options(no_arguments[0..2]));
    assert_eq!(Ok(("input.file".to_string(), "configure.file".to_string())),
               parse_options(no_arguments));
}

#[test]
fn test_decode_toml() {
    let toml_config_str = r#"
    version = 0.0

    [[tools]]
    command = "apvlv"
    extentions = [ "pdf" ]

    [[tools]]
    command = "mirage"
    extentions = [ "jpg", "png", "gif" ]

    [[tools]]
    command = "vlc"
    extentions = [ "mp4", "mov", "avi" ]

    [[tools]]
    command = "vim -R"
    extentions = [ "conf" ]
    "#;

    let config: Config = toml::from_str(toml_config_str).unwrap();
    assert_eq!(config.version, toml::Value::Float(0.0));

    assert_eq!(config.tools[0].command,
               toml::Value::String("apvlv".to_string()));
    assert_eq!(config.tools[0].extentions[0],
               toml::Value::String("pdf".to_string()));

    assert_eq!(config.tools[1].command,
               toml::Value::String("mirage".to_string()));
    assert_eq!(config.tools[1].extentions[0],
               toml::Value::String("jpg".to_string()));
    assert_eq!(config.tools[1].extentions[1],
               toml::Value::String("png".to_string()));
    assert_eq!(config.tools[1].extentions[2],
               toml::Value::String("gif".to_string()));

    assert_eq!(config.tools[2].command,
               toml::Value::String("vlc".to_string()));
    assert_eq!(config.tools[2].extentions[0],
               toml::Value::String("mp4".to_string()));
    assert_eq!(config.tools[2].extentions[1],
               toml::Value::String("mov".to_string()));
    assert_eq!(config.tools[2].extentions[2],
               toml::Value::String("avi".to_string()));

    assert_eq!(config.tools[3].command,
               toml::Value::String("vim -R".to_string()));
    assert_eq!(config.tools[3].extentions[0],
               toml::Value::String("conf".to_string()));
}
<commit_msg>load TOML config file<commit_after>#[macro_use]
extern crate serde_derive;
extern crate toml;
extern crate getopts;
use std::env;
use std::fs;
use std::io;
use std::io::prelude::*;
use std::io::Write;
use std::path;
use std::process;
use getopts::Options;
use getopts::ParsingStyle;

const DEFAULT_CONF_PATH: &str = "~/.config/openby/config";

#[derive(Debug)]
enum AppError {
    Io(io::Error),
    Toml(toml::de::Error),
}

#[allow(dead_code)]
#[derive(Deserialize)]
struct Config {
    version: toml::Value,
    tools: Vec<Tools>,
}

#[allow(dead_code)]
#[derive(Deserialize)]
struct Tools {
    command: toml::Value,
    extentions: toml::value::Array,
}

fn main() {
    let exit_code = match run() {
        Ok(_) => 0,
        Err(e) => {
            writeln!(&mut io::stderr(), "{:?}", e).unwrap();
            1
        }
    };
    process::exit(exit_code);
}

fn run() -> Result<i32, AppError> {
    let args: Vec<String> = env::args().collect();
    let args_str: Vec<&str> = args.iter().map(|s| s.as_str()).collect();
    let (file_name, conf_name) = parse_options(args_str)?;
    println!("Ok: {} {}", file_name, conf_name);

    load_config(conf_name)?;

    Ok(0)
}

fn parse_options(args: Vec<&str>) -> Result<(String, String), AppError> {
    let ref program = &args[0];

    let mut opts = Options::new();
    opts.parsing_style(ParsingStyle::FloatingFrees);
    opts.optopt("c", "config", "specify configure file name", "CONFIG");
    opts.optflag("h", "help", "print this help menu");

    let matches = opts.parse(&args[1..]).unwrap();

    if matches.opt_present("h") {
        print_usage(&program, &opts);
        process::exit(0);
    }

    let file_name = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, &opts);
        return Result::Err(AppError::Io(io::Error::new(io::ErrorKind::NotFound,
                                                       "FILE is not found")));
    };

    let conf_name = if let Some(c) = matches.opt_str("c") {
        c
    } else {
        DEFAULT_CONF_PATH.to_string()
    };

    Ok((file_name, conf_name))
}

fn print_usage(program: &str, opts: &Options) {
    let brief = format!("Usage: {} [options] FILE", program);
    println!("{}", opts.usage(&brief));
}

fn load_config(conf_name: String) -> Result<Config, AppError> {
    let path = path::Path::new(conf_name.as_str());
    if path.exists() == false {
        return Result::Err(AppError::Io(io::Error::new(io::ErrorKind::NotFound,
                                                       format!("{} is not exist",
                                                               path.to_str().unwrap_or("")))));
    }

    let mut reader = io::BufReader::new(fs::File::open(path).map_err(AppError::Io)?);
    let mut s = String::new();
    reader.read_to_string(&mut s).map_err(AppError::Io)?;

    let config: Config = toml::from_str(s.as_str()).map_err(AppError::Toml)?;

    Ok(config)
}

#[test]
fn test_parse_options() {
    let no_arguments = vec!["openby", "input.file", "-c", "configure.file"];

    assert_eq!(Err(1), parse_options(no_arguments[0..1]));
    assert_eq!(Ok(("input.file".to_string(), DEFAULT_CONF_PATH.to_string())),
               parse_options(no_arguments[0..2]));
    assert_eq!(Ok(("input.file".to_string(), "configure.file".to_string())),
               parse_options(no_arguments));
}

#[test]
fn test_decode_toml() {
    let toml_config_str = r#"
    version = 0.0

    [[tools]]
    command = "apvlv"
    extentions = [ "pdf" ]

    [[tools]]
    command = "mirage"
    extentions = [ "jpg", "png", "gif" ]

    [[tools]]
    command = "vlc"
    extentions = [ "mp4", "mov", "avi" ]

    [[tools]]
    command = "vim -R"
    extentions = [ "conf" ]
    "#;

    let config: Config = toml::from_str(toml_config_str).unwrap();
    assert_eq!(config.version, toml::Value::Float(0.0));

    assert_eq!(config.tools[0].command,
               toml::Value::String("apvlv".to_string()));
    assert_eq!(config.tools[0].extentions[0],
               toml::Value::String("pdf".to_string()));

    assert_eq!(config.tools[1].command,
               toml::Value::String("mirage".to_string()));
    assert_eq!(config.tools[1].extentions[0],
               toml::Value::String("jpg".to_string()));
    assert_eq!(config.tools[1].extentions[1],
               toml::Value::String("png".to_string()));
    assert_eq!(config.tools[1].extentions[2],
               toml::Value::String("gif".to_string()));

    assert_eq!(config.tools[2].command,
               toml::Value::String("vlc".to_string()));
    assert_eq!(config.tools[2].extentions[0],
               toml::Value::String("mp4".to_string()));
    assert_eq!(config.tools[2].extentions[1],
               toml::Value::String("mov".to_string()));
    assert_eq!(config.tools[2].extentions[2],
               toml::Value::String("avi".to_string()));

    assert_eq!(config.tools[3].command,
               toml::Value::String("vim -R".to_string()));
    assert_eq!(config.tools[3].extentions[0],
               toml::Value::String("conf".to_string()));
}
<|endoftext|>


<commit_before>use std::env;
use std::fs::File;
use std::error::Error;
use std::io::prelude::*;
use std::io::BufWriter;
extern crate time;
extern crate toml;

mod decoders;

fn usage() {
  println!("rawloader <file>");
  std::process::exit(1);
}

fn error(err: &str) {
  println!("ERROR: {}", err);
  std::process::exit(2);
}

fn main() {
  let args: Vec<_> = env::args().collect();
  if args.len() != 2 {
    usage();
  }
  let file = &args[1];
  println!("Loading file \"{}\"", file);

  let rawloader = decoders::RawLoader::new();
  let from_time = time::precise_time_ns();
  let image = match rawloader.decode_safe(file) {
    Ok(val) => val,
    Err(e) => {error(&e);unreachable!()},
  };
  let to_time = time::precise_time_ns();
  println!("Decoded in {} ms", (to_time - from_time)/1000000);

  println!("Found camera \"{}\" model \"{}\"", image.make, image.model);
  println!("Found canonical named camera \"{}\" model \"{}\"", image.canonical_make, image.canonical_model);
  println!("Image size is {}x{}", image.width, image.height);
  println!("WB coeffs are {:?}", image.wb_coeffs);
  println!("black levels are {:?}", image.blacklevels);
  println!("white levels are {:?}", image.whitelevels);
  println!("color matrix is {:?}", image.color_matrix);
  println!("dcraw filters is {:#x}", image.dcraw_filters);
  println!("crops are {:?}", image.crops);

  let mut sum: u64 = 0;
  for i in 0..(image.width*image.height) {
    sum += image.data[i as usize] as u64;
  }
  println!("Image sum: {}", sum);
  let count: u64 = (image.width as u64) * (image.height as u64);
  println!("Image avg: {}", sum/count);

  let uf = match File::create(format!("{}.ppm",file)) {
    Ok(val) => val,
    Err(e) => {error(e.description());unreachable!()},
  };
  let mut f = BufWriter::new(uf);
  let preamble = format!("P6 {} {} {}\n", image.width, image.height, image.whitelevels[0]).into_bytes();
  if let Err(err) = f.write_all(&preamble) {
    error(err.description());
  }
  for row in 0..image.height {
    let from: usize = (row as usize) * (image.width as usize);
    let to: usize = ((row+1) as usize) * (image.width as usize);
    let imgline = &image.data[from .. to];

    for pixel in imgline {
      let bytes = [(pixel>>4) as u8, (pixel&0x0f) as u8, (pixel>>4) as u8, (pixel&0x0f) as u8, (pixel>>4) as u8, (pixel&0x0f) as u8];
       if let Err(err) = f.write_all(&bytes) {
        error(err.description());
      }
    }
  }
}
<commit_msg>Use the crate itself in main.rs<commit_after>use std::env;
use std::fs::File;
use std::error::Error;
use std::io::prelude::*;
use std::io::BufWriter;
extern crate time;
extern crate toml;
extern crate rawloader;
use rawloader::decoders;

fn usage() {
  println!("rawloader <file>");
  std::process::exit(1);
}

fn error(err: &str) {
  println!("ERROR: {}", err);
  std::process::exit(2);
}

fn main() {
  let args: Vec<_> = env::args().collect();
  if args.len() != 2 {
    usage();
  }
  let file = &args[1];
  println!("Loading file \"{}\"", file);

  let rawloader = decoders::RawLoader::new();
  let from_time = time::precise_time_ns();
  let image = match rawloader.decode_safe(file) {
    Ok(val) => val,
    Err(e) => {error(&e);unreachable!()},
  };
  let to_time = time::precise_time_ns();
  println!("Decoded in {} ms", (to_time - from_time)/1000000);

  println!("Found camera \"{}\" model \"{}\"", image.make, image.model);
  println!("Found canonical named camera \"{}\" model \"{}\"", image.canonical_make, image.canonical_model);
  println!("Image size is {}x{}", image.width, image.height);
  println!("WB coeffs are {:?}", image.wb_coeffs);
  println!("black levels are {:?}", image.blacklevels);
  println!("white levels are {:?}", image.whitelevels);
  println!("color matrix is {:?}", image.color_matrix);
  println!("dcraw filters is {:#x}", image.dcraw_filters);
  println!("crops are {:?}", image.crops);

  let mut sum: u64 = 0;
  for i in 0..(image.width*image.height) {
    sum += image.data[i as usize] as u64;
  }
  println!("Image sum: {}", sum);
  let count: u64 = (image.width as u64) * (image.height as u64);
  println!("Image avg: {}", sum/count);

  let uf = match File::create(format!("{}.ppm",file)) {
    Ok(val) => val,
    Err(e) => {error(e.description());unreachable!()},
  };
  let mut f = BufWriter::new(uf);
  let preamble = format!("P6 {} {} {}\n", image.width, image.height, image.whitelevels[0]).into_bytes();
  if let Err(err) = f.write_all(&preamble) {
    error(err.description());
  }
  for row in 0..image.height {
    let from: usize = (row as usize) * (image.width as usize);
    let to: usize = ((row+1) as usize) * (image.width as usize);
    let imgline = &image.data[from .. to];

    for pixel in imgline {
      let bytes = [(pixel>>4) as u8, (pixel&0x0f) as u8, (pixel>>4) as u8, (pixel&0x0f) as u8, (pixel>>4) as u8, (pixel&0x0f) as u8];
       if let Err(err) = f.write_all(&bytes) {
        error(err.description());
      }
    }
  }
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate vecmath;
extern crate rayon;

mod vec3d;
mod light;
mod scene;
mod material;
mod color;
mod shape;
mod sphere;
mod plane;

use scene::Scene;

use sdl2::pixels::PixelFormatEnum;
use sdl2::rect::Rect;
use sdl2::EventPump;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use std::time::Instant;

use rayon::prelude::*;

// Return true for quit
fn handle_events(scene: &mut Scene,
                 resolution: u32,
                 event_pump: &mut EventPump,
                 x: i32,
                 y: i32)
                 -> bool {
    for event in event_pump.poll_iter() {
        match event {
            Event::Quit { .. } |
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => return true,
            Event::KeyDown { keycode: Some(Keycode::W), .. } => {
                scene.mv_camera_fwd();
            }
            Event::KeyDown { keycode: Some(Keycode::S), .. } => {
                scene.mv_camera_back();
            }
            _ => {}
        }
    }

    // TODO: Y rotation is incorrect
    let x_dist = ((resolution as i32) / 2) - x;
    let y_dist = ((resolution as i32) / 2) - y;
    let x_rot = x_dist as f64 * (-0.001);
    let y_rot = y_dist as f64 * (-0.001);
    scene.rot_camera(x_rot, y_rot);
    false
}

// Test scene
fn test_scene() -> Scene {
    use light::Light;
    use vec3d::Vec3d;
    use sphere::Sphere;
    use plane::Plane;

    let camera_pos: Vec3d = [0.0, 0.0, -100.0];

    let camera_dir: Vec3d = [0.0, 0.0, 1.0];
    let camera_up: Vec3d = [0.0, 1.0, 0.0];
    let light_pos: Vec3d = [50.0, 5.0, -100.0];

    let light = Light::new(light_pos, color::Color(0.6, 0.6, 0.6));
    let mut scene = Scene::new(light, camera_pos, camera_dir, camera_up);
    scene.add_shape(Box::new(Sphere::new([-20.0, -15.0, 45.0], 5.0, color::Color(1.0, 0.5, 0.5))));
    scene.add_shape(Box::new(Sphere::new([15.0, -10.0, 35.0], 5.0, color::Color(0.4, 0.4, 0.4))));
    scene.add_shape(Box::new(Sphere::new([0.0, -10.0, 25.0], 5.0, color::Color(0.5, 0.5, 1.0))));
    scene.add_shape(Box::new(Sphere::new([0.0, -120.0, 55.0], 100.0, color::WHITE)));
    scene.add_shape(Box::new(Sphere::new([0.0, 120.0, 55.0], 100.0, color::Color(1.0, 1.0, 0.0))));
    scene.add_shape(Box::new(Sphere::new([0.0, 0.0, 200.0], 100.0, color::Color(1.0, 0.5, 1.0))));
    scene.add_shape(Box::new(Sphere::from_material([15.0, 0.0, 40.0], 5.0, material::MIRROR)));
    scene.add_shape(Box::new(Sphere::new([-45.0, 0.0, 45.0], 20.0, color::Color(0.1, 0.1, 0.1))));

    scene.add_shape(Box::new(Plane::new([0.0, -200.0, 0.0], [0.0, 1.0, 0.0], color::Color(0.4, 0.4, 0.4))));
    scene.add_shape(Box::new(Plane::new([0.0, 200.0, 0.0], [0.0, -1.0, 0.0], color::Color(0.4, 0.4, 0.4))));
    scene.add_shape(Box::new(Plane::from_material([200.0, 0.0, 0.0], [-1.0, 0.0, 0.0], material::MIRROR)));
    scene.add_shape(Box::new(Plane::new([-200.0, 0.0, 0.0], [1.0, 0.0, 0.0], color::Color(0.8, 0.4, 0.8))));
    scene.add_shape(Box::new(Plane::new([0.0, 0.0, 200.0], [0.0, 0.0, -1.0], color::Color(0.4, 0.4, 0.4))));
    scene.add_shape(Box::new(Plane::new([0.0, 0.0, -200.0], [0.0, 0.0, 1.0], color::Color(0.4, 0.4, 0.4))));
    scene
}

// A simple test code that uses SDL for rendering
fn main() {
    let resolution: u32 = 512;
    let res_u = resolution as usize;
    let mut scene = test_scene();

    // Stuff from sdl2-rust example
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window = video_subsystem.window("Ray", resolution, resolution)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    let mut renderer = window.renderer().build().unwrap();

    let mut texture =
        renderer.create_texture_streaming(PixelFormatEnum::RGB24, resolution, resolution)
            .unwrap();

    let mut event_pump = sdl_context.event_pump().unwrap();

    let mut lines: Vec<(usize, Vec<(u8, u8, u8)>)> = Vec::new();
    for line_no in 0..res_u {
        lines.push((line_no, Vec::with_capacity(res_u)));
    }

    let mut frame_cnt = 0;
    let mut time_stamp = Instant::now();
    loop {
        let (_, x, y) = sdl_context.mouse().mouse_state();
        let quit = handle_events(&mut scene, resolution, &mut event_pump, x, y);
        if quit {
            break;
        }

        if frame_cnt == 10 {
            let elapsed = time_stamp.elapsed();
            let msecs = (elapsed.as_secs() * 1000) as u64 + (elapsed.subsec_nanos() as u64 / 1000000);
            time_stamp = Instant::now();
            println!("FPS {}", (frame_cnt as f32) / (msecs as f32 / 1000.0));
            frame_cnt = 0;
        }

        scene.step();

        lines.par_iter_mut().for_each(|tup| {
            let (line_no, ref mut vec) = *tup;
            vec.drain(..);
            scene.line_iter_u8(res_u, res_u, line_no).fold((), |(), x| vec.push(x));
        });

        texture.with_lock(None, |buffer: &mut [u8], pitch: usize| {
                for tup in lines.iter() {
                    let (line_no, ref vec) = *tup;
                    let line_start = line_no * pitch;
                    let line_end = line_start + res_u * 3;
                    let line_buf = &mut buffer[line_start..line_end];
                    for (c, offset) in vec.iter().zip((0..).map(|x| 3 * x)) {
                        line_buf[offset + 0] = c.0;
                        line_buf[offset + 1] = c.1;
                        line_buf[offset + 2] = c.2;
                    }
                }
            }).unwrap();
        renderer.clear();
        renderer.copy(&texture,
                  None,
                  Some(Rect::new(0, 0, resolution, resolution)))
            .unwrap();
        renderer.present();
        frame_cnt += 1;
    }
}
<commit_msg>Make the vec iteration more readable<commit_after>extern crate sdl2;
extern crate vecmath;
extern crate rayon;

mod vec3d;
mod light;
mod scene;
mod material;
mod color;
mod shape;
mod sphere;
mod plane;

use scene::Scene;

use sdl2::pixels::PixelFormatEnum;
use sdl2::rect::Rect;
use sdl2::EventPump;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use std::time::Instant;

use rayon::prelude::*;

// Return true for quit
fn handle_events(scene: &mut Scene,
                 resolution: u32,
                 event_pump: &mut EventPump,
                 x: i32,
                 y: i32)
                 -> bool {
    for event in event_pump.poll_iter() {
        match event {
            Event::Quit { .. } |
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => return true,
            Event::KeyDown { keycode: Some(Keycode::W), .. } => {
                scene.mv_camera_fwd();
            }
            Event::KeyDown { keycode: Some(Keycode::S), .. } => {
                scene.mv_camera_back();
            }
            _ => {}
        }
    }

    // TODO: Y rotation is incorrect
    let x_dist = ((resolution as i32) / 2) - x;
    let y_dist = ((resolution as i32) / 2) - y;
    let x_rot = x_dist as f64 * (-0.001);
    let y_rot = y_dist as f64 * (-0.001);
    scene.rot_camera(x_rot, y_rot);
    false
}

// Test scene
fn test_scene() -> Scene {
    use light::Light;
    use vec3d::Vec3d;
    use sphere::Sphere;
    use plane::Plane;

    let camera_pos: Vec3d = [0.0, 0.0, -100.0];

    let camera_dir: Vec3d = [0.0, 0.0, 1.0];
    let camera_up: Vec3d = [0.0, 1.0, 0.0];
    let light_pos: Vec3d = [50.0, 5.0, -100.0];

    let light = Light::new(light_pos, color::Color(0.6, 0.6, 0.6));
    let mut scene = Scene::new(light, camera_pos, camera_dir, camera_up);
    scene.add_shape(Box::new(Sphere::new([-20.0, -15.0, 45.0], 5.0, color::Color(1.0, 0.5, 0.5))));
    scene.add_shape(Box::new(Sphere::new([15.0, -10.0, 35.0], 5.0, color::Color(0.4, 0.4, 0.4))));
    scene.add_shape(Box::new(Sphere::new([0.0, -10.0, 25.0], 5.0, color::Color(0.5, 0.5, 1.0))));
    scene.add_shape(Box::new(Sphere::new([0.0, -120.0, 55.0], 100.0, color::WHITE)));
    scene.add_shape(Box::new(Sphere::new([0.0, 120.0, 55.0], 100.0, color::Color(1.0, 1.0, 0.0))));
    scene.add_shape(Box::new(Sphere::new([0.0, 0.0, 200.0], 100.0, color::Color(1.0, 0.5, 1.0))));
    scene.add_shape(Box::new(Sphere::from_material([15.0, 0.0, 40.0], 5.0, material::MIRROR)));
    scene.add_shape(Box::new(Sphere::new([-45.0, 0.0, 45.0], 20.0, color::Color(0.1, 0.1, 0.1))));

    scene.add_shape(Box::new(Plane::new([0.0, -200.0, 0.0], [0.0, 1.0, 0.0], color::Color(0.4, 0.4, 0.4))));
    scene.add_shape(Box::new(Plane::new([0.0, 200.0, 0.0], [0.0, -1.0, 0.0], color::Color(0.4, 0.4, 0.4))));
    scene.add_shape(Box::new(Plane::from_material([200.0, 0.0, 0.0], [-1.0, 0.0, 0.0], material::MIRROR)));
    scene.add_shape(Box::new(Plane::new([-200.0, 0.0, 0.0], [1.0, 0.0, 0.0], color::Color(0.8, 0.4, 0.8))));
    scene.add_shape(Box::new(Plane::new([0.0, 0.0, 200.0], [0.0, 0.0, -1.0], color::Color(0.4, 0.4, 0.4))));
    scene.add_shape(Box::new(Plane::new([0.0, 0.0, -200.0], [0.0, 0.0, 1.0], color::Color(0.4, 0.4, 0.4))));
    scene
}

// A simple test code that uses SDL for rendering
fn main() {
    let resolution: u32 = 512;
    let res_u = resolution as usize;
    let mut scene = test_scene();

    // Stuff from sdl2-rust example
    let sdl_context = sdl2::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window = video_subsystem.window("Ray", resolution, resolution)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    let mut renderer = window.renderer().build().unwrap();

    let mut texture =
        renderer.create_texture_streaming(PixelFormatEnum::RGB24, resolution, resolution)
            .unwrap();

    let mut event_pump = sdl_context.event_pump().unwrap();

    let mut lines: Vec<(usize, Vec<(u8, u8, u8)>)> = Vec::new();
    for line_no in 0..res_u {
        lines.push((line_no, Vec::with_capacity(res_u)));
    }

    let mut frame_cnt = 0;
    let mut time_stamp = Instant::now();
    loop {
        let (_, x, y) = sdl_context.mouse().mouse_state();
        let quit = handle_events(&mut scene, resolution, &mut event_pump, x, y);
        if quit {
            break;
        }

        if frame_cnt == 10 {
            let elapsed = time_stamp.elapsed();
            let msecs = (elapsed.as_secs() * 1000) as u64 + (elapsed.subsec_nanos() as u64 / 1000000);
            time_stamp = Instant::now();
            println!("FPS {}", (frame_cnt as f32) / (msecs as f32 / 1000.0));
            frame_cnt = 0;
        }

        scene.step();

        lines.par_iter_mut().for_each(|tup| {
            let (line_no, ref mut vec) = *tup;
            vec.clear();
            vec.extend(scene.line_iter_u8(res_u, res_u, line_no));
        });

        texture.with_lock(None, |buffer: &mut [u8], pitch: usize| {
                for tup in lines.iter() {
                    let (line_no, ref vec) = *tup;
                    let line_start = line_no * pitch;
                    let line_end = line_start + res_u * 3;
                    let line_buf = &mut buffer[line_start..line_end];
                    for (c, offset) in vec.iter().zip((0..).map(|x| 3 * x)) {
                        line_buf[offset + 0] = c.0;
                        line_buf[offset + 1] = c.1;
                        line_buf[offset + 2] = c.2;
                    }
                }
            }).unwrap();
        renderer.clear();
        renderer.copy(&texture,
                  None,
                  Some(Rect::new(0, 0, resolution, resolution)))
            .unwrap();
        renderer.present();
        frame_cnt += 1;
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(regex_macros)]
#![feature(collections)]

extern crate argparse;
extern crate html5ever;
extern crate html5ever_dom_sink;
extern crate hyper;
extern crate iron;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate rand;
extern crate regex;
extern crate rustc_serialize;
extern crate tempfile;
extern crate tendril;
extern crate url;

/// Helper macro for unwrapping Result values whose E types implement std::fmt::Display. For Ok(),
/// evaluates to the contained value. For Err(), returns early with an Err containing the formatted
/// error.
macro_rules! try_display {
    ($expr:expr, $($format_arg:expr),* ) => (match $expr {
        Ok(val) => val,
        Err(err) => return Err(format!("{}: {}", format!($($format_arg),*), err)),
    })
}

mod json;
mod wiki;

use argparse::ArgumentParser;
use argparse::Store;
//use collections::borrow::Borrow;
use std::fs::OpenOptions;
use std::io::Read;
use std::io::Write;
use std::process::Command;
use std::process::Stdio;
use std::str::FromStr;

use html5ever::Attribute;
use html5ever::tree_builder::interface::TreeSink;
use html5ever_dom_sink::common::NodeEnum;
use html5ever_dom_sink::rcdom::Handle;
use html5ever_dom_sink::rcdom::RcDom;
use hyper::Client;
use hyper::header::Connection;
use iron::Iron;
use iron::IronResult;
use iron::Request;
use iron::Response;
use iron::headers::ContentType;
use iron::middleware::Handler;
use iron::mime::Mime;
use iron::mime::SubLevel;
use iron::mime::TopLevel;
use tempfile::NamedTempFile;

use wiki::Revision;
use wiki::Wiki;

// TODO: consider doing s/en.wikipedia.org/this app's url/ on the HTML before serving it. This
// currently works fine, but might not over HTTPS.

/// Does a 3-way merge, merging `new1` and `new2` under the assumption that both diverged from
/// `old`. Returns None if the strings do not merge together cleanly.
fn merge(old: &str, new1: &str, new2: &str) -> Result<Option<String>, String> {
    fn write_to_temp_file(contents: &str) -> Result<NamedTempFile, String> {
        let tempfile = try_display!(NamedTempFile::new(), "Error creating temp file");
        let mut file = try_display!(OpenOptions::new().write(true).open(tempfile.path()),
                                    "Error opening temp file for writing");
        try_display!(file.write_all(contents.as_bytes()), "Error writing to temp file");
        try_display!(file.flush(), "Error flushing temp file");
        Ok(tempfile)
    }

    let old_tempfile = try!(write_to_temp_file(old));
    let new1_tempfile = try!(write_to_temp_file(new1));
    let new2_tempfile = try!(write_to_temp_file(new2));

    let mut process = Command::new("diff3");
    process.arg("-m").args(&[new1_tempfile.path(), old_tempfile.path(), new2_tempfile.path()])
        .stdout(Stdio::piped()).stderr(Stdio::null());
    let output = try_display!(process.output(), "Error getting output from diff3 subprocess");
    if output.status.success() {
        Ok(Some(try_display!(String::from_utf8(output.stdout),
                             "Error converting diff3 output to UTF-8")))
    } else {
        Ok(None)
    }
}

fn replace_node_with_placeholder(original_html: &str, div_id: &str, placeholder: &str)
    -> Result<String, String> {
    let html = tendril::StrTendril::from_str(original_html).unwrap();
    let mut dom: RcDom = html5ever::parse(html5ever::one_input(html), Default::default());

    let handle = try!(find_node_by_id(&dom.get_document(), div_id));
    let child_handles =
        (&handle.borrow().children).into_iter().map(|child| child.clone()).collect::<Vec<_>>();
    for child_handle in child_handles {
        dom.remove_from_parent(child_handle);
    }
    dom.append(handle,
               html5ever::tree_builder::interface::NodeOrText::AppendText(
                   tendril::StrTendril::from_str(placeholder).unwrap()));
    let mut serialized: Vec<u8> = vec![];
    html5ever::serialize::serialize(&mut serialized, &dom.document, Default::default());
    Ok(try_display!(String::from_utf8(serialized),
                    "Error converting serialized HTML to UTF-8 string"))
}

fn find_node_by_id(handle: &Handle, id: &str) -> Result<Handle, String> {
    fn has_matching_id(attributes: &Vec<Attribute>, id: &str) -> bool {
        return attributes.into_iter().any(
            |attribute| attribute.name.local.as_slice() == "id" &&
                format!("{}", attribute.value) == id);
    }

    let node = handle.borrow();
    match node.node {
        NodeEnum::Element(_, ref attributes) if has_matching_id(attributes, id) => Ok(handle.clone()),
        _ => (&node.children).into_iter()
            .map(|child| find_node_by_id(child, id))
            .filter(|result| result.is_ok())
            .map(|result| result.unwrap())
            .next().ok_or(format!("No node with ID {} found", id)),
    }
}

struct WikipediaMinusWikipediansHandler {
    wiki: Wiki,
    client: Client
}

impl WikipediaMinusWikipediansHandler {
    fn new(wiki: Wiki, client: Client) -> WikipediaMinusWikipediansHandler {
        WikipediaMinusWikipediansHandler { wiki: wiki, client: client }
    }

    /// Returns a vector of Revisions representing all reversions of vandalism for the page `title`.
    fn get_vandalism_reversions(&self, title: &str) -> Result<Vec<Revision>, String> {
        // TODO: Add a flag to control number of revisions, and experiment with it.
        let revisions = try!(self.wiki.get_revisions(title, 60));
        Ok(revisions.into_iter().filter(|revision| revision.comment.contains("vandal")).collect())
    }

    // TODO: this name is terrible.
    fn get_page_with_vandalism_restored(&self, title: &str) -> Result<String, String> {
        let canonical_title = try!(self.wiki.get_canonical_title(title));
        info!("Canonical page title for \"{}\" is \"{}\"", title, canonical_title);

        let latest_revid = try!(self.wiki.get_latest_revision(&canonical_title)).revid;
        let mut accumulated_contents =
            try!(self.wiki.get_revision_content(&canonical_title, latest_revid));
        let mut merged_revisions = vec![];
        let vandalism_reversions = try!(self.get_vandalism_reversions(&canonical_title));
        for revision in &vandalism_reversions {
            let reverted_contents =
                try!(self.wiki.get_revision_content(&canonical_title, revision.revid));
            let vandalized_contents =
                try!(self.wiki.get_revision_content(&canonical_title, revision.parentid));
            match merge(&reverted_contents, &vandalized_contents, &accumulated_contents) {
                Ok(Some(merged_contents)) => {
                    accumulated_contents = merged_contents;
                    merged_revisions.push(revision.revid);
                }
                Ok(None) => (),
                Err(msg) => return Err(format!("Error merging revision {} of \"{}\": {}",
                                               revision.revid, title, msg))
            }
        }

        info!("For \"{}\", successfully merged {} of {} possible vandalisms: {:?}", title,
              merged_revisions.len(), vandalism_reversions.len(), merged_revisions);

        let body = try!(self.wiki.parse_wikitext(&canonical_title, &accumulated_contents));
        // Note: "title" rather than "canonical_title", so that redirects look right.
        let current_page_contents = try!(self.wiki.get_current_page_content(&title));
        let placeholder = format!("WMW_PLACEHOLDER_TEXT_{}", rand::random::<u64>());
        let page_contents_with_placeholder =
            try!(replace_node_with_placeholder(
                &current_page_contents, "mw-content-text", &placeholder));
        Ok(page_contents_with_placeholder.replace(&placeholder, &body))
    }
}

impl Handler for WikipediaMinusWikipediansHandler {
    fn handle(&self, request: &mut Request) -> IronResult<Response> {
        if request.url.path.len() == 2 && request.url.path[0] == "wiki" {
            let mut response =
                match self.get_page_with_vandalism_restored(&request.url.path[1]) {
                    Ok(page_contents) => Response::with((iron::status::Ok, page_contents)),
                    // TODO: create an Error type to pass around, so this can distinguish different
                    // types of error (if that would be helpful).
                    // TODO: create a better error page
                    Err(msg) => Response::with(
                        (iron::status::InternalServerError, "ERROR")),
                };
            response.headers.set(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])));
            Ok(response)
        } else {
            // TODO: should I use an HTTP redirect here instead? Would that work? Would it be desirable?
            // TODO: Maybe should be moved to wiki module.
            let mut url = request.url.clone();
            url.host = url::Host::Domain(self.wiki.hostname.clone());
            match self.client.get(&url.into_generic_url().serialize())
                .header(Connection::close()).send() {
                    Ok(mut wikipedia_response) => {
                        let mut wikipedia_body: Vec<u8> = Vec::new();
                        wikipedia_response.read_to_end(&mut wikipedia_body);

                        let mut response = Response::with(wikipedia_body);
                        response.status = Some(wikipedia_response.status);
                        response.headers = wikipedia_response.headers.clone();
                        info!("Forwarded request for {} to {}", request.url.path.join("/"),
                              self.wiki.hostname);
                        Ok(response)
                    },
                    Err(error) => {
                        let mut response = Response::with(
                            (iron::status::InternalServerError,
                             format!("ERROR: {}", error)));
                        response.headers.set(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])));
                        Ok(response)
                    }
                }
        }
    }
}

fn main() {
    log4rs::init_file("log.toml", Default::default()).unwrap();

    let mut port = 3000;
    let mut wiki = "en.wikipedia.org".to_string();
    {
        let mut parser = ArgumentParser::new();
        parser.set_description("TODO: Usage description");
        parser.refer(&mut port).add_option(&["-p", "--port"], Store, "The port to serve HTTP on.");
        parser.refer(&mut wiki).add_option(&["--wiki"], Store, "The wiki to mirror.");
        parser.parse_args_or_exit();
    }
    let handler =
        WikipediaMinusWikipediansHandler::new(Wiki::new(wiki.to_string(), Client::new()),
                                              Client::new());
    Iron::new(handler).http(("localhost", port)).unwrap();
}

#[cfg(test)]
mod tests {
    use super::{merge, replace_node_with_placeholder};

    #[test]
    fn test_merge_clean() {
        let old = "First line.\n\nSecond line.\n";
        let new1 = "First line.\n\nSecond line changed.\n";
        let new2 = "First line changed.\n\nSecond line.\n";
        assert_eq!(Some("First line changed.\n\nSecond line changed.\n".to_string()),
                   merge(old, new1, new2).unwrap());
    }

    #[test]
    fn test_merge_conflicting() {
        let old = "First line.\n\nSecond line.\n";
        let new1 = "First line.\n\nSecond line changed one way.\n";
        let new2 = "First line changed.\n\nSecond line changed a different way.\n";
        assert_eq!(None, merge(old, new1, new2).unwrap());
    }

    #[test]
    fn test_merge_special_characters() {
        let old = "First line.\n\nSecond line.\n";
        let new1 = "First line.\n\nSecond line 𐅃.\n";
        let new2 = "First line さようなら.\n\nSecond line.\n";
        assert_eq!(Some("First line さようなら.\n\nSecond line 𐅃.\n".to_string()),
                   merge(old, new1, new2).unwrap());
    }

    #[test]
    fn test_replace_html_content() {
        let original_html = "

original text

Other text

";
        let expected_html = "

replaced text

Other text

";
        let processed_html = replace_node_with_placeholder(original_html, "mw-content-text", "replaced text").unwrap();
        assert_eq!(expected_html, processed_html);
    }
}
<commit_msg>Remove an extraneous #! line that shouldn't have been committed.<commit_after>#![feature(plugin)]
#![plugin(regex_macros)]

extern crate argparse;
extern crate html5ever;
extern crate html5ever_dom_sink;
extern crate hyper;
extern crate iron;
#[macro_use]
extern crate log;
extern crate log4rs;
extern crate rand;
extern crate regex;
extern crate rustc_serialize;
extern crate tempfile;
extern crate tendril;
extern crate url;

/// Helper macro for unwrapping Result values whose E types implement std::fmt::Display. For Ok(),
/// evaluates to the contained value. For Err(), returns early with an Err containing the formatted
/// error.
macro_rules! try_display {
    ($expr:expr, $($format_arg:expr),* ) => (match $expr {
        Ok(val) => val,
        Err(err) => return Err(format!("{}: {}", format!($($format_arg),*), err)),
    })
}

mod json;
mod wiki;

use argparse::ArgumentParser;
use argparse::Store;
//use collections::borrow::Borrow;
use std::fs::OpenOptions;
use std::io::Read;
use std::io::Write;
use std::process::Command;
use std::process::Stdio;
use std::str::FromStr;

use html5ever::Attribute;
use html5ever::tree_builder::interface::TreeSink;
use html5ever_dom_sink::common::NodeEnum;
use html5ever_dom_sink::rcdom::Handle;
use html5ever_dom_sink::rcdom::RcDom;
use hyper::Client;
use hyper::header::Connection;
use iron::Iron;
use iron::IronResult;
use iron::Request;
use iron::Response;
use iron::headers::ContentType;
use iron::middleware::Handler;
use iron::mime::Mime;
use iron::mime::SubLevel;
use iron::mime::TopLevel;
use tempfile::NamedTempFile;

use wiki::Revision;
use wiki::Wiki;

// TODO: consider doing s/en.wikipedia.org/this app's url/ on the HTML before serving it. This
// currently works fine, but might not over HTTPS.

/// Does a 3-way merge, merging `new1` and `new2` under the assumption that both diverged from
/// `old`. Returns None if the strings do not merge together cleanly.
fn merge(old: &str, new1: &str, new2: &str) -> Result<Option<String>, String> {
    fn write_to_temp_file(contents: &str) -> Result<NamedTempFile, String> {
        let tempfile = try_display!(NamedTempFile::new(), "Error creating temp file");
        let mut file = try_display!(OpenOptions::new().write(true).open(tempfile.path()),
                                    "Error opening temp file for writing");
        try_display!(file.write_all(contents.as_bytes()), "Error writing to temp file");
        try_display!(file.flush(), "Error flushing temp file");
        Ok(tempfile)
    }

    let old_tempfile = try!(write_to_temp_file(old));
    let new1_tempfile = try!(write_to_temp_file(new1));
    let new2_tempfile = try!(write_to_temp_file(new2));

    let mut process = Command::new("diff3");
    process.arg("-m").args(&[new1_tempfile.path(), old_tempfile.path(), new2_tempfile.path()])
        .stdout(Stdio::piped()).stderr(Stdio::null());
    let output = try_display!(process.output(), "Error getting output from diff3 subprocess");
    if output.status.success() {
        Ok(Some(try_display!(String::from_utf8(output.stdout),
                             "Error converting diff3 output to UTF-8")))
    } else {
        Ok(None)
    }
}

fn replace_node_with_placeholder(original_html: &str, div_id: &str, placeholder: &str)
    -> Result<String, String> {
    let html = tendril::StrTendril::from_str(original_html).unwrap();
    let mut dom: RcDom = html5ever::parse(html5ever::one_input(html), Default::default());

    let handle = try!(find_node_by_id(&dom.get_document(), div_id));
    let child_handles =
        (&handle.borrow().children).into_iter().map(|child| child.clone()).collect::<Vec<_>>();
    for child_handle in child_handles {
        dom.remove_from_parent(child_handle);
    }
    dom.append(handle,
               html5ever::tree_builder::interface::NodeOrText::AppendText(
                   tendril::StrTendril::from_str(placeholder).unwrap()));
    let mut serialized: Vec<u8> = vec![];
    html5ever::serialize::serialize(&mut serialized, &dom.document, Default::default());
    Ok(try_display!(String::from_utf8(serialized),
                    "Error converting serialized HTML to UTF-8 string"))
}

fn find_node_by_id(handle: &Handle, id: &str) -> Result<Handle, String> {
    fn has_matching_id(attributes: &Vec<Attribute>, id: &str) -> bool {
        return attributes.into_iter().any(
            |attribute| attribute.name.local.as_slice() == "id" &&
                format!("{}", attribute.value) == id);
    }

    let node = handle.borrow();
    match node.node {
        NodeEnum::Element(_, ref attributes) if has_matching_id(attributes, id) => Ok(handle.clone()),
        _ => (&node.children).into_iter()
            .map(|child| find_node_by_id(child, id))
            .filter(|result| result.is_ok())
            .map(|result| result.unwrap())
            .next().ok_or(format!("No node with ID {} found", id)),
    }
}

struct WikipediaMinusWikipediansHandler {
    wiki: Wiki,
    client: Client
}

impl WikipediaMinusWikipediansHandler {
    fn new(wiki: Wiki, client: Client) -> WikipediaMinusWikipediansHandler {
        WikipediaMinusWikipediansHandler { wiki: wiki, client: client }
    }

    /// Returns a vector of Revisions representing all reversions of vandalism for the page `title`.
    fn get_vandalism_reversions(&self, title: &str) -> Result<Vec<Revision>, String> {
        // TODO: Add a flag to control number of revisions, and experiment with it.
        let revisions = try!(self.wiki.get_revisions(title, 60));
        Ok(revisions.into_iter().filter(|revision| revision.comment.contains("vandal")).collect())
    }

    // TODO: this name is terrible.
    fn get_page_with_vandalism_restored(&self, title: &str) -> Result<String, String> {
        let canonical_title = try!(self.wiki.get_canonical_title(title));
        info!("Canonical page title for \"{}\" is \"{}\"", title, canonical_title);

        let latest_revid = try!(self.wiki.get_latest_revision(&canonical_title)).revid;
        let mut accumulated_contents =
            try!(self.wiki.get_revision_content(&canonical_title, latest_revid));
        let mut merged_revisions = vec![];
        let vandalism_reversions = try!(self.get_vandalism_reversions(&canonical_title));
        for revision in &vandalism_reversions {
            let reverted_contents =
                try!(self.wiki.get_revision_content(&canonical_title, revision.revid));
            let vandalized_contents =
                try!(self.wiki.get_revision_content(&canonical_title, revision.parentid));
            match merge(&reverted_contents, &vandalized_contents, &accumulated_contents) {
                Ok(Some(merged_contents)) => {
                    accumulated_contents = merged_contents;
                    merged_revisions.push(revision.revid);
                }
                Ok(None) => (),
                Err(msg) => return Err(format!("Error merging revision {} of \"{}\": {}",
                                               revision.revid, title, msg))
            }
        }

        info!("For \"{}\", successfully merged {} of {} possible vandalisms: {:?}", title,
              merged_revisions.len(), vandalism_reversions.len(), merged_revisions);

        let body = try!(self.wiki.parse_wikitext(&canonical_title, &accumulated_contents));
        // Note: "title" rather than "canonical_title", so that redirects look right.
        let current_page_contents = try!(self.wiki.get_current_page_content(&title));
        let placeholder = format!("WMW_PLACEHOLDER_TEXT_{}", rand::random::<u64>());
        let page_contents_with_placeholder =
            try!(replace_node_with_placeholder(
                &current_page_contents, "mw-content-text", &placeholder));
        Ok(page_contents_with_placeholder.replace(&placeholder, &body))
    }
}

impl Handler for WikipediaMinusWikipediansHandler {
    fn handle(&self, request: &mut Request) -> IronResult<Response> {
        if request.url.path.len() == 2 && request.url.path[0] == "wiki" {
            let mut response =
                match self.get_page_with_vandalism_restored(&request.url.path[1]) {
                    Ok(page_contents) => Response::with((iron::status::Ok, page_contents)),
                    // TODO: create an Error type to pass around, so this can distinguish different
                    // types of error (if that would be helpful).
                    // TODO: create a better error page
                    Err(msg) => Response::with(
                        (iron::status::InternalServerError, "ERROR")),
                };
            response.headers.set(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])));
            Ok(response)
        } else {
            // TODO: should I use an HTTP redirect here instead? Would that work? Would it be desirable?
            // TODO: Maybe should be moved to wiki module.
            let mut url = request.url.clone();
            url.host = url::Host::Domain(self.wiki.hostname.clone());
            match self.client.get(&url.into_generic_url().serialize())
                .header(Connection::close()).send() {
                    Ok(mut wikipedia_response) => {
                        let mut wikipedia_body: Vec<u8> = Vec::new();
                        wikipedia_response.read_to_end(&mut wikipedia_body);

                        let mut response = Response::with(wikipedia_body);
                        response.status = Some(wikipedia_response.status);
                        response.headers = wikipedia_response.headers.clone();
                        info!("Forwarded request for {} to {}", request.url.path.join("/"),
                              self.wiki.hostname);
                        Ok(response)
                    },
                    Err(error) => {
                        let mut response = Response::with(
                            (iron::status::InternalServerError,
                             format!("ERROR: {}", error)));
                        response.headers.set(ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![])));
                        Ok(response)
                    }
                }
        }
    }
}

fn main() {
    log4rs::init_file("log.toml", Default::default()).unwrap();

    let mut port = 3000;
    let mut wiki = "en.wikipedia.org".to_string();
    {
        let mut parser = ArgumentParser::new();
        parser.set_description("TODO: Usage description");
        parser.refer(&mut port).add_option(&["-p", "--port"], Store, "The port to serve HTTP on.");
        parser.refer(&mut wiki).add_option(&["--wiki"], Store, "The wiki to mirror.");
        parser.parse_args_or_exit();
    }
    let handler =
        WikipediaMinusWikipediansHandler::new(Wiki::new(wiki.to_string(), Client::new()),
                                              Client::new());
    Iron::new(handler).http(("localhost", port)).unwrap();
}

#[cfg(test)]
mod tests {
    use super::{merge, replace_node_with_placeholder};

    #[test]
    fn test_merge_clean() {
        let old = "First line.\n\nSecond line.\n";
        let new1 = "First line.\n\nSecond line changed.\n";
        let new2 = "First line changed.\n\nSecond line.\n";
        assert_eq!(Some("First line changed.\n\nSecond line changed.\n".to_string()),
                   merge(old, new1, new2).unwrap());
    }

    #[test]
    fn test_merge_conflicting() {
        let old = "First line.\n\nSecond line.\n";
        let new1 = "First line.\n\nSecond line changed one way.\n";
        let new2 = "First line changed.\n\nSecond line changed a different way.\n";
        assert_eq!(None, merge(old, new1, new2).unwrap());
    }

    #[test]
    fn test_merge_special_characters() {
        let old = "First line.\n\nSecond line.\n";
        let new1 = "First line.\n\nSecond line 𐅃.\n";
        let new2 = "First line さようなら.\n\nSecond line.\n";
        assert_eq!(Some("First line さようなら.\n\nSecond line 𐅃.\n".to_string()),
                   merge(old, new1, new2).unwrap());
    }

    #[test]
    fn test_replace_html_content() {
        let original_html = "

original text

Other text

";
        let expected_html = "

replaced text

Other text

";
        let processed_html = replace_node_with_placeholder(original_html, "mw-content-text", "replaced text").unwrap();
        assert_eq!(expected_html, processed_html);
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

mod action;
mod opts;
mod session;

use std::fs::File;
use std::io::Result;

use fleetspeak::Packet;
use log::error;
use opts::{Opts};

use self::action::{Response};

fn main() -> Result<()> {
    let opts = opts::from_args();
    init(&opts);

    fleetspeak::startup(env!("CARGO_PKG_VERSION"))?;

    use self::action::startup;
    match startup::handle(()) {
        Ok(response) => {
            let mut data = Vec::new();
            // TODO: Use proper error handling.
            prost::Message::encode(&response.into_proto(), &mut data)?;

            let message = rrg_proto::GrrMessage {
                session_id: Some(String::from("flows/F:Startup")),
                r#type: Some(rrg_proto::grr_message::Type::Message.into()),
                args_rdf_name: startup::Response::RDF_NAME.map(String::from),
                args: Some(data),
                ..Default::default()
            };

            fleetspeak::send(Packet {
                service: String::from("GRR"),
                kind: Some(String::from("GrrMessage")),
                data: message,
            })?;
        },
        Err(error) => error!("failed to execute startup action: {}", error),
    }

    loop {
        let packet = fleetspeak::collect(opts.heartbeat_rate)?;
        handle(packet.data);
    }
}

fn init(opts: &Opts) {
    init_log(opts);
}

fn init_log(opts: &Opts) {
    let level = opts.log_verbosity.level();

    let mut loggers = Vec::<Box<dyn simplelog::SharedLogger>>::new();

    if let Some(std) = &opts.log_std {
        let config = Default::default();
        let logger = simplelog::TermLogger::new(level, config, std.mode())
            .expect("failed to create a terminal logger");

        loggers.push(logger);
    }

    if let Some(path) = &opts.log_file {
        let file = File::create(path)
            .expect("failed to create the log file");

        let config = Default::default();
        let logger = simplelog::WriteLogger::new(level, config, file);

        loggers.push(logger);
    }

    simplelog::CombinedLogger::init(loggers)
        .expect("failed to init logging");
}

fn handle(message: rrg_proto::GrrMessage) {
    match message.name {
        Some(name) => println!("requested to execute the '{}' action", name),
        None => eprintln!("missing action name to execute"),
    }
}
<commit_msg>Refactor startup to use the session mechanism.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

mod action;
mod opts;
mod session;

use std::fs::File;
use std::io::Result;

use log::error;
use opts::{Opts};

use self::session::{Session};

fn main() -> Result<()> {
    let opts = opts::from_args();
    init(&opts);

    fleetspeak::startup(env!("CARGO_PKG_VERSION"))?;

    match self::action::startup::handle(()) {
        Ok(response) => Session::known("/flows/F:Startup").reply(response)?,
        Err(error) => error!("failed to execute startup action: {}", error),
    }

    loop {
        let packet = fleetspeak::collect(opts.heartbeat_rate)?;
        handle(packet.data);
    }
}

fn init(opts: &Opts) {
    init_log(opts);
}

fn init_log(opts: &Opts) {
    let level = opts.log_verbosity.level();

    let mut loggers = Vec::<Box<dyn simplelog::SharedLogger>>::new();

    if let Some(std) = &opts.log_std {
        let config = Default::default();
        let logger = simplelog::TermLogger::new(level, config, std.mode())
            .expect("failed to create a terminal logger");

        loggers.push(logger);
    }

    if let Some(path) = &opts.log_file {
        let file = File::create(path)
            .expect("failed to create the log file");

        let config = Default::default();
        let logger = simplelog::WriteLogger::new(level, config, file);

        loggers.push(logger);
    }

    simplelog::CombinedLogger::init(loggers)
        .expect("failed to init logging");
}

fn handle(message: rrg_proto::GrrMessage) {
    match message.name {
        Some(name) => println!("requested to execute the '{}' action", name),
        None => eprintln!("missing action name to execute"),
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use std::iter::FromIterator;
use rand::distributions::{IndependentSample, Range};

const N: usize = 50;
const P: usize = 128;

fn schwefel(solution: &Vec<f64>) -> f64 {
    418.9829_f64 * solution.len() as f64
        + solution.iter().fold(0_f64, |sum, x| sum + x * x.abs().sqrt().sin())
}

fn main() {
    let mut rng = rand::thread_rng();
    let range = Range::new(-512.03, 511.97);

    // initialize population
    let population = Vec::from_iter((0..P).map(|_| {
        Vec::from_iter((0..N).map(|_| {
            range.ind_sample(&mut rng)
        }))
    }));

    println!("{:?}", population); // debug print of solutions

    println!("The best solution's fitness was {}", schwefel(&population[0]));
}
<commit_msg>Make Range use f64<commit_after>extern crate rand;

use std::iter::FromIterator;
use rand::distributions::{IndependentSample, Range};

const N: usize = 50;
const P: usize = 128;

fn schwefel(solution: &Vec<f64>) -> f64 {
    418.9829_f64 * solution.len() as f64
        + solution.iter().fold(0_f64, |sum, x| sum + x * x.abs().sqrt().sin())
}

fn main() {
    let mut rng = rand::thread_rng();
    let range = Range::new(-512.03_f64, 511.97);

    // initialize population
    let population = Vec::from_iter((0..P).map(|_| {
        Vec::from_iter((0..N).map(|_| {
            range.ind_sample(&mut rng)
        }))
    }));

    println!("{:?}", population); // debug print of solutions

    println!("The best solution's fitness was {}", schwefel(&population[0]));
}
<|endoftext|>


<commit_before>extern crate rand;

use rand::thread_rng;
use rand::distributions::Range;
use individual::Individual;

mod individual;

fn main() {
    let mut rng = thread_rng();
    let range = Range::new(-512.03_f64, 511.97); // range for Schwefel problem

    // initialize population
    let population: Vec<_> = (0..128).map(|_| {
        Individual::new(&range, &mut rng)
    }).collect();

    // generate mutated offspring
    let offspring: Vec<_> = population.iter().map(|x| {
        x.mutate(&range, &mut rng)
    }).collect();

    let best = population.iter().min().unwrap();
    println!("The best solution was {:?}", best.solution);
    println!("Its fitness was {}", best.fitness);

    let best = offspring.iter().min().unwrap();
    println!("The best new solution was {:?}", best.solution);
    println!("Its fitness was {}", best.fitness);
}
<commit_msg>Run naive algorithm in a loop<commit_after>extern crate rand;

use rand::thread_rng;
use rand::distributions::Range;
use individual::Individual;

mod individual;

fn main() {
    let mut rng = thread_rng();
    let range = Range::new(-512.03_f64, 511.97); // range for Schwefel problem

    // initialize population
    let population: Vec<_> = (0..128).map(|_| {
        Individual::new(&range, &mut rng)
    }).collect();

    loop {
        // generate mutated offspring
        let offspring: Vec<_> = population.iter().map(|x| {
            x.mutate(&range, &mut rng)
        }).collect();

        let best = offspring.iter().min().unwrap();
        println!("Fitness: {}", best.fitness);

        if best.fitness < 1000_f64 {
            println!("Solution: {:?}", best.solution);
            break;
        }
    }
}
<|endoftext|>


<commit_before>extern crate binichonline;

use std::thread;
use binichonline::ui;
use binichonline::net;

struct Looper {
    interval: u32
}

impl Looper {
    pub fn run(&self) {
        loop {
            ui::update(net::is_online());
            thread::sleep_ms(self.interval);
            ui::clear_screen();
        }
    }
}

fn main() {
    Looper { interval: 1500 }.run();
}
<commit_msg>Adapt to changes in std::time::Duration<commit_after>extern crate binichonline;

use std::thread;
use std::time::Duration;
use binichonline::ui;
use binichonline::net;

struct Looper {
    interval: std::time::Duration
}

impl Looper {
    pub fn run(&self) {
        loop {
            ui::update(net::is_online());
            thread::sleep(self.interval);
            ui::clear_screen();
        }
    }
}

fn main() {
    Looper { interval: Duration::from_millis(1500) }.run();
}
<|endoftext|>


<commit_before>fn main(expr: &str) -> f32 {
  let mut stack:Vec<f32> = Vec::new();
  for token in expr.split_whitespace() {
    let wrapped_operand = token.parse::<f32>();
    let is_operator = wrapped_operand.is_err();
    if is_operator {
      if stack.len() < 2 {
        panic!("Unsufficient operands before operator");
      }
      // xxxFlorent: Any way to destructure like this? Not sure of what I am doing below
      // let [ operand1, operand2 ] = stack.drain((token.len() - 3)..).collect();
      let operand2 = stack.pop().expect("expected f32 values only in stack");
      let operand1 = stack.pop().expect("expected f32 values only in stack");
      let result = match token {
        "+" => operand1 + operand2,
        "-" => operand1 - operand2,
        "*" => operand1 * operand2,
        "/" => operand1 / operand2,
        _ => panic!("Unsupported operator")
      };
      stack.push(result);
      println!("{}", result);
    } else {
      stack.push(wrapped_operand.unwrap());
    }
  }

  if stack.len() != 1 {
    panic!("Remaining untreated operands. Probably missing operator.");
  }
  return stack.pop().expect("expected a f32 value remaining in stack");
}

#[test]
fn it_adds() {
  let result = main("1 2 +");
  assert_eq!(result, 3.0);
}

#[test]
fn it_substracts() {
  let result = main("1 2 -");
  assert_eq!(result, -1.0);
}

#[test]
fn it_multiplies() {
  let result = main("6 7 *");
  assert_eq!(result, 42.0);
}

#[test]
fn it_divides() {
  let result = main("1 2 /");
  assert_eq!(result, 0.5);
}

#[test]
fn it_calculates_complex_expressions() {
  // ((1+2) * 8 / (5-1) - 1) / 2
  let result = main("1 2 + 8 * 5 1 - / 1 - 2 /");
  assert_eq!(result, 2.5);
}

#[test]
#[should_panic]
fn it_panics_for_unsupported_operators() {
  main("1 2 =");
  // xxxFlorent: How to test the panic message is right?
}

#[test]
#[should_panic]
fn it_panics_for_unsufficient_operands() {
  main("1 +");
  // xxxFlorent: How to test the panic message is right?
}

#[test]
#[should_panic]
fn it_panics_for_unsufficient_operators() {
  main("1 2 3 +");
  // xxxFlorent: How to test the panic message is right?
}
<commit_msg>Test that we allow multiple spaces and sort of spaces<commit_after>fn main(expr: &str) -> f32 {
  let mut stack:Vec<f32> = Vec::new();
  for token in expr.split_whitespace() {
    let wrapped_operand = token.parse::<f32>();
    let is_operator = wrapped_operand.is_err();
    if is_operator {
      if stack.len() < 2 {
        panic!("Unsufficient operands before operator");
      }
      // xxxFlorent: Any way to destructure like this? Not sure of what I am doing below
      // let [ operand1, operand2 ] = stack.drain((token.len() - 3)..).collect();
      let operand2 = stack.pop().expect("expected f32 values only in stack");
      let operand1 = stack.pop().expect("expected f32 values only in stack");
      let result = match token {
        "+" => operand1 + operand2,
        "-" => operand1 - operand2,
        "*" => operand1 * operand2,
        "/" => operand1 / operand2,
        _ => panic!("Unsupported operator")
      };
      stack.push(result);
    } else {
      stack.push(wrapped_operand.unwrap());
    }
  }

  if stack.len() != 1 {
    panic!("Remaining untreated operands. Probably missing operator.");
  }
  return stack.pop().expect("expected a f32 value remaining in stack");
}

#[test]
fn it_adds() {
  let result = main("1 2 +");
  assert_eq!(result, 3.0);
}

#[test]
fn it_substracts() {
  let result = main("1 2 -");
  assert_eq!(result, -1.0);
}

#[test]
fn it_multiplies() {
  let result = main("6 7 *");
  assert_eq!(result, 42.0);
}

#[test]
fn it_divides() {
  let result = main("1 2 /");
  assert_eq!(result, 0.5);
}

#[test]
fn it_calculates_complex_expressions() {
  // ((1+2) * 8 / (5-1) - 1) / 2
  let result = main("1 2 + 8 * 5 1 - / 1 - 2 /");
  assert_eq!(result, 2.5);
}

#[test]
fn it_allows_multiple_shitespaces() {
  let result = main("1  2 +\t3 -");
  assert_eq!(result, 0.0);
}

#[test]
#[should_panic]
fn it_panics_for_unsupported_characters() {
  main("1 2 t");
  // xxxFlorent: How to test the panic message is right?
}

#[test]
#[should_panic]
fn it_panics_for_unsufficient_operands() {
  main("1 +");
  // xxxFlorent: How to test the panic message is right?
}

#[test]
#[should_panic]
fn it_panics_for_unsufficient_operators() {
  main("1 2 3 +");
  // xxxFlorent: How to test the panic message is right?
}
<|endoftext|>


<commit_before>use std::env;
use std::io::prelude::*;
use std::fs::File;
use std::path::PathBuf;
extern crate uuid;
use uuid::Uuid;
extern crate getopts;
use getopts::Options;
use std::io;

fn print_usage(program: &str, opts: Options) {
    let path = PathBuf::from(program);
    let command = path.file_name().unwrap().to_string_lossy();

    let brief = format!("Usage: {} FILE [options]", command);
    let info = "Safely rewrite contents of FILE with stdin, even\nwhere FILE is being read by \
                upstream command";
    print!("{}", opts.usage(&[&brief, info].join("\n")));
}

fn redirect_to_file(outfile: &str) -> Result<(), io::Error> {
    let mut tempfile = env::temp_dir();
    tempfile.push(Uuid::new_v4().hyphenated().to_string());
    // println!("{}", tempfile.display());

    {
        let mut buffer = [0; 512];
        let mut stdin = io::stdin();
        let mut f = File::create(&tempfile).expect("Failed to create output file!");

        loop {
            let read_bytes = stdin.read(&mut buffer).expect("Error reading from stdin!");
            if read_bytes == 0 {
                break;
            }

            let write_bytes = match f.write(&buffer[0..read_bytes]) {
                Ok(m) => m,
                Err(e) => panic!("{}", e),
            };

            assert!(write_bytes == read_bytes);
        }
    }

    match std::fs::rename(&tempfile, &outfile) {
        Ok(m) => m,
        _ => {
            // fs::rename does not support cross-device linking
            // copy and delete instead
            assert!(std::fs::copy(&tempfile, &outfile).is_ok());
            assert!(std::fs::remove_file(&tempfile).is_ok());
        }
    };

    return Ok(());
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optflag("h", "help", "prints this help info");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string()),
    };
    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }
    let infile = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };

    assert!(redirect_to_file(&infile).is_ok());
}
<commit_msg>Nicer error handling<commit_after>use std::env;
use std::io::prelude::*;
use std::fs::File;
use std::path::PathBuf;
extern crate uuid;
use uuid::Uuid;
extern crate getopts;
use getopts::Options;
use std::io;

fn print_usage(program: &str, opts: Options) {
    let path = PathBuf::from(program);
    let command = path.file_name().unwrap().to_string_lossy();

    let brief = format!("Usage: {} FILE [options]", command);
    let info = "Safely rewrite contents of FILE with stdin, even\nwhere FILE is being read by \
                upstream command";
    print!("{}", opts.usage(&[&brief, info].join("\n")));
}

fn redirect_to_file(outfile: &str) -> Result<(), io::Error> {
    let mut tempfile = env::temp_dir();
    tempfile.push(Uuid::new_v4().hyphenated().to_string());
    // println!("{}", tempfile.display());

    {
        let mut buffer = [0; 512];
        let mut stdin = io::stdin();
        let mut f = File::create(&tempfile).expect("Failed to create temporary file!");

        loop {
            let read_bytes = stdin.read(&mut buffer).expect("Error reading from stdin!");
            if read_bytes == 0 {
                break;
            }

            let write_bytes = f.write(&buffer[0..read_bytes])
                .expect("Failed to write to temporary file!");

            assert!(write_bytes == read_bytes);
        }
    }

    match std::fs::rename(&tempfile, &outfile) {
        Ok(m) => m,
        _ => {
            // fs::rename does not support cross-device linking
            // copy and delete instead
            std::fs::copy(&tempfile, &outfile).expect("Failed to create output file!");
            std::fs::remove_file(&tempfile)
                .unwrap_or_else(|e| print!("Failed to delete temporary file!\n{:?}", e));
        }
    };

    return Ok(());
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optflag("h", "help", "prints this help info");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string()),
    };
    if matches.opt_present("h") {
        print_usage(&program, opts);
        return;
    }
    let infile = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        print_usage(&program, opts);
        return;
    };

    assert!(redirect_to_file(&infile).is_ok());
}
<|endoftext|>


<commit_before>#![feature(iter_cmp)]

use std::collections::HashMap;
use std::path::Path;

extern crate image;
use image::{DynamicImage, GenericImage};

mod byte_utils;
mod color;
use color::Color;
mod k_means;

#[cfg(test)]
mod tests;

fn main() {
    let mut image = image::open(&Path::new("00.png")).unwrap();

    let quantization_map = quantize_image(&image);

    let mut output_image = image.as_mut_rgba8().unwrap();
    for pixel in output_image.pixels_mut() {
        let &new_color = quantization_map.get(pixel).unwrap();
        *pixel = new_color;
    }

    output_image.save("output.png");
}

fn quantize_image(image: &DynamicImage) -> HashMap<Color, Color> {
    let colors = image.pixels().map(|(_, _, color)| color);
    k_means::quantize(colors)
}
<commit_msg>Refactoring.<commit_after>#![feature(iter_cmp)]

use std::collections::HashMap;
use std::path::Path;

extern crate image;
use image::{GenericImage, RgbaImage};

mod byte_utils;
mod color;
use color::Color;
mod k_means;

#[cfg(test)]
mod tests;

fn main() {
    let mut image = image::open(&Path::new("00.png")).unwrap();
    let mut image = image.as_mut_rgba8().unwrap();

    let quantization_map = quantize_image(&image);

    for pixel in image.pixels_mut() {
        let &new_color = quantization_map.get(pixel).unwrap();
        *pixel = new_color;
    }

    image.save("output.png");
}

fn quantize_image(image: &RgbaImage) -> HashMap<Color, Color> {
    let colors = image.pixels().map(|&color| color);
    k_means::quantize(colors)
}
<|endoftext|>