<commit_before>use std::env;
use std::ffi::OsString;
use std::fmt::{self, Display};
use std::fs::{self, File};
use std::io::{self, BufRead, Read, Write};
use std::path::{Path, PathBuf};
use std::process::{self, Command, Stdio};

use atty::Stream::{Stderr, Stdout};
use prettyprint::{PagingMode, PrettyPrinter, PrettyPrintError};
use quote::quote;
use structopt::clap::AppSettings;
use structopt::StructOpt;

#[derive(StructOpt)]
#[structopt(bin_name = "cargo")]
enum Opts {
    /// Show the result of macro expansion.
    #[structopt(
        name = "expand",
        raw(
            setting = "AppSettings::UnifiedHelpMessage",
            setting = "AppSettings::DeriveDisplayOrder",
            setting = "AppSettings::DontCollapseArgsInUsage"
        )
    )]
    Expand(Args),
}

#[derive(StructOpt, Debug)]
#[structopt(rename_all = "kebab-case")]
struct Args {
    /// Space-separated list of features to activate
    #[structopt(long, value_name = "FEATURES")]
    features: Option<String>,

    /// Activate all available features
    #[structopt(long)]
    all_features: bool,

    /// Do not activate the `default` feature
    #[structopt(long)]
    no_default_features: bool,

    /// Build only this package's library
    #[structopt(long)]
    lib: bool,

    /// Build only the specified binary
    #[structopt(long, value_name = "NAME")]
    bin: Option<String>,

    /// Build only the specified example
    #[structopt(long, value_name = "NAME")]
    example: Option<String>,

    /// Build only the specified test target
    #[structopt(long, value_name = "NAME")]
    test: Option<String>,

    /// Build only the specified bench target
    #[structopt(long, value_name = "NAME")]
    bench: Option<String>,

    /// Target triple which compiles will be for
    #[structopt(long, value_name = "TARGET")]
    target: Option<String>,

    /// Directory for all generated artifacts
    #[structopt(long, value_name = "DIRECTORY", parse(from_os_str))]
    target_dir: Option<PathBuf>,

    /// Path to Cargo.toml
    #[structopt(long, value_name = "PATH", parse(from_os_str))]
    manifest_path: Option<PathBuf>,

    /// Number of parallel jobs, defaults to # of CPUs
    #[structopt(short, long, value_name = "N")]
    jobs: Option<u64>,

    /// Coloring: auto, always, never
    #[structopt(long, value_name = "WHEN")]
    color: Option<String>,

    /// Require Cargo.lock and cache are up to date
    #[structopt(long)]
    frozen: bool,

    /// Require Cargo.lock is up to date
    #[structopt(long)]
    locked: bool,

    /// Unstable (nightly-only) flags to Cargo
    #[structopt(short = "Z", value_name = "FLAG")]
    unstable_flags: Vec<String>,

    /// Do not attempt to run rustfmt
    #[structopt(long)]
    ugly: bool,
}

fn main() {
    let result = cargo_expand_or_run_nightly();
    process::exit(match result {
        Ok(code) => code,
        Err(err) => {
            let _ = writeln!(&mut io::stderr(), "{}", err);
            1
        }
    });
}

enum Error {
    Io(io::Error),
    Print(PrettyPrintError),
}

impl From<io::Error> for Error {
    fn from(error: io::Error) -> Self {
        Error::Io(error)
    }
}

impl From<PrettyPrintError> for Error {
    fn from(error: PrettyPrintError) -> Self {
        Error::Print(error)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::Io(error) => Display::fmt(error, formatter),
            Error::Print(error) => Display::fmt(error, formatter),
        }
    }
}

type Result<T> = std::result::Result<T, Error>;

fn cargo_expand_or_run_nightly() -> Result<i32> {
    const NO_RUN_NIGHTLY: &str = "CARGO_EXPAND_NO_RUN_NIGHTLY";

    let maybe_nightly = !definitely_not_nightly();
    if maybe_nightly || env::var_os(NO_RUN_NIGHTLY).is_some() {
        return cargo_expand();
    }

    let mut nightly = Command::new("cargo");
    nightly.arg("+nightly");
    nightly.arg("expand");

    let mut args = env::args_os().peekable();
    args.next().unwrap(); // cargo
    if args.peek().map_or(false, |arg| arg == "expand") {
        args.next().unwrap(); // expand
    }
    nightly.args(args);

    // Hopefully prevent infinite re-run loop.
    nightly.env(NO_RUN_NIGHTLY, "");

    let status = nightly.status()?;

    Ok(match status.code() {
        Some(code) => code,
        None => {
            if status.success() {
                0
            } else {
                1
            }
        }
    })
}

fn definitely_not_nightly() -> bool {
    let mut cmd = Command::new(cargo_binary());
    cmd.arg("--version");

    let output = match cmd.output() {
        Ok(output) => output,
        Err(_) => return false,
    };

    let version = match String::from_utf8(output.stdout) {
        Ok(version) => version,
        Err(_) => return false,
    };

    version.starts_with("cargo 1") && !version.contains("nightly")
}

fn cargo_binary() -> OsString {
    env::var_os("CARGO").unwrap_or_else(|| "cargo".to_owned().into())
}

fn cargo_expand() -> Result<i32> {
    let Opts::Expand(args) = Opts::from_args();

    let mut builder = tempfile::Builder::new();
    builder.prefix("cargo-expand");
    let outdir = builder.tempdir().expect("failed to create tmp file");
    let outfile_path = outdir.path().join("expanded");

    // Run cargo
    let mut cmd = Command::new(cargo_binary());
    apply_args(&mut cmd, &args, &outfile_path);
    let code = filter_err(&mut cmd, ignore_cargo_err)?;

    let mut outfile = File::open(&outfile_path)?;
    if outfile.metadata()?.len() == 0 {
        let _ = writeln!(
            &mut io::stderr(),
            "ERROR: rustc produced no expanded output"
        );
        return Ok(if code == 0 { 1 } else { code });
    }

    // Run rustfmt
    let which_rustfmt = match args.ugly {
        false => which(&["rustfmt"]),
        true => None,
    };
    if let Some(fmt) = which_rustfmt {
        // Discard comments, which are misplaced by the compiler
        let mut content = Vec::new();
        outfile.read_to_end(&mut content)?;
        match String::from_utf8(content) {
            Ok(content) => {
                if let Ok(syntax_tree) = syn::parse_file(&content) {
                    let content = quote!(#syntax_tree).to_string();
                    fs::write(&outfile_path, content)?;
                }
            }
            Err(_) => {
                let _ = writeln!(&mut io::stderr(), "WARNING: non-UTF8 content");
            }
        }

        // Ignore any errors.
        let _status = Command::new(fmt)
            .arg(&outfile_path)
            .stderr(Stdio::null())
            .status();
    }

    // Run pretty printer
    let do_color = match args.color.as_ref().map(String::as_str) {
        Some("always") => true,
        Some("never") => false,
        None | Some("auto") | Some(_) => atty::is(Stdout),
    };
    if do_color {
        let mut content = fs::read_to_string(&outfile_path)?;
        if content.ends_with('\n') {
            // Pretty printer seems to print an extra trailing newline.
            content.truncate(content.len() - 1);
        }
        let printer = PrettyPrinter::default()
            .header(false)
            .grid(false)
            .line_numbers(false)
            .language("rust")
            .paging_mode(PagingMode::Never)
            .build()
            .unwrap();

        // Ignore any errors.
        let _ = printer.string(content);
    } else {
        let mut reader = File::open(&outfile_path)?;
        io::copy(&mut reader, &mut io::stdout())?;
    }

    Ok(0)
}

// Based on https://github.com/rsolomo/cargo-check
fn apply_args(cmd: &mut Command, args: &Args, outfile: &Path) {
    cmd.arg("rustc");
    cmd.arg("--profile=check");

    if let Some(features) = &args.features {
        cmd.arg("--features");
        cmd.arg(features);
    }

    if args.all_features {
        cmd.arg("--all-features");
    }

    if args.no_default_features {
        cmd.arg("--no-default-features");
    }

    if args.lib {
        cmd.arg("--lib");
    }

    if let Some(bin) = &args.bin {
        cmd.arg("--bin");
        cmd.arg(bin);
    }

    if let Some(example) = &args.example {
        cmd.arg("--example");
        cmd.arg(example);
    }

    if let Some(test) = &args.test {
        cmd.arg("--test");
        cmd.arg(test);
    }

    if let Some(bench) = &args.bench {
        cmd.arg("--bench");
        cmd.arg(bench);
    }

    if let Some(target) = &args.target {
        cmd.arg("--target");
        cmd.arg(target);
    }

    if let Some(target_dir) = &args.target_dir {
        cmd.arg("--target-dir");
        cmd.arg(target_dir);
    }

    if let Some(manifest_path) = &args.manifest_path {
        cmd.arg("--manifest-path");
        cmd.arg(manifest_path);
    }

    if let Some(jobs) = args.jobs {
        cmd.arg("--jobs");
        cmd.arg(jobs.to_string());
    }

    cmd.arg("--color");
    if let Some(color) = &args.color {
        cmd.arg(color);
    } else {
        cmd.arg(if atty::is(Stderr) { "always" } else { "never" });
    }

    if args.frozen {
        cmd.arg("--frozen");
    }

    if args.locked {
        cmd.arg("--locked");
    }

    for unstable_flag in &args.unstable_flags {
        cmd.arg("-Z");
        cmd.arg(unstable_flag);
    }

    cmd.arg("--");
    cmd.arg("-o");
    cmd.arg(outfile);
    cmd.arg("-Zunstable-options");
    cmd.arg("--pretty=expanded");
}

fn which(cmd: &[&str]) -> Option<OsString> {
    if env::args_os().any(|arg| arg == *"--help") {
        return None;
    }

    if let Some(which) = env::var_os(&cmd[0].to_uppercase()) {
        return if which.is_empty() { None } else { Some(which) };
    }

    let spawn = Command::new(cmd[0])
        .args(&cmd[1..])
        .stdin(Stdio::null())
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .spawn();
    let mut child = match spawn {
        Ok(child) => child,
        Err(_) => {
            return None;
        }
    };

    let exit = match child.wait() {
        Ok(exit) => exit,
        Err(_) => {
            return None;
        }
    };

    if exit.success() {
        Some(cmd[0].into())
    } else {
        None
    }
}

fn filter_err(cmd: &mut Command, ignore: fn(&str) -> bool) -> io::Result<i32> {
    let mut child = cmd.stderr(Stdio::piped()).spawn()?;
    let mut stderr = io::BufReader::new(child.stderr.take().unwrap());
    let mut line = String::new();
    while let Ok(n) = stderr.read_line(&mut line) {
        if n == 0 {
            break;
        }
        if !ignore(&line) {
            let _ = write!(&mut io::stderr(), "{}", line);
        }
        line.clear();
    }
    let code = child.wait()?.code().unwrap_or(1);
    Ok(code)
}

fn ignore_cargo_err(line: &str) -> bool {
    if line.trim().is_empty() {
        return true;
    }

    let blacklist = [
        "ignoring specified output filename because multiple outputs were \
         requested",
        "ignoring specified output filename for 'link' output because multiple \
         outputs were requested",
        "ignoring --out-dir flag due to -o flag",
        "ignoring -C extra-filename flag due to -o flag",
        "due to multiple output types requested, the explicitly specified \
         output file name will be adapted for each output type",
    ];
    for s in &blacklist {
        if line.contains(s) {
            return true;
        }
    }

    false
}
<commit_msg>Simplify rustfmt detection<commit_after>use std::env;
use std::ffi::OsString;
use std::fmt::{self, Display};
use std::fs::{self, File};
use std::io::{self, BufRead, Read, Write};
use std::path::{Path, PathBuf};
use std::process::{self, Command, Stdio};

use atty::Stream::{Stderr, Stdout};
use prettyprint::{PagingMode, PrettyPrinter, PrettyPrintError};
use quote::quote;
use structopt::clap::AppSettings;
use structopt::StructOpt;

#[derive(StructOpt)]
#[structopt(bin_name = "cargo")]
enum Opts {
    /// Show the result of macro expansion.
    #[structopt(
        name = "expand",
        raw(
            setting = "AppSettings::UnifiedHelpMessage",
            setting = "AppSettings::DeriveDisplayOrder",
            setting = "AppSettings::DontCollapseArgsInUsage"
        )
    )]
    Expand(Args),
}

#[derive(StructOpt, Debug)]
#[structopt(rename_all = "kebab-case")]
struct Args {
    /// Space-separated list of features to activate
    #[structopt(long, value_name = "FEATURES")]
    features: Option<String>,

    /// Activate all available features
    #[structopt(long)]
    all_features: bool,

    /// Do not activate the `default` feature
    #[structopt(long)]
    no_default_features: bool,

    /// Build only this package's library
    #[structopt(long)]
    lib: bool,

    /// Build only the specified binary
    #[structopt(long, value_name = "NAME")]
    bin: Option<String>,

    /// Build only the specified example
    #[structopt(long, value_name = "NAME")]
    example: Option<String>,

    /// Build only the specified test target
    #[structopt(long, value_name = "NAME")]
    test: Option<String>,

    /// Build only the specified bench target
    #[structopt(long, value_name = "NAME")]
    bench: Option<String>,

    /// Target triple which compiles will be for
    #[structopt(long, value_name = "TARGET")]
    target: Option<String>,

    /// Directory for all generated artifacts
    #[structopt(long, value_name = "DIRECTORY", parse(from_os_str))]
    target_dir: Option<PathBuf>,

    /// Path to Cargo.toml
    #[structopt(long, value_name = "PATH", parse(from_os_str))]
    manifest_path: Option<PathBuf>,

    /// Number of parallel jobs, defaults to # of CPUs
    #[structopt(short, long, value_name = "N")]
    jobs: Option<u64>,

    /// Coloring: auto, always, never
    #[structopt(long, value_name = "WHEN")]
    color: Option<String>,

    /// Require Cargo.lock and cache are up to date
    #[structopt(long)]
    frozen: bool,

    /// Require Cargo.lock is up to date
    #[structopt(long)]
    locked: bool,

    /// Unstable (nightly-only) flags to Cargo
    #[structopt(short = "Z", value_name = "FLAG")]
    unstable_flags: Vec<String>,

    /// Do not attempt to run rustfmt
    #[structopt(long)]
    ugly: bool,
}

fn main() {
    let result = cargo_expand_or_run_nightly();
    process::exit(match result {
        Ok(code) => code,
        Err(err) => {
            let _ = writeln!(&mut io::stderr(), "{}", err);
            1
        }
    });
}

enum Error {
    Io(io::Error),
    Print(PrettyPrintError),
}

impl From<io::Error> for Error {
    fn from(error: io::Error) -> Self {
        Error::Io(error)
    }
}

impl From<PrettyPrintError> for Error {
    fn from(error: PrettyPrintError) -> Self {
        Error::Print(error)
    }
}

impl Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::Io(error) => Display::fmt(error, formatter),
            Error::Print(error) => Display::fmt(error, formatter),
        }
    }
}

type Result<T> = std::result::Result<T, Error>;

fn cargo_expand_or_run_nightly() -> Result<i32> {
    const NO_RUN_NIGHTLY: &str = "CARGO_EXPAND_NO_RUN_NIGHTLY";

    let maybe_nightly = !definitely_not_nightly();
    if maybe_nightly || env::var_os(NO_RUN_NIGHTLY).is_some() {
        return cargo_expand();
    }

    let mut nightly = Command::new("cargo");
    nightly.arg("+nightly");
    nightly.arg("expand");

    let mut args = env::args_os().peekable();
    args.next().unwrap(); // cargo
    if args.peek().map_or(false, |arg| arg == "expand") {
        args.next().unwrap(); // expand
    }
    nightly.args(args);

    // Hopefully prevent infinite re-run loop.
    nightly.env(NO_RUN_NIGHTLY, "");

    let status = nightly.status()?;

    Ok(match status.code() {
        Some(code) => code,
        None => {
            if status.success() {
                0
            } else {
                1
            }
        }
    })
}

fn definitely_not_nightly() -> bool {
    let mut cmd = Command::new(cargo_binary());
    cmd.arg("--version");

    let output = match cmd.output() {
        Ok(output) => output,
        Err(_) => return false,
    };

    let version = match String::from_utf8(output.stdout) {
        Ok(version) => version,
        Err(_) => return false,
    };

    version.starts_with("cargo 1") && !version.contains("nightly")
}

fn cargo_binary() -> OsString {
    env::var_os("CARGO").unwrap_or_else(|| "cargo".to_owned().into())
}

fn cargo_expand() -> Result<i32> {
    let Opts::Expand(args) = Opts::from_args();

    let mut builder = tempfile::Builder::new();
    builder.prefix("cargo-expand");
    let outdir = builder.tempdir().expect("failed to create tmp file");
    let outfile_path = outdir.path().join("expanded");

    // Run cargo
    let mut cmd = Command::new(cargo_binary());
    apply_args(&mut cmd, &args, &outfile_path);
    let code = filter_err(&mut cmd, ignore_cargo_err)?;

    let mut outfile = File::open(&outfile_path)?;
    if outfile.metadata()?.len() == 0 {
        let _ = writeln!(
            &mut io::stderr(),
            "ERROR: rustc produced no expanded output"
        );
        return Ok(if code == 0 { 1 } else { code });
    }

    // Run rustfmt
    let which_rustfmt = match args.ugly {
        false => which("rustfmt"),
        true => None,
    };
    if let Some(fmt) = which_rustfmt {
        // Discard comments, which are misplaced by the compiler
        let mut content = Vec::new();
        outfile.read_to_end(&mut content)?;
        match String::from_utf8(content) {
            Ok(content) => {
                if let Ok(syntax_tree) = syn::parse_file(&content) {
                    let content = quote!(#syntax_tree).to_string();
                    fs::write(&outfile_path, content)?;
                }
            }
            Err(_) => {
                let _ = writeln!(&mut io::stderr(), "WARNING: non-UTF8 content");
            }
        }

        // Ignore any errors.
        let _status = Command::new(fmt)
            .arg(&outfile_path)
            .stderr(Stdio::null())
            .status();
    }

    // Run pretty printer
    let do_color = match args.color.as_ref().map(String::as_str) {
        Some("always") => true,
        Some("never") => false,
        None | Some("auto") | Some(_) => atty::is(Stdout),
    };
    if do_color {
        let mut content = fs::read_to_string(&outfile_path)?;
        if content.ends_with('\n') {
            // Pretty printer seems to print an extra trailing newline.
            content.truncate(content.len() - 1);
        }
        let printer = PrettyPrinter::default()
            .header(false)
            .grid(false)
            .line_numbers(false)
            .language("rust")
            .paging_mode(PagingMode::Never)
            .build()
            .unwrap();

        // Ignore any errors.
        let _ = printer.string(content);
    } else {
        let mut reader = File::open(&outfile_path)?;
        io::copy(&mut reader, &mut io::stdout())?;
    }

    Ok(0)
}

// Based on https://github.com/rsolomo/cargo-check
fn apply_args(cmd: &mut Command, args: &Args, outfile: &Path) {
    cmd.arg("rustc");
    cmd.arg("--profile=check");

    if let Some(features) = &args.features {
        cmd.arg("--features");
        cmd.arg(features);
    }

    if args.all_features {
        cmd.arg("--all-features");
    }

    if args.no_default_features {
        cmd.arg("--no-default-features");
    }

    if args.lib {
        cmd.arg("--lib");
    }

    if let Some(bin) = &args.bin {
        cmd.arg("--bin");
        cmd.arg(bin);
    }

    if let Some(example) = &args.example {
        cmd.arg("--example");
        cmd.arg(example);
    }

    if let Some(test) = &args.test {
        cmd.arg("--test");
        cmd.arg(test);
    }

    if let Some(bench) = &args.bench {
        cmd.arg("--bench");
        cmd.arg(bench);
    }

    if let Some(target) = &args.target {
        cmd.arg("--target");
        cmd.arg(target);
    }

    if let Some(target_dir) = &args.target_dir {
        cmd.arg("--target-dir");
        cmd.arg(target_dir);
    }

    if let Some(manifest_path) = &args.manifest_path {
        cmd.arg("--manifest-path");
        cmd.arg(manifest_path);
    }

    if let Some(jobs) = args.jobs {
        cmd.arg("--jobs");
        cmd.arg(jobs.to_string());
    }

    cmd.arg("--color");
    if let Some(color) = &args.color {
        cmd.arg(color);
    } else {
        cmd.arg(if atty::is(Stderr) { "always" } else { "never" });
    }

    if args.frozen {
        cmd.arg("--frozen");
    }

    if args.locked {
        cmd.arg("--locked");
    }

    for unstable_flag in &args.unstable_flags {
        cmd.arg("-Z");
        cmd.arg(unstable_flag);
    }

    cmd.arg("--");
    cmd.arg("-o");
    cmd.arg(outfile);
    cmd.arg("-Zunstable-options");
    cmd.arg("--pretty=expanded");
}

fn which(cmd: &str) -> Option<OsString> {
    if env::args_os().any(|arg| arg == *"--help") {
        return None;
    }

    if let Some(which) = env::var_os(&cmd.to_uppercase()) {
        return if which.is_empty() { None } else { Some(which) };
    }

    let spawn = Command::new(cmd)
        .stdin(Stdio::null())
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .spawn();
    let mut child = match spawn {
        Ok(child) => child,
        Err(_) => {
            return None;
        }
    };

    let exit = match child.wait() {
        Ok(exit) => exit,
        Err(_) => {
            return None;
        }
    };

    if exit.success() {
        Some(cmd.into())
    } else {
        None
    }
}

fn filter_err(cmd: &mut Command, ignore: fn(&str) -> bool) -> io::Result<i32> {
    let mut child = cmd.stderr(Stdio::piped()).spawn()?;
    let mut stderr = io::BufReader::new(child.stderr.take().unwrap());
    let mut line = String::new();
    while let Ok(n) = stderr.read_line(&mut line) {
        if n == 0 {
            break;
        }
        if !ignore(&line) {
            let _ = write!(&mut io::stderr(), "{}", line);
        }
        line.clear();
    }
    let code = child.wait()?.code().unwrap_or(1);
    Ok(code)
}

fn ignore_cargo_err(line: &str) -> bool {
    if line.trim().is_empty() {
        return true;
    }

    let blacklist = [
        "ignoring specified output filename because multiple outputs were \
         requested",
        "ignoring specified output filename for 'link' output because multiple \
         outputs were requested",
        "ignoring --out-dir flag due to -o flag",
        "ignoring -C extra-filename flag due to -o flag",
        "due to multiple output types requested, the explicitly specified \
         output file name will be adapted for each output type",
    ];
    for s in &blacklist {
        if line.contains(s) {
            return true;
        }
    }

    false
}
<|endoftext|>


<commit_before>extern crate noise;

use noise::index::{Index, OpenOptions};
use noise::query::Query;

fn main() {
    let dbname = "querytestdb";
    Index::delete(dbname);

    let mut index = Index::new();
    index.open(dbname, Some(OpenOptions::Create)).unwrap();
    index.add(r#"{"_id": "foo", "hello": "world"}"#);
    index.flush().unwrap();

    let mut query_results = Query::get_matches(r#"hello="world""#.to_string(), &index).unwrap();
    //let mut query_results = Query::get_matches(r#"a.b[foo="bar"]"#.to_string(), &index).unwrap();
    println!("query results: {:?}", query_results.get_next_id());
}
<commit_msg>Got rid of compile warnings of unused result<commit_after>extern crate noise;

use noise::index::{Index, OpenOptions};
use noise::query::Query;

fn main() {
    let dbname = "querytestdb";
    let _ = Index::delete(dbname);

    let mut index = Index::new();
    index.open(dbname, Some(OpenOptions::Create)).unwrap();
    let _ = index.add(r#"{"_id": "foo", "hello": "world"}"#);
    index.flush().unwrap();

    let mut query_results = Query::get_matches(r#"hello="world""#.to_string(), &index).unwrap();
    //let mut query_results = Query::get_matches(r#"a.b[foo="bar"]"#.to_string(), &index).unwrap();
    println!("query results: {:?}", query_results.get_next_id());
}
<|endoftext|>


<commit_before>
extern crate "xor-rs" as xorfn;
extern crate collections;

fn main() {
    let source = [95, 80, 96, 71, 120, 25, 44, 92, 120, 71, 96, 79, 54];
    let result = xorfn::xor(source, [23, 53, 12, 43]);

    match collections::str::from_utf8(result.as_slice()) {
        Some(string) => println!("{}", string),
        _ => {}
    }
}
<commit_msg>A 'main' function excluded from tests.<commit_after>
extern crate "xor-rs" as xorfn;
extern crate collections;

#[cfg(not(test))]
fn main() {
    let source = [95, 80, 96, 71, 120, 25, 44, 92, 120, 71, 96, 79, 54];
    let result = xorfn::xor(source, [23, 53, 12, 43]);

    match collections::str::from_utf8(result.as_slice()) {
        Some(string) => println!("{}", string),
        _ => {}
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2016 University of Glasgow
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

extern crate byteorder;
extern crate mio;

mod packets;
mod session;

use session::*;
use std::io::Result;
use std::str::FromStr;
use std::net::{SocketAddr, IpAddr, Ipv4Addr};
use std::time::{Duration, Instant};
use mio::*;
use mio::udp::*;

const TOKEN : mio::Token = mio::Token(0);

// =====================

struct NetworkMio {
    socket : UdpSocket
}

impl NetworkMio {
    fn new(group : &Ipv4Addr, port : u16) -> Self {
        let ip = IpAddr::V4(Ipv4Addr::new(0,0,0,0));
        let sockaddr = SocketAddr::new(ip, port);
        let socket = UdpSocket::bind(&sockaddr).unwrap();

        socket.join_multicast_v4(group, &Ipv4Addr::new(0,0,0,0)).unwrap();
        NetworkMio {
            socket : socket
        }
    }
}

impl SendDatagram for NetworkMio {
  fn send_datagram(&self, buf : &[u8], addr : SocketAddr) -> Result<usize> {
      unimplemented!();
  }
}

// =====================

struct TimersMio {
}

impl TimersMio {
    fn new() -> Self {
        TimersMio {
        }
    }
}

impl Timers for TimersMio {
  fn   start(&self, id : u32, timeout : Duration) {
      unimplemented!();
  }

  fn  cancel(&self, id : u32) {
      unimplemented!();
  }
}

// =====================

fn main() {
    let address = "224.2.2.2".parse().unwrap();
    let port    = 2223;

    let network = NetworkMio::new(&address, port);
    let timers  = TimersMio::new();
    let session = Session::<Inactive>::new(&network, &timers);

//    let active = session.join();
//    let leaving = active.leave();

    let poll = Poll::new().unwrap();
    let mut events = Events::with_capacity(1024);

    poll.register(&network.socket, TOKEN, Ready::readable(), PollOpt::edge()).unwrap();

    loop {
        poll.poll(&mut events, None).unwrap();

        for event in &events {
            match event.token() {
                TOKEN => {
                    println!("got event");
                }
                _ => panic!("event with unexpected token")
            }
        }
    }
}

<commit_msg>We can implement traits directly on mio::UdpSocket<commit_after>// Copyright (c) 2014-2016 University of Glasgow
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

extern crate byteorder;
extern crate mio;

mod packets;
mod session;

use session::*;
use std::io::Result;
use std::str::FromStr;
use std::net::{SocketAddr, IpAddr, Ipv4Addr};
use std::time::{Duration, Instant};
use mio::*;
use mio::udp::*;

const TOKEN : mio::Token = mio::Token(0);

// =====================

impl SendDatagram for UdpSocket {
  fn send_datagram(&self, buf : &[u8], addr : SocketAddr) -> Result<usize> {
      match self.send_to(buf, &addr) {
          Ok(None) => {
              Ok(0)     // EWOULDBLOCK
          }
          Ok(Some(size)) => {
              Ok(size)
          }
          Err(e) => {
              Err(e)
          }
      }
  }
}

// =====================

struct TimersMio {
}

impl TimersMio {
    fn new() -> Self {
        TimersMio {
        }
    }
}

impl Timers for TimersMio {
  fn   start(&self, id : u32, timeout : Duration) {
      unimplemented!();
  }

  fn  cancel(&self, id : u32) {
      unimplemented!();
  }
}

// =====================

fn main() {
    let port    = 2223;

    let ip = IpAddr::V4(Ipv4Addr::new(0,0,0,0));
    let sockaddr = SocketAddr::new(ip, port);
    let socket = UdpSocket::bind(&sockaddr).unwrap();

    socket.join_multicast_v4(&Ipv4Addr::new(224,2,2,2), &Ipv4Addr::new(0,0,0,0)).unwrap();

    let timers  = TimersMio::new();
    let session = Session::<Inactive>::new(&socket, &timers);

//    let active = session.join();
//    let leaving = active.leave();

    let poll = Poll::new().unwrap();
    let mut events = Events::with_capacity(1024);

    poll.register(&socket, TOKEN, Ready::readable(), PollOpt::edge()).unwrap();

    loop {
        poll.poll(&mut events, None).unwrap();

        for event in &events {
            match event.token() {
                TOKEN => {
                    println!("got event");
                }
                _ => panic!("event with unexpected token")
            }
        }
    }
}

<|endoftext|>


<commit_before>#![feature(slice_patterns)]
extern crate nix;
extern crate libc;
use std::env;
use libc::{pid_t,c_void};
use nix::sys::ptrace;
use nix::sys::ptrace::ptrace::{PTRACE_ATTACH,PTRACE_DETACH};
fn infect(pid: pid_t) -> Result<(),()> {
    ptrace::ptrace(PTRACE_ATTACH,pid,0 as *mut c_void ,0 as *mut c_void);

    // todo stuff

    ptrace::ptrace(PTRACE_DETACH,pid,0 as *mut c_void ,0 as *mut c_void);
    unimplemented!()
}
fn main() {
     let args: Vec<String> = env::args().collect();

     match &args[..] {
         &[ref pid, ref code] => {

             },
         _ => unimplemented!(),
     }
}
<commit_msg>much todo<commit_after>#![feature(slice_patterns)]
extern crate nix;
extern crate libc;
use std::env;
use libc::{pid_t,c_void};
use nix::sys::ptrace;
use nix::sys::ptrace::ptrace::{PTRACE_ATTACH,PTRACE_DETACH,PTRACE_GETREGS};

#[cfg(target_arch = "x86_64")]
#[derive(Debug,Default)]
#[repr(C)]
struct user_regs_struct {
    r15: u64,
    r14: u64,
    r13: u64,
    r12: u64,
    rbp: u64,
    rbx: u64,
    r11: u64,
    r10: u64,
    r9: u64,
    r8: u64,
    rax: u64,
    rcx: u64,
    rdx: u64,
    rsi: u64,
    rdi: u64,
    orig_rax: u64,
    rip: u64,
    cs: u64,
    eflags: u64,
    rsp: u64,
    ss: u64,
    fs_base: u64,
    gs_base: u64,
    ds: u64,
    es: u64,
    fs: u64,
    gs: u64,
}

fn infect(pid: pid_t) -> Result<(),()> {
    ptrace::ptrace(PTRACE_ATTACH,pid,0 as *mut c_void ,0 as *mut c_void);
    let mut regs: user_regs_struct = user_regs_struct::default();
    ptrace::ptrace(PTRACE_GETREGS,pid,&mut regs as *mut user_regs_struct as *mut c_void,&mut regs as *mut user_regs_struct as *mut c_void);
    println!("{:?}",regs);
    ptrace::ptrace(PTRACE_DETACH,pid,0 as *mut c_void ,0 as *mut c_void);
    unimplemented!()
}
fn main() {
     let args: Vec<String> = env::args().collect();

     match &args[1..] {
         &[ref pid, ref code] => {
            infect(2138);
             },
         _ => unimplemented!(),
     }
}
<|endoftext|>


<commit_before>use std::{env, process};

fn main() {
    let path_or_url = match env::args().nth(1) {
        Some(arg) => arg,
        None => {
            eprintln!("usage: open <path-or-url>");
            process::exit(1);
        }
    };

    match open::that(&path_or_url) {
        Ok(status) if status.success() => (),
        Ok(status) => match status.code() {
            Some(code) => open_error(code, &path_or_url, &format!("error code: {}", code)),
            None => open_error(3, &path_or_url, "error unknown"),
        },
        Err(err) => open_error(3, &path_or_url, &err.to_string()),
    }
}

fn open_error(code: i32, path: &str, error_message: &str) {
    eprintln!(
        "An error occurred when opening '{}': {}",
        path, error_message
    );
    process::exit(code);
}
<commit_msg>clarify what the error handler does<commit_after>use std::{env, process};

fn main() {
    let path_or_url = match env::args().nth(1) {
        Some(arg) => arg,
        None => {
            eprintln!("usage: open <path-or-url>");
            process::exit(1);
        }
    };

    match open::that(&path_or_url) {
        Ok(status) if status.success() => (),
        Ok(status) => match status.code() {
            Some(code) => print_error_and_exit(code, &path_or_url, &format!("error code: {}", code)),
            None => print_error_and_exit(3, &path_or_url, "error unknown"),
        },
        Err(err) => print_error_and_exit(3, &path_or_url, &err.to_string()),
    }
}

fn print_error_and_exit(code: i32, path: &str, error_message: &str) -> ! {
    eprintln!(
        "An error occurred when opening '{}': {}",
        path, error_message
    );
    process::exit(code);
}
<|endoftext|>


<commit_before>extern crate piston_window;
extern crate find_folder;

use piston_window::*;

#[derive(Copy, Clone, PartialEq)]
enum Player {
    X,
    O,
}

fn winner(board: &[[Option<Player>; 3]; 3], last_move: (usize, usize)) -> Option<Player> {
    let (y, x) = last_move;
    let player = board[y][x];

    // check row
    if board[y][0] == player && board[y][1] == player && board[y][2] == player {
        return player;
    }

    // check column
    if board[0][x] == player && board[1][x] == player && board[2][x] == player {
        return player;
    }

    match (y, x) {
        // not on a diagonal
        (0, 1) | (1, 0) | (1, 2) | (2, 1) => None,

        (y, x) => {
            // on a primary diagonal
            if y == x && board[0][0] == player && board[1][1] == player && board[2][2] == player {
                player
            }
            // on a secondary diagonal
            else if y + x == 2 && board[0][2] == player && board[1][1] == player && board[2][0] == player {
                player
            }
            else {
                None
            }
        }
    }
}

fn main() {
    let black = [0.0, 0.0, 0.0, 1.0];
    let white = [1.0, 1.0, 1.0, 1.0];

    let mut window: PistonWindow =
        WindowSettings::new("Tic Tac Toe!", [300, 300])
        .resizable(true)
        .build()
        .unwrap();

    // find the assets folder
    let assets = find_folder::Search::ParentsThenKids(3, 3)
        .for_folder("assets").unwrap();
    let font = assets.join("Verdana.ttf");
    let factory = window.factory.clone();

    // get font glyphs
    let mut glyphs = Glyphs::new(font, factory).unwrap();
    let mut board = [[None; 3]; 3];
    // click event flag
    let mut click = false;
    // gameover flag
    let mut gameover = false;
    // the player starting the game
    let mut player = Player::X;
    // current mouse cursor coordinates
    let mut coords = (0.0, 0.0);

    while let Some(e) = window.next() {

        if let Some(button) = e.release_args() {
            if button == Button::Mouse(MouseButton::Left) && !gameover {
                click = true;
            }
        }

        if let Some(pos) = e.mouse_cursor_args() {
            coords = (pos[0], pos[1]);
        }

        if click {
            let x = match coords.0 as u16 {
                0 ... 99 => 0,
                100 ... 199 => 1,
                200 ... 299 => 2,
                _ => unreachable!()
            };
            let y = match coords.1 as u16 {
                0 ... 99 => 0,
                100 ... 199 => 1,
                200 ... 299 => 2,
                _ => unreachable!()
            };
            if board[y][x] == None {
                board[y][x] = Some(player);
                // We have a winner!
                if let Some(winner) = winner(&board, (y, x)) {
                    match winner {
                        Player::X => window.set_title("X wins!".to_string()),
                        Player::O => window.set_title("O wins!".to_string()),
                    };
                    gameover = true;
                    continue;
                }
                // Pass the turn to the other player and
                // display an invitation for him to make a move
                player = match player {
                    Player::X => {
                        window.set_title("Your move, O!".to_string());
                        Player::O
                    }
                    Player::O => {
                        window.set_title("Your move, X!".to_string());
                        Player::X
                    }
                }
            }
            click = false;
        }

        // Draw the board
        window.draw_2d(&e, |c, g| {
            clear(white, g);
            for (y, row) in board.into_iter().enumerate() {
                let y = y as f64;
                for (x, cell) in row.into_iter().enumerate() {
                    let x = x as f64;
                    let ct = c.transform.trans(100.0*x, 95.0+100.0*y);
                    match *cell {
                        // Print "O" character on the board
                        Some(Player::O) => text::Text::new_color(black, 150).draw(
                            "o",
                            &mut glyphs,
                            &c.draw_state,
                            ct, g
                        ),
                        // Print "X" character on the board
                        Some(Player::X) => text::Text::new_color(black, 150).draw(
                            "x",
                            &mut glyphs,
                            &c.draw_state,
                            ct, g
                        ),
                        None => {}
                    }
                }
            }
        });
    }
}
<commit_msg>Moved board data into a tuple struct<commit_after>extern crate piston_window;
extern crate find_folder;

use piston_window::*;
use std::ops::{Index, IndexMut};

#[derive(Copy, Clone, PartialEq)]
enum Player { X, O }

struct Board([[Option<Player>; 3]; 3]);

impl Board {
    fn new() -> Self {
        Board([[None; 3]; 3])
    }

    fn winner(&self, last_move: (usize, usize)) -> Option<Player> {
        let (y, x) = last_move;
        let board = self.0;
        let player = board[y][x];

        // check row
        if board[y][0] == player && board[y][1] == player && board[y][2] == player {
            return player;
        }

        // check column
        if board[0][x] == player && board[1][x] == player && board[2][x] == player {
            return player;
        }

        match (y, x) {
            // not on a diagonal
            (0, 1) | (1, 0) | (1, 2) | (2, 1) => None,

            (y, x) => {
                // on a primary diagonal
                if y == x && board[0][0] == player && board[1][1] == player && board[2][2] == player {
                    player
                }
                // on a secondary diagonal
                else if y + x == 2 && board[0][2] == player && board[1][1] == player && board[2][0] == player {
                    player
                }
                // everything else
                else {
                    None
                }
            }
        }
    }
}

impl Index<usize> for Board {
    type Output = [Option<Player>; 3];

    fn index(&self, index: usize) -> &Self::Output {
        &self.0[index]
    }
}

impl IndexMut<usize> for Board {
    fn index_mut<'a>(&'a mut self, index: usize) -> &'a mut [Option<Player>; 3] {
        &mut self.0[index]
    }
}

impl<'a> IntoIterator for &'a Board {
    type Item = &'a [Option<Player>; 3];
    type IntoIter = std::slice::Iter<'a, [Option<Player>; 3]>;

    fn into_iter(self) -> Self::IntoIter {
        self.0.into_iter()
    }
}

fn main() {
    let black = [0.0, 0.0, 0.0, 1.0];
    let white = [1.0, 1.0, 1.0, 1.0];

    let mut window: PistonWindow =
        WindowSettings::new("Tic Tac Toe!", [300, 300])
        .resizable(true)
        .build()
        .unwrap();

    // find the assets folder
    let assets = find_folder::Search::ParentsThenKids(3, 3)
        .for_folder("assets")
        .unwrap();

    let font = assets.join("Verdana.ttf");
    let factory = window.factory.clone();

    // get font glyphs
    let mut glyphs = Glyphs::new(font, factory).unwrap();
    let mut board = Board::new();
    // click event flag
    let mut click = false;
    // gameover flag
    let mut gameover = false;
    // the player starting the game
    let mut player = Player::X;
    // current mouse cursor coordinates
    let mut coords = (0.0, 0.0);

    while let Some(e) = window.next() {

        if let Some(button) = e.release_args() {
            if button == Button::Mouse(MouseButton::Left) && !gameover {
                click = true;
            }
        }

        if let Some(pos) = e.mouse_cursor_args() {
            coords = (pos[0], pos[1]);
        }

        if click {
            let x = match coords.0 as u16 {
                0 ... 99 => 0,
                100 ... 199 => 1,
                200 ... 299 => 2,
                _ => unreachable!()
            };
            let y = match coords.1 as u16 {
                0 ... 99 => 0,
                100 ... 199 => 1,
                200 ... 299 => 2,
                _ => unreachable!()
            };
            if board[y][x] == None {
                board[y][x] = Some(player);
                // We have a winner!
                if let Some(winner) = board.winner((y, x)) {
                    match winner {
                        Player::X => window.set_title("X wins!".to_string()),
                        Player::O => window.set_title("O wins!".to_string()),
                    };
                    gameover = true;
                    continue;
                }
                // Pass the turn to the other player and
                // display an invitation for him to make a move
                player = match player {
                    Player::X => {
                        window.set_title("Your move, O!".to_string());
                        Player::O
                    }
                    Player::O => {
                        window.set_title("Your move, X!".to_string());
                        Player::X
                    }
                }
            }
            click = false;
        }

        // Draw the board
        window.draw_2d(&e, |c, g| {
            clear(white, g);
            for (y, row) in board.into_iter().enumerate() {
                let y = y as f64;
                for (x, cell) in row.into_iter().enumerate() {
                    let x = x as f64;
                    let ct = c.transform.trans(100.0*x, 95.0+100.0*y);
                    match *cell {
                        // Print "O" character on the board
                        Some(Player::O) => text::Text::new_color(black, 150).draw(
                            "o",
                            &mut glyphs,
                            &c.draw_state,
                            ct, g
                        ),
                        // Print "X" character on the board
                        Some(Player::X) => text::Text::new_color(black, 150).draw(
                            "x",
                            &mut glyphs,
                            &c.draw_state,
                            ct, g
                        ),
                        None => {}
                    }
                }
            }
        });
    }
}
<|endoftext|>


<commit_before>
extern crate moss;
use std::env;
use moss::object::{Object,Map};
use moss::CompilerExtra;

const HELP: &'static str = r#"
Usage: moss [options] [file] [arguments]

Options:
-i file     Include and execute a file before normal execution.
            Multiple files are possible: '-i file1 -i file2'.

-m          Math mode: use moss as a calculator.

-e "1+2"    Evaluate some Moss code inline.

-d          Debug mode: compile assert statements.
"#;

const MATH: &'static str = r#"
use math{
  e, pi, nan, inf,
  floor, ceil, exp, sqrt, ln, lg,
  sin, cos, tan, sinh, cosh, tanh,
  asin, acos, atan, asinh, acosh, atanh,
  hypot, atan2, gamma, erf
}
"#;

fn is_option(s: &str) -> bool {
    s.len()>0 && &s[0..1]=="-"
}

struct IFile{
    s: String,
    e: bool
}

struct Info{
    program: Option<String>,
    ifile: Vec<IFile>,
    argv: Vec<String>,
    cmd: Option<String>,
    exit: bool,
    math: bool,
    debug_mode: bool
}

impl Info{
    pub fn new() -> Box<Self> {
        let mut info = Info{
            program: None,
            ifile: Vec::new(),
            argv: Vec::new(),
            cmd: None,
            exit: false,
            math: false,
            debug_mode: false
        };
        let mut first = true;
        let mut ifile = false;
        let mut cmd = false;
        let mut args = false;
        for s in env::args() {
            if args {
                info.argv.push(s);
            }else if first {
                info.program = Some(s);
                first = false;
            }else if is_option(&s) {
                if s=="-i" {
                    ifile = true;
                }else if s=="-e" {
                    cmd = true;
                }else if s=="-ei" {
                    ifile = true;
                    cmd = true;
                }else if s=="-m" {
                    info.math = true;
                }else if s=="-h" || s=="-help" || s=="--help" {
                    println!("{}",HELP);
                    info.exit = true;
                    return Box::new(info);
                }else if s=="-d" {
                    info.debug_mode = true;
                }else{
                    println!("Error: unknown option: {}.",&s);
                }
            }else if ifile {
                info.ifile.push(IFile{s: s, e: cmd});
                ifile = false;
                cmd = false;
            }else if cmd {
                info.cmd = Some(s);
            }else{
                info.argv.push(s);
                args = true;
            }
        }
        return Box::new(info);
    }
}

fn main(){
    let info = Info::new();
    let i = moss::Interpreter::new();
    i.set_config(CompilerExtra{
        debug_mode: info.debug_mode
    });

    let gtab = Map::new();
    i.rte.clear_at_exit(gtab.clone());

    if info.exit {return;}

    {
        let mut argv = i.rte.argv.borrow_mut();
        *argv = Some(moss::new_list_str(&info.argv));
    }
    let mut ilock = i.lock();
    let mut env = ilock.env();

    if info.math {
        env.eval_env(MATH,gtab.clone());
    }
    for file in &info.ifile {
        if file.e {
            env.eval_env(&file.s,gtab.clone());
        }else{
            env.eval_file(&file.s,gtab.clone());
        }
    }
    if let Some(ref id) = info.argv.first() {
        if id.len()==0 {
            env.command_line_session(gtab);
        }else{
            env.eval_file(id,gtab);
        }
    }else if let Some(ref cmd) = info.cmd {
        let x = env.eval_env(cmd,gtab);
        if x != Object::Null {
            println!("{}",i.repr(&x));
        }
    }else{
        env.command_line_session(gtab);
    }
}

<commit_msg>update<commit_after>
extern crate moss;
use std::env;
use moss::object::{Object,Map};
use moss::CompilerExtra;

const HELP: &'static str = r#"
Usage: moss [options] [file] [arguments]

Options:
-i file     Include and execute a file before normal execution.
            Multiple files are possible: '-i file1 -i file2'.

-m          Math mode: use moss as a calculator.

-e "1+2"    Evaluate some Moss code inline.

-d          Debug mode: compile assert statements.
"#;

const MATH: &'static str = r#"
use math{
  e, pi, nan, inf,
  floor, ceil, exp, sqrt, ln, lg,
  sin, cos, tan, sinh, cosh, tanh,
  asin, acos, atan, asinh, acosh, atanh,
  hypot, atan2, gamma, erf
}
"#;

fn is_option(s: &str) -> bool {
    s.len()>0 && &s[0..1]=="-"
}

struct IFile{
    s: String,
    e: bool
}

struct Info{
    program: Option<String>,
    ifile: Vec<IFile>,
    argv: Vec<String>,
    cmd: Option<String>,
    exit: bool,
    math: bool,
    debug_mode: bool
}

impl Info{
    pub fn new() -> Box<Self> {
        let mut info = Info{
            program: None,
            ifile: Vec::new(),
            argv: Vec::new(),
            cmd: None,
            exit: false,
            math: false,
            debug_mode: false
        };
        let mut first = true;
        let mut ifile = false;
        let mut cmd = false;
        let mut args = false;
        for s in env::args() {
            if args {
                info.argv.push(s);
            }else if first {
                info.program = Some(s);
                first = false;
            }else if is_option(&s) {
                if s=="-i" {
                    ifile = true;
                }else if s=="-e" {
                    cmd = true;
                }else if s=="-ei" {
                    ifile = true;
                    cmd = true;
                }else if s=="-m" {
                    info.math = true;
                }else if s=="-h" || s=="-help" || s=="--help" {
                    println!("{}",HELP);
                    info.exit = true;
                    return Box::new(info);
                }else if s=="-d" {
                    info.debug_mode = true;
                }else{
                    println!("Error: unknown option: {}.",&s);
                }
            }else if ifile {
                info.ifile.push(IFile{s: s, e: cmd});
                ifile = false;
                cmd = false;
            }else if cmd {
                info.cmd = Some(s);
            }else{
                info.argv.push(s);
                args = true;
            }
        }
        return Box::new(info);
    }
}

fn main(){
    let info = Info::new();
    let i = moss::Interpreter::new();
    i.set_config(CompilerExtra{
        debug_mode: info.debug_mode
    });

    let gtab = Map::new();
    i.rte.clear_at_exit(gtab.clone());

    if info.exit {return;}

    {
        let mut argv = i.rte.argv.borrow_mut();
        *argv = Some(moss::new_list_str(&info.argv));
    }
    let mut ilock = i.lock();
    let mut env = ilock.env();

    if info.math {
        env.eval_env(MATH,gtab.clone());
    }
    for file in &info.ifile {
        if file.e {
            env.eval_env(&file.s,gtab.clone());
        }else{
            env.eval_file(&file.s,gtab.clone());
        }
    }
    if let Some(ref id) = info.argv.first() {
        if id.len()==0 {
            env.command_line_session(gtab);
        }else{
            env.eval_file(id,gtab);
        }
    }else if let Some(ref cmd) = info.cmd {
        let x = env.eval_env(cmd,gtab);
        if x != Object::Null {
            match x.repr(&mut env) {
                Ok(s) => println!("{}",s),
                Err(e) => {
                    println!("{}",env.exception_to_string(&e));
                    println!("[exception in Interpreter::repr, see stdout]");
                }
            }
        }
    }else{
        env.command_line_session(gtab);
    }
}

<|endoftext|>


<commit_before>extern crate image;
extern crate clap;
extern crate rand;
extern crate itertools;

mod rgba;

mod utils;

fn main()
{
    println!("Hello, world!");
}
<commit_msg>Experimental frontend<commit_after>extern crate image;
extern crate clap;
extern crate rand;
extern crate itertools;

use clap::*;

mod rgba;

mod utils;

fn main()
{
    let matches = App::new("stag")
        .version("0.0.1")
        .about("Image steganography")
        .subcommand(SubCommand::with_name("encode")
            .about("encodes a file")
            .arg(Arg::with_name("mode")
                 .short("m")
                 .long("mode")
                 .value_name("MODE")
                 .help("Set the encoding mode, default depends on SOURCE type")
                 .takes_value(true))
            .arg(Arg::with_name("SOURCE")
                 .help("The image source")
                 .index(1)
                 .required(true)))
        .subcommand(SubCommand::with_name("decode")
            .about("decodes a file")
            .arg(Arg::with_name("mode")
                 .short("m")
                 .long("mode")
                 .value_name("MODE")
                 .help("Set the decoding mode, default depends on SOURCE type")
                 .takes_value(true))
            .arg(Arg::with_name("SOURCE")
                 .help("The image source")
                 .index(1)
                 .required(true))
            .arg(Arg::with_name("OUTPUT")
                 .help("The output image")
                 .index(2)
                 .required(true)))
        .get_matches();

    if let Some(matches) = matches.subcommand_matches("encode")
    {
        encode(
            matches.value_of("mode"),
            matches.value_of("SOURCE").unwrap(),
            matches.value_of("OUTPUT").unwrap()
        );
    }

    if let Some(matches) = matches.subcommand_matches("decode")
    {
        decode(
            matches.value_of("mode"),
            matches.value_of("SOURCE").unwrap()
        );
    }
}

use std::io::{stdin, stdout, Read, Write};
use std::fs::File;

use image::{open, DynamicImage};
use rand::StdRng;

use rgba::{encode_rgba, decode_rgba, RgbaMode};

fn encode(mode: Option<&str>, source: &str, output: &str)
{
    let dyimage = match open(source)
    {
        Ok(di) => di,
        Err(_) =>
        {
            eprintln!("Error opening source image");
            ::std::process::exit(1);
        },
    };

    match dyimage
    {
        DynamicImage::ImageRgba8(mut image) =>
        {
            let mode = match mode
            {
                Some("alpha") => RgbaMode::Alpha,
                Some("all") => RgbaMode::All,
                Some(_) | None => RgbaMode::Alpha,
            };

            let rng = match StdRng::new()
            {
                Ok(r) => r,
                Err(_) =>
                {
                    eprintln!("Error creating an RNG");
                    std::process::exit(1);
                }
            };

            let mut payload = String::new();
            stdin().read_to_string(&mut payload).unwrap();

            encode_rgba(&mut image, &payload.bytes().collect::<Vec<_>>(), mode, rng);

            match image.save(output)
            {
                Ok(_) => {},
                Err(_) =>
                {
                    eprintln!("Error saving output file");
                    ::std::process::exit(1);
                }
            };
        },
        _ => unimplemented!()
    }
}

fn decode(mode: Option<&str>, source: &str)
{
    let dyimage = match open(source)
    {
        Ok(di) => di,
        Err(_) =>
        {
            eprintln!("Error opening source image");
            ::std::process::exit(1);
        },
    };

    match dyimage
    {
        DynamicImage::ImageRgba8(image) =>
        {
            let mode = match mode
            {
                Some("alpha") => RgbaMode::Alpha,
                Some("all") => RgbaMode::All,
                Some(_) | None => RgbaMode::Alpha,
            };

            let payload = decode_rgba(&image, mode);

            match stdout().write(&payload)
            {
                Ok(_) => {},
                Err(_) =>
                {
                    eprintln!("Error writing payload");
                    ::std::process::exit(1);
                }
            };
        },
        _ => unimplemented!()
    }
}
<|endoftext|>


<commit_before>//! SEGIMAP is an IMAP server implementation.
#![feature(macro_rules)]
#![deny(non_camel_case_types)]
#![feature(phase)]

extern crate "rust-crypto" as crypto;
extern crate regex;
#[phase(plugin)] extern crate regex_macros;
#[phase(plugin, link)] extern crate log;
extern crate serialize;
extern crate toml;

pub use config::Config;
pub use email::Email;
pub use login::LoginData;
pub use message::Message;
pub use server::Server;
pub use session::Session;
pub use user::User;

use std::io::{Listener, Acceptor, BufferedStream};
use std::sync::Arc;

mod auth;
mod config;
mod email;
mod error;
mod folder;
mod login;
mod message;
mod server;
mod session;
mod user;

/// The file in which user data is stored.
// TODO: add the ability for the user to specify the user data file as an
// argument.
static USER_DATA_FILE: &'static str = "./users.json";

fn main() {
    // Load configuration.
    let config = Config::new();

    // Load the user data from the user data file.
    // TODO: figure out what to do for error handling.
    let users = user::load_users(USER_DATA_FILE.to_string()).unwrap();

    let multipart_message = Message::parse(&Path::new("maildir/new/12345:2,FRS")).unwrap();
    let html_message = Message::parse(&Path::new("maildir/cur/54321:2,FS")).unwrap();

    // Avoid unused variable notices temporarily.
    //println!("Config: {}", config);
    //println!("Users: {}", users);
    //println!("Message: {}", multipart_message);
    //println!("Message: {}", html_message);

    let serv = Arc::new(Server::new(config, users));
    match serv.imap_listener() {
        Err(_) => {
            println!("Error listening on IMAP port!");
        }
        Ok(v) => {
            let mut acceptor = v.listen();
            for stream in acceptor.incoming() {
                match stream {
                    Err(e) => {
                        println!("Error accepting incoming connection!")
                    }
                    Ok(stream) => {
                        let session_serv = serv.clone();
                        spawn(proc() {
                            let mut session = Session::new(BufferedStream::new(stream), session_serv);
                            session.handle();
                        });
                    }
                }
            }
            drop(acceptor);
        }
    }
}
<commit_msg>Uncomment a println statement<commit_after>//! SEGIMAP is an IMAP server implementation.
#![feature(macro_rules)]
#![deny(non_camel_case_types)]
#![feature(phase)]

extern crate "rust-crypto" as crypto;
extern crate regex;
#[phase(plugin)] extern crate regex_macros;
#[phase(plugin, link)] extern crate log;
extern crate serialize;
extern crate toml;

pub use config::Config;
pub use email::Email;
pub use login::LoginData;
pub use message::Message;
pub use server::Server;
pub use session::Session;
pub use user::User;

use std::io::{Listener, Acceptor, BufferedStream};
use std::sync::Arc;

mod auth;
mod config;
mod email;
mod error;
mod folder;
mod login;
mod message;
mod server;
mod session;
mod user;

/// The file in which user data is stored.
// TODO: add the ability for the user to specify the user data file as an
// argument.
static USER_DATA_FILE: &'static str = "./users.json";

fn main() {
    // Load configuration.
    let config = Config::new();

    // Load the user data from the user data file.
    // TODO: figure out what to do for error handling.
    let users = user::load_users(USER_DATA_FILE.to_string()).unwrap();

    let multipart_message = Message::parse(&Path::new("maildir/new/12345:2,FRS")).unwrap();
    let html_message = Message::parse(&Path::new("maildir/cur/54321:2,FS")).unwrap();

    // Avoid unused variable notices temporarily.
    //println!("Config: {}", config);
    //println!("Users: {}", users);
    //println!("Message: {}", multipart_message);
    println!("Message: {}", html_message);

    let serv = Arc::new(Server::new(config, users));
    match serv.imap_listener() {
        Err(_) => {
            println!("Error listening on IMAP port!");
        }
        Ok(v) => {
            let mut acceptor = v.listen();
            for stream in acceptor.incoming() {
                match stream {
                    Err(e) => {
                        println!("Error accepting incoming connection!")
                    }
                    Ok(stream) => {
                        let session_serv = serv.clone();
                        spawn(proc() {
                            let mut session = Session::new(BufferedStream::new(stream), session_serv);
                            session.handle();
                        });
                    }
                }
            }
            drop(acceptor);
        }
    }
}
<|endoftext|>


<commit_before>#![feature(conservative_impl_trait)]

extern crate curl;
extern crate env_logger;
extern crate futures;
extern crate tokio_core;
extern crate tokio_curl;
#[macro_use]
extern crate clap;
extern crate chrono;
extern crate histogram;

mod args;

use args::{Config, parse_args};

use curl::easy::Easy;
use futures::{Future, stream};
use futures::future::{ok, loop_fn, Loop};
use futures::Stream;
use tokio_core::reactor::Core;
use tokio_curl::{PerformError, Session};
use chrono::*;
use std::sync::mpsc::channel;
use histogram::*;
use std::thread;

struct RequestResult {
    /// The worker that processed the request
    worker: Worker,
    /// The curl easy response to the request
    curl_easy: Easy,
}

impl RequestResult {
    fn new(worker: Worker, curl_easy: Easy) -> Self {
        RequestResult {
            worker: worker,
            curl_easy: curl_easy,
        }
    }
}

struct Worker {
    /// Number of succesful requests this worker has made
    num_requests: usize,
    histogram: Histogram,
    /// Number of failed requests this worker has made
    num_failed_requests: usize,
}

impl Worker {
    pub fn new() -> Self {
        Worker {
            num_requests: 0,
            histogram: Histogram::new(),
            num_failed_requests: 0,
        }
    }

    fn merge(&mut self, other: &Self) {
        self.num_requests += other.num_requests;
        self.num_failed_requests += other.num_failed_requests;
        self.histogram.merge(&other.histogram);
    }

    fn send_request(mut self, easy_request: Easy, session: &Session) -> impl Future<Item=RequestResult, Error=PerformError> {
        session.perform(easy_request)
            .then(|res| {
                match res {
                    Ok(mut easy) => {
                        self.num_requests += 1;
                        easy.total_time()
                            .ok()
                            .and_then(|x| Duration::from_std(x).ok())
                            .and_then(|latency| {
                                latency.num_nanoseconds()
                                    .map(|x| self.histogram.increment(x as u64).ok())
                            });
                        let request_result = RequestResult::new(self, easy);
                        Ok(request_result)
                    }
                    Err(error) => {
                        self.num_failed_requests += 1;
                        Err(error)
                    }
                }
            })
    }
}

struct RunInfo {
    /// Number of requests successfully completed
    pub requests_completed: usize,
    pub duration: Duration,
    histogram: Histogram,
    /// Number of failed requests
    num_failed_requests: usize,
}

impl RunInfo {
    pub fn requests_per_second(&self) -> f32 {
        (self.requests_completed as f32) / (self.duration.num_seconds() as f32)
    }
}

/// Delegates and manages all the work.
struct Boss {
    /// Number of requests successfully completed
    pub requests_completed: usize,
    /// Number of active connections
    pub connections: usize,
    num_threads: usize,
}

impl Boss {
    pub fn new(num_threads: usize) -> Self {
        Boss {
            requests_completed: 0,
            connections: 0,
            num_threads: num_threads,
        }
    }

    pub fn start_workforce(&self,
                           desired_connections: usize,
                           url: String,
                           duration: Duration)
                           -> RunInfo {
        let (tx, rx) = channel();
        for _ in 0..self.num_threads {
            let tx = tx.clone();
            let url = url.clone();
            thread::spawn(move || {

                let mut lp = Core::new().unwrap();
                let start_time = Local::now();
                let wanted_end_time = start_time + duration;
                let session = Session::new(lp.handle());

                let iterator = (0..desired_connections).map(|_| {
                    let mut easy_request = Easy::new();
                    easy_request.get(true).unwrap();
                    easy_request.url(&url).unwrap();
                    let request_result = RequestResult::new(Worker::new(), easy_request);
                    loop_fn(request_result, |request_result| {
                        request_result.worker.send_request(request_result.curl_easy, &session)
                            .and_then(|state| {
                                let now_time = Local::now();
                                if now_time < wanted_end_time {
                                    Ok(Loop::Continue(state))
                                } else {
                                    Ok(Loop::Break(state))
                                }
                            })
                    })
                        // Extract worker statistics
                        .map(|request_res| request_res.worker)
                });
                let future = stream::futures_unordered(iterator)
                    .fold(Worker::new(), |mut worker_acc, worker| {
                        worker_acc.merge(&worker);
                        ok(worker_acc)
                    });
                let res = lp.run(future).unwrap();
                tx.send(res).unwrap();
            });
        }
        // collect information from all workers
        let worker_info: Worker = rx.iter()
            .take(self.num_threads)
            .fold(Worker::new(), |mut worker_acc, worker| {
                worker_acc.merge(&worker);
                worker_acc
            });
        RunInfo {
            requests_completed: worker_info.num_requests,
            num_failed_requests: worker_info.num_failed_requests,
            duration: duration,
            histogram: worker_info.histogram,
        }
    }
}

fn start(config: Config) -> RunInfo {
    let boss = Boss::new(config.num_threads);
    boss.start_workforce(config.num_connections, config.url, config.duration)
}

fn nanoseconds_to_milliseconds(nanoseconds: u64) -> f64 {
    nanoseconds as f64 / 1_000_000_f64
}

/// Presents the results to the user
fn present(run_info: RunInfo) {
    let requests_completed = run_info.requests_completed;
    println!("{} requests in {}s",
             requests_completed,
             run_info.duration.num_seconds());
    println!("{} failed requests", run_info.num_failed_requests);
    println!("Requests per second: {}", run_info.requests_per_second());
    println!("Latency distribution: \n50%: {} ms\n75%: {} ms\n90%: {} ms\n95%: {} ms\n99%: {} ms",
        run_info.histogram.percentile(50.0).map(nanoseconds_to_milliseconds).unwrap(),
        run_info.histogram.percentile(75.0).map(nanoseconds_to_milliseconds).unwrap(),
        run_info.histogram.percentile(90.0).map(nanoseconds_to_milliseconds).unwrap(),
        run_info.histogram.percentile(95.0).map(nanoseconds_to_milliseconds).unwrap(),
        run_info.histogram.percentile(99.0).map(nanoseconds_to_milliseconds).unwrap(),
    );
}

fn main() {
    env_logger::init().unwrap();
    let config = parse_args();
    let run_info = start(config);
    present(run_info)
}
<commit_msg>Disregard send_request error The error is not needed further down the line. The worker keeps track of the number of failed requests<commit_after>#![feature(conservative_impl_trait)]

extern crate curl;
extern crate env_logger;
extern crate futures;
extern crate tokio_core;
extern crate tokio_curl;
#[macro_use]
extern crate clap;
extern crate chrono;
extern crate histogram;

mod args;

use args::{Config, parse_args};

use curl::easy::Easy;
use futures::{Future, stream};
use futures::future::{ok, loop_fn, Loop};
use futures::Stream;
use tokio_core::reactor::Core;
use tokio_curl::Session;
use chrono::*;
use std::sync::mpsc::channel;
use histogram::*;
use std::thread;

struct RequestResult {
    /// The worker that processed the request
    worker: Worker,
    /// The curl easy response to the request
    curl_easy: Easy,
}

impl RequestResult {
    fn new(worker: Worker, curl_easy: Easy) -> Self {
        RequestResult {
            worker: worker,
            curl_easy: curl_easy,
        }
    }
}

struct Worker {
    /// Number of succesful requests this worker has made
    num_requests: usize,
    histogram: Histogram,
    /// Number of failed requests this worker has made
    num_failed_requests: usize,
}

impl Worker {
    pub fn new() -> Self {
        Worker {
            num_requests: 0,
            histogram: Histogram::new(),
            num_failed_requests: 0,
        }
    }

    fn merge(&mut self, other: &Self) {
        self.num_requests += other.num_requests;
        self.num_failed_requests += other.num_failed_requests;
        self.histogram.merge(&other.histogram);
    }

    fn send_request(mut self,
                    easy_request: Easy,
                    session: &Session)
                    -> impl Future<Item = RequestResult, Error = ()> {
        session.perform(easy_request)
            .then(|res| match res {
                Ok(mut easy) => {
                    self.num_requests += 1;
                    easy.total_time()
                        .ok()
                        .and_then(|x| Duration::from_std(x).ok())
                        .and_then(|latency| {
                            latency.num_nanoseconds()
                                .map(|x| self.histogram.increment(x as u64).ok())
                        });
                    let request_result = RequestResult::new(self, easy);
                    Ok(request_result)
                }
                Err(_) => {
                    self.num_failed_requests += 1;
                    Err(())
                }
            })
    }
}

struct RunInfo {
    /// Number of requests successfully completed
    pub requests_completed: usize,
    pub duration: Duration,
    histogram: Histogram,
    /// Number of failed requests
    num_failed_requests: usize,
}

impl RunInfo {
    pub fn requests_per_second(&self) -> f32 {
        (self.requests_completed as f32) / (self.duration.num_seconds() as f32)
    }
}

/// Delegates and manages all the work.
struct Boss {
    /// Number of requests successfully completed
    pub requests_completed: usize,
    /// Number of active connections
    pub connections: usize,
    num_threads: usize,
}

impl Boss {
    pub fn new(num_threads: usize) -> Self {
        Boss {
            requests_completed: 0,
            connections: 0,
            num_threads: num_threads,
        }
    }

    pub fn start_workforce(&self,
                           desired_connections: usize,
                           url: String,
                           duration: Duration)
                           -> RunInfo {
        let (tx, rx) = channel();
        for _ in 0..self.num_threads {
            let tx = tx.clone();
            let url = url.clone();
            thread::spawn(move || {

                let mut lp = Core::new().unwrap();
                let start_time = Local::now();
                let wanted_end_time = start_time + duration;
                let session = Session::new(lp.handle());

                let iterator = (0..desired_connections).map(|_| {
                    let mut easy_request = Easy::new();
                    easy_request.get(true).unwrap();
                    easy_request.url(&url).unwrap();
                    let request_result = RequestResult::new(Worker::new(), easy_request);
                    loop_fn(request_result, |request_result| {
                        request_result.worker.send_request(request_result.curl_easy, &session)
                            .and_then(|state| {
                                let now_time = Local::now();
                                if now_time < wanted_end_time {
                                    Ok(Loop::Continue(state))
                                } else {
                                    Ok(Loop::Break(state))
                                }
                            })
                    })
                        // Extract worker statistics
                        .map(|request_res| request_res.worker)
                });
                let future = stream::futures_unordered(iterator)
                    .fold(Worker::new(), |mut worker_acc, worker| {
                        worker_acc.merge(&worker);
                        ok(worker_acc)
                    });
                let res = lp.run(future).unwrap();
                tx.send(res).unwrap();
            });
        }
        // collect information from all workers
        let worker_info: Worker = rx.iter()
            .take(self.num_threads)
            .fold(Worker::new(), |mut worker_acc, worker| {
                worker_acc.merge(&worker);
                worker_acc
            });
        RunInfo {
            requests_completed: worker_info.num_requests,
            num_failed_requests: worker_info.num_failed_requests,
            duration: duration,
            histogram: worker_info.histogram,
        }
    }
}

fn start(config: Config) -> RunInfo {
    let boss = Boss::new(config.num_threads);
    boss.start_workforce(config.num_connections, config.url, config.duration)
}

fn nanoseconds_to_milliseconds(nanoseconds: u64) -> f64 {
    nanoseconds as f64 / 1_000_000_f64
}

/// Presents the results to the user
fn present(run_info: RunInfo) {
    let requests_completed = run_info.requests_completed;
    println!("{} requests in {}s",
             requests_completed,
             run_info.duration.num_seconds());
    println!("{} failed requests", run_info.num_failed_requests);
    println!("Requests per second: {}", run_info.requests_per_second());
    println!("Latency distribution: \n50%: {} ms\n75%: {} ms\n90%: {} ms\n95%: {} ms\n99%: {} ms",
        run_info.histogram.percentile(50.0).map(nanoseconds_to_milliseconds).unwrap(),
        run_info.histogram.percentile(75.0).map(nanoseconds_to_milliseconds).unwrap(),
        run_info.histogram.percentile(90.0).map(nanoseconds_to_milliseconds).unwrap(),
        run_info.histogram.percentile(95.0).map(nanoseconds_to_milliseconds).unwrap(),
        run_info.histogram.percentile(99.0).map(nanoseconds_to_milliseconds).unwrap(),
    );
}

fn main() {
    env_logger::init().unwrap();
    let config = parse_args();
    let run_info = start(config);
    present(run_info)
}
<|endoftext|>


<commit_before>// Copyright 2016 Alex Crawford
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate clap;
extern crate hyper;
extern crate pulldown_cmark;
extern crate url;
extern crate walkdir;

use clap::{Arg, App};
use hyper::client::Client;
use hyper::status::StatusCode;
use pulldown_cmark::{Event, OPTION_ENABLE_TABLES, Parser, Tag};
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;
use std::process::exit;
use url::{ParseError, Url};
use walkdir::WalkDir;

macro_rules! fail {
    ($($print:expr),+) => {
        {
            let _ = writeln!(&mut std::io::stderr(), $($print),+);
            exit(2);
        }
    };
}

macro_rules! print_issue {
    ($flag:expr, $($print:expr),+) => {
        {
            println!($($print),+);
            $flag = true;
        }
    };
}

struct State<'a> {
    skip_http: bool,
    code_block: bool,
    last_text: String,
    directory: &'a Path,
}

enum LinkError {
    PathAbsolute,
    PathNonExistant,
    HttpStatus(StatusCode),
    HttpError(hyper::error::Error),
    UrlMalformed(ParseError),
}

fn main() {
    let matches = App::new("Marker")
        .version(crate_version!())
        .arg(Arg::with_name("root")
            .short("r")
            .long("root")
            .help("The path to the root of the documentation to be checked")
            .takes_value(true))
        .arg(Arg::with_name("skip-http")
            .long("skip-http")
            .help("Skip validation of HTTP[S] URLs"))
        .get_matches();

    let skip_http = matches.is_present("skip-http");
    let root = Path::new(matches.value_of("root").unwrap_or("."));
    let mut links = HashMap::new();
    let mut found_issue = false;

    for entry in WalkDir::new(root).into_iter().filter_map(|entry| {
        let entry = entry.unwrap_or_else(|err| {
            fail!("Failed to walk directory: {}", err);
        });
        if entry.file_type().is_file() && entry.path().extension() == Some(OsStr::new("md")) {
            Some(entry)
        } else {
            None
        }
    }) {
        let contents = {
            let mut file = File::open(entry.path()).unwrap_or_else(|err| {
                fail!("Failed to open file ({}): {}", entry.path().display(), err);
            });
            let mut text = String::new();
            if let Err(err) = file.read_to_string(&mut text) {
                fail!("Failed to read file ({}): {}", entry.path().display(), err);
            };
            text
        };

        let mut state = State {
            skip_http: skip_http,
            code_block: false,
            last_text: String::new(),
            directory: entry.path().parent().expect("non-root path"),
        };
        for event in Parser::new_ext(&contents, OPTION_ENABLE_TABLES) {
            match event {
                Event::Text(ref text) => {
                    state.last_text = text.to_string();
                    if let Some(reference) = try_reference(&state, text) {
                        print_issue!(found_issue,
                                     "Found broken reference ({}) in {}",
                                     reference,
                                     entry.path().display())
                    }
                }
                Event::End(Tag::Link(dest, _)) => {
                    match check_link(&mut state, &mut links, &dest) {
                        Ok(()) => {}
                        Err(LinkError::PathAbsolute) => {
                            print_issue!(found_issue,
                                         "Found absolute path    ({} -> {}) in {}",
                                         state.last_text,
                                         dest,
                                         entry.path().display())
                        }
                        Err(LinkError::PathNonExistant) => {
                            print_issue!(found_issue,
                                         "Found broken path      ({} -> {}) in {}",
                                         state.last_text,
                                         dest,
                                         entry.path().display())
                        }
                        Err(LinkError::HttpStatus(status)) => {
                            print_issue!(found_issue,
                                         "Found broken url       ({} -> {}) in {}: {}",
                                         state.last_text,
                                         dest,
                                         entry.path().display(),
                                         status)
                        }
                        Err(LinkError::HttpError(err)) => {
                            print_issue!(found_issue,
                                         "HTTP failure           ({} -> {}) in {}: {}",
                                         state.last_text,
                                         dest,
                                         entry.path().display(),
                                         err);
                        }
                        Err(LinkError::UrlMalformed(err)) => {
                            print_issue!(found_issue,
                                         "Found malformed URL    ({} -> {}) in {}: {}",
                                         state.last_text,
                                         dest,
                                         entry.path().display(),
                                         err);
                        }
                    }
                }
                Event::Start(Tag::Code) => state.code_block = true,
                Event::End(Tag::Code) => state.code_block = false,
                _ => {}
            }
        }
    }

    if found_issue {
        exit(1)
    }
}

fn try_reference<'a>(state: &State, text: &'a str) -> Option<&'a str> {
    if !state.code_block && text.chars().next() == Some('[') && text.chars().last() == Some(']') {
        Some(text)
    } else {
        None
    }
}

fn check_link(state: &mut State,
              links: &mut HashMap<Url, StatusCode>,
              dest: &str)
              -> Result<(), LinkError> {
    match (Url::parse(&dest), state.skip_http) {
        (Ok(url), false) => check_url(links, url),
        (Ok(_), true) => Ok(()),
        (Err(ParseError::RelativeUrlWithoutBase), _) => check_path(state, dest),
        (Err(err), _) => Err(LinkError::UrlMalformed(err)),
    }
}

fn check_url(links: &mut HashMap<Url, StatusCode>, url: Url) -> Result<(), LinkError> {
    if url.scheme() != "http" && url.scheme() != "https" {
        return Ok(());
    }

    let client = Client::new();
    let status = if let Some(status) = links.remove(&url) {
        status
    } else {
        let res = client.head(url.clone()).send().and_then(|resp| {
            if resp.status == StatusCode::MethodNotAllowed {
                client.get(url.clone()).send()
            } else {
                Ok(resp)
            }
        });
        match res {
            Ok(resp) => resp.status,
            Err(err) => return Err(LinkError::HttpError(err)),
        }
    };
    links.insert(url, status);
    match status {
        StatusCode::Ok => Ok(()),
        status => Err(LinkError::HttpStatus(status)),
    }
}

fn check_path(state: &mut State, path: &str) -> Result<(), LinkError> {
    let path = Path::new(OsStr::new(path.split('#').next().expect("string")));
    if path.is_absolute() {
        Err(LinkError::PathAbsolute)
    } else if !state.directory.join(path).exists() {
        Err(LinkError::PathNonExistant)
    } else {
        Ok(())
    }
}
<commit_msg>main: add user agent to requests<commit_after>// Copyright 2016 Alex Crawford
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate clap;
extern crate hyper;
extern crate pulldown_cmark;
extern crate url;
extern crate walkdir;

use clap::{Arg, App};
use hyper::client::Client;
use hyper::header::UserAgent;
use hyper::status::StatusCode;
use pulldown_cmark::{Event, OPTION_ENABLE_TABLES, Parser, Tag};
use std::collections::HashMap;
use std::ffi::OsStr;
use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;
use std::process::exit;
use url::{ParseError, Url};
use walkdir::WalkDir;

macro_rules! fail {
    ($($print:expr),+) => {
        {
            let _ = writeln!(&mut std::io::stderr(), $($print),+);
            exit(2);
        }
    };
}

macro_rules! print_issue {
    ($flag:expr, $($print:expr),+) => {
        {
            println!($($print),+);
            $flag = true;
        }
    };
}

struct State<'a> {
    skip_http: bool,
    code_block: bool,
    last_text: String,
    directory: &'a Path,
}

enum LinkError {
    PathAbsolute,
    PathNonExistant,
    HttpStatus(StatusCode),
    HttpError(hyper::error::Error),
    UrlMalformed(ParseError),
}

fn main() {
    let matches = App::new("Marker")
        .version(crate_version!())
        .arg(Arg::with_name("root")
            .short("r")
            .long("root")
            .help("The path to the root of the documentation to be checked")
            .takes_value(true))
        .arg(Arg::with_name("skip-http")
            .long("skip-http")
            .help("Skip validation of HTTP[S] URLs"))
        .get_matches();

    let skip_http = matches.is_present("skip-http");
    let root = Path::new(matches.value_of("root").unwrap_or("."));
    let mut links = HashMap::new();
    let mut found_issue = false;

    for entry in WalkDir::new(root).into_iter().filter_map(|entry| {
        let entry = entry.unwrap_or_else(|err| {
            fail!("Failed to walk directory: {}", err);
        });
        if entry.file_type().is_file() && entry.path().extension() == Some(OsStr::new("md")) {
            Some(entry)
        } else {
            None
        }
    }) {
        let contents = {
            let mut file = File::open(entry.path()).unwrap_or_else(|err| {
                fail!("Failed to open file ({}): {}", entry.path().display(), err);
            });
            let mut text = String::new();
            if let Err(err) = file.read_to_string(&mut text) {
                fail!("Failed to read file ({}): {}", entry.path().display(), err);
            };
            text
        };

        let mut state = State {
            skip_http: skip_http,
            code_block: false,
            last_text: String::new(),
            directory: entry.path().parent().expect("non-root path"),
        };
        for event in Parser::new_ext(&contents, OPTION_ENABLE_TABLES) {
            match event {
                Event::Text(ref text) => {
                    state.last_text = text.to_string();
                    if let Some(reference) = try_reference(&state, text) {
                        print_issue!(found_issue,
                                     "Found broken reference ({}) in {}",
                                     reference,
                                     entry.path().display())
                    }
                }
                Event::End(Tag::Link(dest, _)) => {
                    match check_link(&mut state, &mut links, &dest) {
                        Ok(()) => {}
                        Err(LinkError::PathAbsolute) => {
                            print_issue!(found_issue,
                                         "Found absolute path    ({} -> {}) in {}",
                                         state.last_text,
                                         dest,
                                         entry.path().display())
                        }
                        Err(LinkError::PathNonExistant) => {
                            print_issue!(found_issue,
                                         "Found broken path      ({} -> {}) in {}",
                                         state.last_text,
                                         dest,
                                         entry.path().display())
                        }
                        Err(LinkError::HttpStatus(status)) => {
                            print_issue!(found_issue,
                                         "Found broken url       ({} -> {}) in {}: {}",
                                         state.last_text,
                                         dest,
                                         entry.path().display(),
                                         status)
                        }
                        Err(LinkError::HttpError(err)) => {
                            print_issue!(found_issue,
                                         "HTTP failure           ({} -> {}) in {}: {}",
                                         state.last_text,
                                         dest,
                                         entry.path().display(),
                                         err);
                        }
                        Err(LinkError::UrlMalformed(err)) => {
                            print_issue!(found_issue,
                                         "Found malformed URL    ({} -> {}) in {}: {}",
                                         state.last_text,
                                         dest,
                                         entry.path().display(),
                                         err);
                        }
                    }
                }
                Event::Start(Tag::Code) => state.code_block = true,
                Event::End(Tag::Code) => state.code_block = false,
                _ => {}
            }
        }
    }

    if found_issue {
        exit(1)
    }
}

fn try_reference<'a>(state: &State, text: &'a str) -> Option<&'a str> {
    if !state.code_block && text.chars().next() == Some('[') && text.chars().last() == Some(']') {
        Some(text)
    } else {
        None
    }
}

fn check_link(state: &mut State,
              links: &mut HashMap<Url, StatusCode>,
              dest: &str)
              -> Result<(), LinkError> {
    match (Url::parse(&dest), state.skip_http) {
        (Ok(url), false) => check_url(links, url),
        (Ok(_), true) => Ok(()),
        (Err(ParseError::RelativeUrlWithoutBase), _) => check_path(state, dest),
        (Err(err), _) => Err(LinkError::UrlMalformed(err)),
    }
}

fn check_url(links: &mut HashMap<Url, StatusCode>, url: Url) -> Result<(), LinkError> {
    if url.scheme() != "http" && url.scheme() != "https" {
        return Ok(());
    }

    let client = Client::new();
    let agent = UserAgent(format!("marker/{}", crate_version!()));

    let status = if let Some(status) = links.remove(&url) {
        status
    } else {
        let res = client.head(url.clone()).header(agent.clone()).send().and_then(|resp| {
            if resp.status == StatusCode::MethodNotAllowed {
                client.get(url.clone()).header(agent.clone()).send()
            } else {
                Ok(resp)
            }
        });
        match res {
            Ok(resp) => resp.status,
            Err(err) => return Err(LinkError::HttpError(err)),
        }
    };
    links.insert(url, status);
    match status {
        StatusCode::Ok => Ok(()),
        status => Err(LinkError::HttpStatus(status)),
    }
}

fn check_path(state: &mut State, path: &str) -> Result<(), LinkError> {
    let path = Path::new(OsStr::new(path.split('#').next().expect("string")));
    if path.is_absolute() {
        Err(LinkError::PathAbsolute)
    } else if !state.directory.join(path).exists() {
        Err(LinkError::PathNonExistant)
    } else {
        Ok(())
    }
}
<|endoftext|>