<commit_before>extern crate liner;
#[macro_use]
extern crate serde_derive;
extern crate toml;

use liner::Context;
use liner::KeyBindings;
use std::collections::HashMap;
use std::collections::hash_map::Keys;
use std::fs::File;
use std::io::{ErrorKind, Read};
use std::mem;
use std::path::Path;

type Data = HashMap<String, String>;

#[derive(Deserialize)]
struct CacheConfig {
    ttl: usize,
}

#[derive(Deserialize)]
struct Config {
    cache: CacheConfig,
}

struct Cache {
    data: Box<Data>,
    config: Config,
    bytes: usize
}

fn get_size_of_string(s: &String) -> usize {
    return s.len() * std::mem::size_of::<u8>();
}

impl Cache {
    fn clear(&mut self) {
        self.data.clear();
        self.bytes = 0;
    }

    fn get(&mut self, key: &String) -> Option<&String> {
        self.data.get(key)
    }

    fn set(&mut self, key: String, value: String) {
        if let Some(previous_value) = self.data.get(&key) {
            self.bytes -= get_size_of_string(previous_value);
        }
        else {
            self.bytes += get_size_of_string(&key);
        }
        self.bytes += get_size_of_string(&value);

        self.data.insert(key, value);
    }

    fn delete(&mut self, key: &String) {
        if let Some(value) = self.data.remove(key) {
            self.bytes -= get_size_of_string(&value) + get_size_of_string(key);
        }
    }

    fn keys(&self) -> Keys<String, String> {
        self.data.keys()
    }

    fn count(&self) -> usize {
        self.data.len()
    }

    fn size(&self) -> usize {
        self.bytes
    }
}

fn main() {
    // Open and read configuration
    let config_path = Path::new("etc/carpool.toml");
    let mut config_file = match File::open(&config_path) {
        Err(_) => panic!("couldn't open {:?}", config_path),
        Ok(file) => file,
    };

    let mut config_content = String::new();
    let _ = config_file.read_to_string(&mut config_content);

    let config: Config = toml::from_str(config_content.as_str()).unwrap();

    // Set up cache
    let mut cache = Cache {
        config: config,
        data: Box::new(HashMap::new()),
        bytes: 0,
    };

    let empty_value = String::from("");

    // Start REPL
    let mut con = Context::new();

    loop {
        let res = con.read_line("> ", &mut |_| {});

        match res {
            Ok(res) => {
                match res.as_str() {
                    s if s.trim() == "" =>  {}
                    s if s.starts_with("get ") =>  {
                        let (_, key) = s.split_at(4);
                        let key_trimmed = String::from(key.trim());
                        if key_trimmed.find(' ').is_some() {
                            println!("key cannot contain space");
                            continue
                        }
                        println!("{}", cache.get(&key_trimmed).unwrap_or(&empty_value));
                    }
                    s if s.starts_with("del ") =>  {
                        let (_, key) = s.split_at(4);
                        let key_trimmed = String::from(key.trim());
                        if key_trimmed.find(' ').is_some() {
                            println!("key cannot contain space");
                            continue
                        }
                        let value = cache.delete(&key_trimmed);
                    }
                    s if s.starts_with("set ") =>  {
                        let (_, key_value) = s.split_at(4);
                        match key_value.find(' ') {
                            Some(i) => {
                                let (key, value) = key_value.split_at(i);
                                let key_trimmed = String::from(key.trim());
                                let value_trimmed = String::from(value.trim());
                                cache.set(key_trimmed, value_trimmed);
                            }
                            None => println!("no value specified")
                        }
                    }
                    "count" =>  {
                        println!("{}", cache.count());
                    }
                    "size" =>  {
                        println!("{} bytes", cache.size());
                    }
                    "keys" =>  {
                        for key in cache.keys() {
                            println!("{}", key);
                        }
                    }
                    "emacs" => {
                        con.key_bindings = KeyBindings::Emacs;
                        println!("emacs mode");
                    }
                    "vi" | "vim" =>  {
                        con.key_bindings = KeyBindings::Vi;
                        println!("vi mode");
                    }
                    "exit" =>  {
                        break;
                    }
                    _ => {
                        println!("operation not defined")
                    }
                }

                con.history.push(res.into()).unwrap();
            }
            Err(e) => {
                match e.kind() {
                    // ctrl-c pressed
                    ErrorKind::Interrupted => {}
                    // ctrl-d pressed
                    ErrorKind::UnexpectedEof => {
                        break;
                    }
                    _ => panic!("error: {:?}", e),
                }
            }
        }
    }
}
<commit_msg>Add get_size_of_string tests<commit_after>extern crate liner;
#[macro_use]
extern crate serde_derive;
extern crate toml;

use liner::Context;
use liner::KeyBindings;
use std::collections::HashMap;
use std::collections::hash_map::Keys;
use std::fs::File;
use std::io::{ErrorKind, Read};
use std::mem;
use std::path::Path;

type Data = HashMap<String, String>;

#[derive(Deserialize)]
struct CacheConfig {
    ttl: usize,
}

#[derive(Deserialize)]
struct Config {
    cache: CacheConfig,
}

struct Cache {
    data: Box<Data>,
    config: Config,
    bytes: usize
}

fn get_size_of_string(s: &String) -> usize {
    return s.len() * std::mem::size_of::<u8>();
}

impl Cache {
    fn clear(&mut self) {
        self.data.clear();
        self.bytes = 0;
    }

    fn get(&mut self, key: &String) -> Option<&String> {
        self.data.get(key)
    }

    fn set(&mut self, key: String, value: String) {
        if let Some(previous_value) = self.data.get(&key) {
            self.bytes -= get_size_of_string(previous_value);
        }
        else {
            self.bytes += get_size_of_string(&key);
        }
        self.bytes += get_size_of_string(&value);

        self.data.insert(key, value);
    }

    fn delete(&mut self, key: &String) {
        if let Some(value) = self.data.remove(key) {
            self.bytes -= get_size_of_string(&value) + get_size_of_string(key);
        }
    }

    fn keys(&self) -> Keys<String, String> {
        self.data.keys()
    }

    fn count(&self) -> usize {
        self.data.len()
    }

    fn size(&self) -> usize {
        self.bytes
    }
}

#[cfg(not(test))]
fn main() {
    // Open and read configuration
    let config_path = Path::new("etc/carpool.toml");
    let mut config_file = match File::open(&config_path) {
        Err(_) => panic!("couldn't open {:?}", config_path),
        Ok(file) => file,
    };

    let mut config_content = String::new();
    let _ = config_file.read_to_string(&mut config_content);

    let config: Config = toml::from_str(config_content.as_str()).unwrap();

    // Set up cache
    let mut cache = Cache {
        config: config,
        data: Box::new(HashMap::new()),
        bytes: 0,
    };

    let empty_value = String::from("");

    // Start REPL
    let mut con = Context::new();

    loop {
        let res = con.read_line("> ", &mut |_| {});

        match res {
            Ok(res) => {
                match res.as_str() {
                    s if s.trim() == "" =>  {}
                    s if s.starts_with("get ") =>  {
                        let (_, key) = s.split_at(4);
                        let key_trimmed = String::from(key.trim());
                        if key_trimmed.find(' ').is_some() {
                            println!("key cannot contain space");
                            continue
                        }
                        println!("{}", cache.get(&key_trimmed).unwrap_or(&empty_value));
                    }
                    s if s.starts_with("del ") =>  {
                        let (_, key) = s.split_at(4);
                        let key_trimmed = String::from(key.trim());
                        if key_trimmed.find(' ').is_some() {
                            println!("key cannot contain space");
                            continue
                        }
                        let value = cache.delete(&key_trimmed);
                    }
                    s if s.starts_with("set ") =>  {
                        let (_, key_value) = s.split_at(4);
                        match key_value.find(' ') {
                            Some(i) => {
                                let (key, value) = key_value.split_at(i);
                                let key_trimmed = String::from(key.trim());
                                let value_trimmed = String::from(value.trim());
                                cache.set(key_trimmed, value_trimmed);
                            }
                            None => println!("no value specified")
                        }
                    }
                    "count" =>  {
                        println!("{}", cache.count());
                    }
                    "size" =>  {
                        println!("{} bytes", cache.size());
                    }
                    "keys" =>  {
                        for key in cache.keys() {
                            println!("{}", key);
                        }
                    }
                    "emacs" => {
                        con.key_bindings = KeyBindings::Emacs;
                        println!("emacs mode");
                    }
                    "vi" | "vim" =>  {
                        con.key_bindings = KeyBindings::Vi;
                        println!("vi mode");
                    }
                    "exit" =>  {
                        break;
                    }
                    _ => {
                        println!("operation not defined")
                    }
                }

                con.history.push(res.into()).unwrap();
            }
            Err(e) => {
                match e.kind() {
                    // ctrl-c pressed
                    ErrorKind::Interrupted => {}
                    // ctrl-d pressed
                    ErrorKind::UnexpectedEof => {
                        break;
                    }
                    _ => panic!("error: {:?}", e),
                }
            }
        }
    }
}

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

    #[test]
    fn get_size_of_simple_string() {
        assert_eq!(get_size_of_string(&String::from("hello")), 5usize);
    }

    #[test]
    fn get_size_of_emoji_string() {
        assert_eq!(get_size_of_string(&String::from("❤")), 6usize);
    }
}
<|endoftext|>


<commit_before>extern crate base64;

extern crate hyper;
extern crate hyper_native_tls;

extern crate pem;

#[macro_use]
extern crate prettytable;

extern crate ct_submitter;

use std::{env, process};
use std::fs::File;
use std::io::Read;
use std::time::Duration;

use ct_submitter::{fetch_trusted_ct_logs, submit_cert_to_logs};

fn main() {
    let path = match env::args().skip(1).next() {
        Some(p) => p,
        None => {
            println!("Usage: {} <path/to/chain.pem>", env::args().next().unwrap());
            process::exit(1);
        }
    };

    let mut contents = String::new();
    File::open(path)
        .unwrap()
        .read_to_string(&mut contents)
        .unwrap();

    let chain = pem::parse_many(contents)
        .into_iter()
        .filter(|p| p.tag == "CERTIFICATE")
        .map(|p| p.contents)
        .collect();

    let mut http_client = hyper::Client::with_connector(
        hyper::net::HttpsConnector::new(hyper_native_tls::NativeTlsClient::new().unwrap())
    );
    http_client.set_read_timeout(Some(Duration::from_secs(5)));
    let logs = fetch_trusted_ct_logs(&http_client);

    let scts = submit_cert_to_logs(&http_client, &logs, chain);

    let mut table = prettytable::Table::new();
    table.add_row(row!["Log", "SCT"]);
    for (log, sct) in scts {
        table.add_row(row![log.description, base64::encode(&sct.to_raw_bytes())]);
    }
    table.printstd();
}
<commit_msg>normalize extern crates<commit_after>extern crate base64;
extern crate hyper;
extern crate hyper_native_tls;
extern crate pem;
#[macro_use]
extern crate prettytable;

extern crate ct_submitter;

use std::{env, process};
use std::fs::File;
use std::io::Read;
use std::time::Duration;

use ct_submitter::{fetch_trusted_ct_logs, submit_cert_to_logs};

fn main() {
    let path = match env::args().skip(1).next() {
        Some(p) => p,
        None => {
            println!("Usage: {} <path/to/chain.pem>", env::args().next().unwrap());
            process::exit(1);
        }
    };

    let mut contents = String::new();
    File::open(path)
        .unwrap()
        .read_to_string(&mut contents)
        .unwrap();

    let chain = pem::parse_many(contents)
        .into_iter()
        .filter(|p| p.tag == "CERTIFICATE")
        .map(|p| p.contents)
        .collect();

    let mut http_client = hyper::Client::with_connector(
        hyper::net::HttpsConnector::new(hyper_native_tls::NativeTlsClient::new().unwrap())
    );
    http_client.set_read_timeout(Some(Duration::from_secs(5)));
    let logs = fetch_trusted_ct_logs(&http_client);

    let scts = submit_cert_to_logs(&http_client, &logs, chain);

    let mut table = prettytable::Table::new();
    table.add_row(row!["Log", "SCT"]);
    for (log, sct) in scts {
        table.add_row(row![log.description, base64::encode(&sct.to_raw_bytes())]);
    }
    table.printstd();
}
<|endoftext|>


<commit_before>extern crate deque;
extern crate docopt;
extern crate env_logger;
extern crate fnv;
extern crate grep;
#[cfg(windows)]
extern crate kernel32;
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
extern crate memchr;
extern crate memmap;
extern crate num_cpus;
extern crate regex;
extern crate rustc_serialize;
extern crate term;
extern crate walkdir;
#[cfg(windows)]
extern crate winapi;

use std::error::Error;
use std::fs::File;
use std::io;
use std::path::{Path, PathBuf};
use std::process;
use std::result;
use std::sync::{Arc, Mutex};
use std::thread;

use deque::{Stealer, Stolen};
use grep::Grep;
use memmap::{Mmap, Protection};
use term::Terminal;
use walkdir::DirEntry;

use args::Args;
use out::{ColoredTerminal, Out};
use pathutil::strip_prefix;
use printer::Printer;
use search_stream::InputBuffer;
#[cfg(windows)]
use terminal_win::WindowsBuffer;

macro_rules! errored {
    ($($tt:tt)*) => {
        return Err(From::from(format!($($tt)*)));
    }
}

macro_rules! eprintln {
    ($($tt:tt)*) => {{
        use std::io::Write;
        let _ = writeln!(&mut ::std::io::stderr(), $($tt)*);
    }}
}

mod args;
mod atty;
mod gitignore;
mod glob;
mod ignore;
mod out;
mod pathutil;
mod printer;
mod search_buffer;
mod search_stream;
#[cfg(windows)]
mod terminal_win;
mod types;
mod walk;

pub type Result<T> = result::Result<T, Box<Error + Send + Sync>>;

fn main() {
    match Args::parse().and_then(run) {
        Ok(count) if count == 0 => process::exit(1),
        Ok(_) => process::exit(0),
        Err(err) => {
            eprintln!("{}", err);
            process::exit(1);
        }
    }
}

fn run(args: Args) -> Result<u64> {
    let args = Arc::new(args);
    let paths = args.paths();
    if args.files() {
        return run_files(args.clone());
    }
    if args.type_list() {
        return run_types(args.clone());
    }
    if paths.len() == 1 && (paths[0] == Path::new("-") || paths[0].is_file()) {
        return run_one(args.clone(), &paths[0]);
    }

    let out = Arc::new(Mutex::new(args.out()));
    let mut workers = vec![];

    let workq = {
        let (workq, stealer) = deque::new();
        for _ in 0..args.threads() {
            let worker = MultiWorker {
                chan_work: stealer.clone(),
                out: out.clone(),
                outbuf: Some(args.outbuf()),
                worker: Worker {
                    args: args.clone(),
                    inpbuf: args.input_buffer(),
                    grep: args.grep(),
                    match_count: 0,
                },
            };
            workers.push(thread::spawn(move || worker.run()));
        }
        workq
    };
    for p in paths {
        if p == Path::new("-") {
            workq.push(Work::Stdin)
        } else {
            for ent in try!(args.walker(p)) {
                workq.push(Work::File(ent));
            }
        }
    }
    for _ in 0..workers.len() {
        workq.push(Work::Quit);
    }
    let mut match_count = 0;
    for worker in workers {
        match_count += worker.join().unwrap();
    }
    Ok(match_count)
}

fn run_one(args: Arc<Args>, path: &Path) -> Result<u64> {
    let mut worker = Worker {
        args: args.clone(),
        inpbuf: args.input_buffer(),
        grep: args.grep(),
        match_count: 0,
    };
    let term = args.stdout();
    let mut printer = args.printer(term);
    let work =
        if path == Path::new("-") {
            WorkReady::Stdin
        } else {
            WorkReady::PathFile(path.to_path_buf(), try!(File::open(path)))
        };
    worker.do_work(&mut printer, work);
    Ok(worker.match_count)
}

fn run_files(args: Arc<Args>) -> Result<u64> {
    let term = args.stdout();
    let mut printer = args.printer(term);
    let mut file_count = 0;
    for p in args.paths() {
        if p == Path::new("-") {
            printer.path(&Path::new("<stdin>"));
            file_count += 1;
        } else {
            for ent in try!(args.walker(p)) {
                printer.path(ent.path());
                file_count += 1;
            }
        }
    }
    Ok(file_count)
}

fn run_types(args: Arc<Args>) -> Result<u64> {
    let term = args.stdout();
    let mut printer = args.printer(term);
    let mut ty_count = 0;
    for def in args.type_defs() {
        printer.type_def(def);
        ty_count += 1;
    }
    Ok(ty_count)
}

enum Work {
    Stdin,
    File(DirEntry),
    Quit,
}

enum WorkReady {
    Stdin,
    DirFile(DirEntry, File),
    PathFile(PathBuf, File),
}

struct MultiWorker {
    chan_work: Stealer<Work>,
    out: Arc<Mutex<Out>>,
    #[cfg(not(windows))]
    outbuf: Option<ColoredTerminal<term::TerminfoTerminal<Vec<u8>>>>,
    #[cfg(windows)]
    outbuf: Option<ColoredTerminal<WindowsBuffer>>,
    worker: Worker,
}

struct Worker {
    args: Arc<Args>,
    inpbuf: InputBuffer,
    grep: Grep,
    match_count: u64,
}

impl MultiWorker {
    fn run(mut self) -> u64 {
        loop {
            let work = match self.chan_work.steal() {
                Stolen::Empty | Stolen::Abort => continue,
                Stolen::Data(Work::Quit) => break,
                Stolen::Data(Work::Stdin) => WorkReady::Stdin,
                Stolen::Data(Work::File(ent)) => {
                    match File::open(ent.path()) {
                        Ok(file) => WorkReady::DirFile(ent, file),
                        Err(err) => {
                            eprintln!("{}: {}", ent.path().display(), err);
                            continue;
                        }
                    }
                }
            };
            let mut outbuf = self.outbuf.take().unwrap();
            outbuf.clear();
            let mut printer = self.worker.args.printer(outbuf);
            self.worker.do_work(&mut printer, work);
            let outbuf = printer.into_inner();
            if !outbuf.get_ref().is_empty() {
                let mut out = self.out.lock().unwrap();
                out.write(&outbuf);
            }
            self.outbuf = Some(outbuf);
        }
        self.worker.match_count
    }
}

impl Worker {
    fn do_work<W: Terminal + Send>(
        &mut self,
        printer: &mut Printer<W>,
        work: WorkReady,
    ) {
        let result = match work {
            WorkReady::Stdin => {
                let stdin = io::stdin();
                let stdin = stdin.lock();
                self.search(printer, &Path::new("<stdin>"), stdin)
            }
            WorkReady::DirFile(ent, file) => {
                let mut path = ent.path();
                if let Some(p) = strip_prefix("./", path) {
                    path = p;
                }
                if self.args.mmap() {
                    self.search_mmap(printer, path, &file)
                } else {
                    self.search(printer, path, file)
                }
            }
            WorkReady::PathFile(path, file) => {
                let mut path = &*path;
                if let Some(p) = strip_prefix("./", path) {
                    path = p;
                }
                if self.args.mmap() {
                    self.search_mmap(printer, path, &file)
                } else {
                    self.search(printer, path, file)
                }
            }
        };
        match result {
            Ok(count) => {
                self.match_count += count;
            }
            Err(err) => {
                eprintln!("{}", err);
            }
        }
    }

    fn search<R: io::Read, W: Terminal + Send>(
        &mut self,
        printer: &mut Printer<W>,
        path: &Path,
        rdr: R,
    ) -> Result<u64> {
        self.args.searcher(
            &mut self.inpbuf,
            printer,
            &self.grep,
            path,
            rdr,
        ).run().map_err(From::from)
    }

    fn search_mmap<W: Terminal + Send>(
        &mut self,
        printer: &mut Printer<W>,
        path: &Path,
        file: &File,
    ) -> Result<u64> {
        if try!(file.metadata()).len() == 0 {
            // Opening a memory map with an empty file results in an error.
            return Ok(0);
        }
        let mmap = try!(Mmap::open(file, Protection::Read));
        Ok(self.args.searcher_buffer(
            printer,
            &self.grep,
            path,
            unsafe { mmap.as_slice() },
        ).run())
    }
}
<commit_msg>Add an error message for catching a common failure mode.<commit_after>extern crate deque;
extern crate docopt;
extern crate env_logger;
extern crate fnv;
extern crate grep;
#[cfg(windows)]
extern crate kernel32;
#[macro_use]
extern crate lazy_static;
extern crate libc;
#[macro_use]
extern crate log;
extern crate memchr;
extern crate memmap;
extern crate num_cpus;
extern crate regex;
extern crate rustc_serialize;
extern crate term;
extern crate walkdir;
#[cfg(windows)]
extern crate winapi;

use std::error::Error;
use std::fs::File;
use std::io;
use std::path::{Path, PathBuf};
use std::process;
use std::result;
use std::sync::{Arc, Mutex};
use std::thread;

use deque::{Stealer, Stolen};
use grep::Grep;
use memmap::{Mmap, Protection};
use term::Terminal;
use walkdir::DirEntry;

use args::Args;
use out::{ColoredTerminal, Out};
use pathutil::strip_prefix;
use printer::Printer;
use search_stream::InputBuffer;
#[cfg(windows)]
use terminal_win::WindowsBuffer;

macro_rules! errored {
    ($($tt:tt)*) => {
        return Err(From::from(format!($($tt)*)));
    }
}

macro_rules! eprintln {
    ($($tt:tt)*) => {{
        use std::io::Write;
        let _ = writeln!(&mut ::std::io::stderr(), $($tt)*);
    }}
}

mod args;
mod atty;
mod gitignore;
mod glob;
mod ignore;
mod out;
mod pathutil;
mod printer;
mod search_buffer;
mod search_stream;
#[cfg(windows)]
mod terminal_win;
mod types;
mod walk;

pub type Result<T> = result::Result<T, Box<Error + Send + Sync>>;

fn main() {
    match Args::parse().and_then(run) {
        Ok(count) if count == 0 => process::exit(1),
        Ok(_) => process::exit(0),
        Err(err) => {
            eprintln!("{}", err);
            process::exit(1);
        }
    }
}

fn run(args: Args) -> Result<u64> {
    let args = Arc::new(args);
    let paths = args.paths();
    if args.files() {
        return run_files(args.clone());
    }
    if args.type_list() {
        return run_types(args.clone());
    }
    if paths.len() == 1 && (paths[0] == Path::new("-") || paths[0].is_file()) {
        return run_one(args.clone(), &paths[0]);
    }

    let out = Arc::new(Mutex::new(args.out()));
    let mut workers = vec![];

    let workq = {
        let (workq, stealer) = deque::new();
        for _ in 0..args.threads() {
            let worker = MultiWorker {
                chan_work: stealer.clone(),
                out: out.clone(),
                outbuf: Some(args.outbuf()),
                worker: Worker {
                    args: args.clone(),
                    inpbuf: args.input_buffer(),
                    grep: args.grep(),
                    match_count: 0,
                },
            };
            workers.push(thread::spawn(move || worker.run()));
        }
        workq
    };
    let mut paths_searched: u64 = 0;
    for p in paths {
        if p == Path::new("-") {
            paths_searched += 1;
            workq.push(Work::Stdin);
        } else {
            for ent in try!(args.walker(p)) {
                paths_searched += 1;
                workq.push(Work::File(ent));
            }
        }
    }
    if !paths.is_empty() && paths_searched == 0 {
        eprintln!("No files were searched, which means ripgrep probably \
                   applied a filter you didn't expect. \
                   Try running again with --debug.");
    }
    for _ in 0..workers.len() {
        workq.push(Work::Quit);
    }
    let mut match_count = 0;
    for worker in workers {
        match_count += worker.join().unwrap();
    }
    Ok(match_count)
}

fn run_one(args: Arc<Args>, path: &Path) -> Result<u64> {
    let mut worker = Worker {
        args: args.clone(),
        inpbuf: args.input_buffer(),
        grep: args.grep(),
        match_count: 0,
    };
    let term = args.stdout();
    let mut printer = args.printer(term);
    let work =
        if path == Path::new("-") {
            WorkReady::Stdin
        } else {
            WorkReady::PathFile(path.to_path_buf(), try!(File::open(path)))
        };
    worker.do_work(&mut printer, work);
    Ok(worker.match_count)
}

fn run_files(args: Arc<Args>) -> Result<u64> {
    let term = args.stdout();
    let mut printer = args.printer(term);
    let mut file_count = 0;
    for p in args.paths() {
        if p == Path::new("-") {
            printer.path(&Path::new("<stdin>"));
            file_count += 1;
        } else {
            for ent in try!(args.walker(p)) {
                printer.path(ent.path());
                file_count += 1;
            }
        }
    }
    Ok(file_count)
}

fn run_types(args: Arc<Args>) -> Result<u64> {
    let term = args.stdout();
    let mut printer = args.printer(term);
    let mut ty_count = 0;
    for def in args.type_defs() {
        printer.type_def(def);
        ty_count += 1;
    }
    Ok(ty_count)
}

enum Work {
    Stdin,
    File(DirEntry),
    Quit,
}

enum WorkReady {
    Stdin,
    DirFile(DirEntry, File),
    PathFile(PathBuf, File),
}

struct MultiWorker {
    chan_work: Stealer<Work>,
    out: Arc<Mutex<Out>>,
    #[cfg(not(windows))]
    outbuf: Option<ColoredTerminal<term::TerminfoTerminal<Vec<u8>>>>,
    #[cfg(windows)]
    outbuf: Option<ColoredTerminal<WindowsBuffer>>,
    worker: Worker,
}

struct Worker {
    args: Arc<Args>,
    inpbuf: InputBuffer,
    grep: Grep,
    match_count: u64,
}

impl MultiWorker {
    fn run(mut self) -> u64 {
        loop {
            let work = match self.chan_work.steal() {
                Stolen::Empty | Stolen::Abort => continue,
                Stolen::Data(Work::Quit) => break,
                Stolen::Data(Work::Stdin) => WorkReady::Stdin,
                Stolen::Data(Work::File(ent)) => {
                    match File::open(ent.path()) {
                        Ok(file) => WorkReady::DirFile(ent, file),
                        Err(err) => {
                            eprintln!("{}: {}", ent.path().display(), err);
                            continue;
                        }
                    }
                }
            };
            let mut outbuf = self.outbuf.take().unwrap();
            outbuf.clear();
            let mut printer = self.worker.args.printer(outbuf);
            self.worker.do_work(&mut printer, work);
            let outbuf = printer.into_inner();
            if !outbuf.get_ref().is_empty() {
                let mut out = self.out.lock().unwrap();
                out.write(&outbuf);
            }
            self.outbuf = Some(outbuf);
        }
        self.worker.match_count
    }
}

impl Worker {
    fn do_work<W: Terminal + Send>(
        &mut self,
        printer: &mut Printer<W>,
        work: WorkReady,
    ) {
        let result = match work {
            WorkReady::Stdin => {
                let stdin = io::stdin();
                let stdin = stdin.lock();
                self.search(printer, &Path::new("<stdin>"), stdin)
            }
            WorkReady::DirFile(ent, file) => {
                let mut path = ent.path();
                if let Some(p) = strip_prefix("./", path) {
                    path = p;
                }
                if self.args.mmap() {
                    self.search_mmap(printer, path, &file)
                } else {
                    self.search(printer, path, file)
                }
            }
            WorkReady::PathFile(path, file) => {
                let mut path = &*path;
                if let Some(p) = strip_prefix("./", path) {
                    path = p;
                }
                if self.args.mmap() {
                    self.search_mmap(printer, path, &file)
                } else {
                    self.search(printer, path, file)
                }
            }
        };
        match result {
            Ok(count) => {
                self.match_count += count;
            }
            Err(err) => {
                eprintln!("{}", err);
            }
        }
    }

    fn search<R: io::Read, W: Terminal + Send>(
        &mut self,
        printer: &mut Printer<W>,
        path: &Path,
        rdr: R,
    ) -> Result<u64> {
        self.args.searcher(
            &mut self.inpbuf,
            printer,
            &self.grep,
            path,
            rdr,
        ).run().map_err(From::from)
    }

    fn search_mmap<W: Terminal + Send>(
        &mut self,
        printer: &mut Printer<W>,
        path: &Path,
        file: &File,
    ) -> Result<u64> {
        if try!(file.metadata()).len() == 0 {
            // Opening a memory map with an empty file results in an error.
            return Ok(0);
        }
        let mmap = try!(Mmap::open(file, Protection::Read));
        Ok(self.args.searcher_buffer(
            printer,
            &self.grep,
            path,
            unsafe { mmap.as_slice() },
        ).run())
    }
}
<|endoftext|>


<commit_before>//#![feature(convert)]

#[macro_use] extern crate nickel;
extern crate rustc_serialize;
extern crate hyper;
extern crate nickel_postgres;
extern crate postgres;
extern crate r2d2_postgres;
extern crate r2d2;

use nickel::{Nickel, HttpRouter, QueryString};
use nickel::extensions::Redirect;
use nickel::status::StatusCode;
use rustc_serialize::json;
use hyper::Client;
use hyper::header::Connection;
use hyper::status::StatusClass;
use hyper::client::response::Response;
use std::io::Read;
use std::env;
use r2d2::{NopErrorHandler, PooledConnection};
use r2d2_postgres::{SslMode, PostgresConnectionManager};
use nickel_postgres::{PostgresMiddleware, PostgresRequestExtensions};

#[derive(RustcDecodable, Debug)]
struct Data {
    data: User,
}

#[derive(RustcDecodable, Debug)]
struct User {
    id: i32,
    email: String,
    created_at: String,
    updated_at: String,
    first_name: String,
    last_name: String,
    graduation: String,
    major: String,
    shirt_size: String,
    dietary_restrictions: String,
    special_needs: Option<String>,
    date_of_birth: String,
    gender: String,
    phone_number: String,
    school: School,
}

#[derive(RustcDecodable, Debug)]
struct School {
    id: i32,
    name: String,
}

#[derive(RustcDecodable, Debug)]
struct TokenResp {
    access_token: String,
    token_type: String,
    scope: String,
    created_at: u64,
}

#[derive(RustcEncodable, Debug)]
struct Payload {
    channel: String,
    username: String,
    text: String,
    icon_emoji: String,
}

#[derive(Debug)]
enum ApiError {
    ClientError,
    ServerError,
}

#[derive(Debug)]
enum RequestError {
    Hyper(hyper::error::Error),
    Io(std::io::Error),
    JsonEnc(rustc_serialize::json::EncoderError),
    JsonDec(rustc_serialize::json::DecoderError),
    Api(ApiError),
}

// `env_err!(var, message)` gets `var` from the environment, and panics with
// `message` if that fails
// `env_err!(var)` gets `var` from the environment and panics with `"Failed to
// get env var $var"` if that fails
macro_rules! env_err {
    ( $var:expr, $error:expr ) => {
        env::var($var).expect($error)
    };
    ( $var:expr ) => {
        env_err!($var, &format!("Failed to get env var {}", $var))
    }
}

// Error handling code.  Expands to impl-ing From for enum_t from from_t to to_t
// See https://doc.rust-lang.org/book/error-handling.html for a full description
macro_rules! impl_from {
    ( $from_t:path, $to_t:path, $enum_t:path ) => {
        impl From<$from_t> for $enum_t {
            fn from(err: $from_t) -> $enum_t {
                $to_t(err)
            }
        }
    }
}

// All the impls for RequestError
impl_from!(hyper::error::Error, RequestError::Hyper, RequestError);
impl_from!(std::io::Error, RequestError::Io, RequestError);
impl_from!(rustc_serialize::json::DecoderError, RequestError::JsonDec,
           RequestError);
impl_from!(rustc_serialize::json::EncoderError, RequestError::JsonEnc,
           RequestError);
impl_from!(ApiError, RequestError::Api, RequestError);

// Checks for 4xx or 5xx errors and returns the appropriate ApiError
fn check_http_error(res: &Response) -> Result<(), ApiError> {
    match res.status.class() {
        StatusClass::ClientError => Err(ApiError::ClientError),
        StatusClass::ServerError => Err(ApiError::ServerError),
        _ => Ok(())
    }
}

// Do the OAUTH stuff for my.mlh.io
// TODO: Something better about the long api urls
fn do_request(code: &str) -> Result<Data, RequestError> {
    let id = env_err!("ID");
    let secret = env_err!("SECRET");
    let redirect = env_err!("REDIRECT");

    let url = format!("https://my.mlh.io/oauth/token?client_id={}&client_secret={}&code={}&redirect_uri={}&grant_type=authorization_code",
                      id, secret, code, redirect);

    let client = Client::new();
    let mut res = try!(client.post(&url)
        .header(Connection::close())
        .send());

    try!(check_http_error(&res));

    let mut body = String::new();
    try!(res.read_to_string(&mut body));

    let token: TokenResp = try!(json::decode(&body));
    let url2 = format!("https://my.mlh.io/api/v1/user?access_token={}",
                       token.access_token);

    res = try!(client.get(&url2)
        .header(Connection::close())
        .send());

    try!(check_http_error(&res));

    body = String::new();
    try!(res.read_to_string(&mut body));

    let person_data: Data = try!(json::decode(&body));

    Ok(person_data)
}

// Send a message to slack when a new user signs up
fn slack_send(user: User) -> Result<(), RequestError> {
    let url = env_err!("SLACKURL");
    let client = Client::new();
    let payload = Payload {
        channel: "#hackcwru".to_string(),
        username: "Signup bot".to_string(),
        icon_emoji: ":hackcwru:".to_string(),
        text: format!("{}, a {} major from {}, has signed up!",
                      user.first_name,
                      user.major,
                      user.school.name),
    };
    let payload_str = try!(json::encode(&payload));
    let res = try!(client.post(&url)
        .body(&payload_str)
        .send());

    try!(check_http_error(&res));

    Ok(())
}

// Create the table if it doesn't exist.  Runs on each startup
fn create_table(conn: PooledConnection<PostgresConnectionManager>) {
    let _r = conn.execute(
            "CREATE TABLE IF NOT EXISTS person (
                id SERIAL PRIMARY KEY,
                email VARCHAR NOT NULL,
                created_at VARCHAR NOT NULL,
                updated_at VARCHAR NOT NULL,
                first_name VARCHAR NOT NULL,
                last_name VARCHAR NOT NULL,
                graduation VARCHAR NOT NULL,
                major VARCHAR NOT NULL,
                shirt_size VARCHAR NOT NULL,
                dietary_restrictions VARCHAR NOT NULL,
                special_needs VARCHAR,
                date_of_birth VARCHAR NOT NULL,
                gender VARCHAR NOT NULL,
                phone_number VARCHAR NOT NULL,
                school_id integer,
                school_name VARCHAR
                )",
            &[]
        );
}

fn main() {
    let mut app = Nickel::new();

    let postgres_url = env_err!("DATABASE");
    let dbpool = PostgresMiddleware::new(&*postgres_url, SslMode::None, 5,
                                         Box::new(NopErrorHandler))
        .expect("Failed to start PostgresMiddleware");

    create_table(dbpool.pool.clone().get().unwrap());
    app.utilize(dbpool);

    app.get("/callback", middleware! { |request, mut response|
        let conn = request.db_conn();
        let code = match request.query().get("code") {
            Some(s) => s,
            None => {
                println!("No code, quitting");
                return response.error(StatusCode::BadRequest, "Failed");
            }
        };
        let user_data = match do_request(code) {
            Ok(s) => s,
            Err(e) => {
                println!("Get user data failed with error: {:?}", e);
                return response
                    .error(StatusCode::InternalServerError, "Failed");
            }
        }.data;

        // TODO: make this a function
        let r = conn.execute(
                "INSERT INTO person (id, email, created_at, updated_at,
                first_name, last_name, graduation, major, shirt_size,
                dietary_restrictions, special_needs, date_of_birth, gender,
                phone_number, school_id, school_name) VALUES ($1, $2, $3, $4,
                $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)",
                &[&user_data.id, &user_data.email, &user_data.created_at,
                  &user_data.updated_at, &user_data.first_name,
                  &user_data.last_name, &user_data.graduation, &user_data.major,
                  &user_data.shirt_size, &user_data.dietary_restrictions,
                  &user_data.special_needs, &user_data.date_of_birth,
                  &user_data.gender, &user_data.phone_number,
                  &user_data.school.id, &user_data.school.name]
            );
        match r {
            Ok(v) => {
                println!("Add to database succeeded with status {:?}", v);
                match slack_send(user_data) {
                    Ok(_) => println!("Slack send worked"),
                    Err(e) => println!("Slack send failed with error: {:?}", e)
                };
            },
            Err(e) => println!("Add to database failed: {:?}", e)
        }

        return response.redirect("http://hack.cwru.edu/register.html")
    });

    app.get("/start", middleware! { |_req, response|
        let id = env_err!("ID");
        let redirect = env_err!("REDIRECT");
        return response.redirect(
            format!(
                    "http://my.mlh.io/oauth/authorize?client_id={}&redirect_uri={}&response_type=code",
                    id, redirect
                )
            );
    });

    let bind = match env::var("BIND") {
        Ok(v) => v,
        Err(_) => "127.0.0.1:8080".to_string(),
    };

    app.listen(&bind[..]);
}
<commit_msg>Add FINALREDIRECT value for where to go when done<commit_after>//#![feature(convert)]

#[macro_use] extern crate nickel;
extern crate rustc_serialize;
extern crate hyper;
extern crate nickel_postgres;
extern crate postgres;
extern crate r2d2_postgres;
extern crate r2d2;

use nickel::{Nickel, HttpRouter, QueryString};
use nickel::extensions::Redirect;
use nickel::status::StatusCode;
use rustc_serialize::json;
use hyper::Client;
use hyper::header::Connection;
use hyper::status::StatusClass;
use hyper::client::response::Response;
use std::io::Read;
use std::env;
use r2d2::{NopErrorHandler, PooledConnection};
use r2d2_postgres::{SslMode, PostgresConnectionManager};
use nickel_postgres::{PostgresMiddleware, PostgresRequestExtensions};

#[derive(RustcDecodable, Debug)]
struct Data {
    data: User,
}

#[derive(RustcDecodable, Debug)]
struct User {
    id: i32,
    email: String,
    created_at: String,
    updated_at: String,
    first_name: String,
    last_name: String,
    graduation: String,
    major: String,
    shirt_size: String,
    dietary_restrictions: String,
    special_needs: Option<String>,
    date_of_birth: String,
    gender: String,
    phone_number: String,
    school: School,
}

#[derive(RustcDecodable, Debug)]
struct School {
    id: i32,
    name: String,
}

#[derive(RustcDecodable, Debug)]
struct TokenResp {
    access_token: String,
    token_type: String,
    scope: String,
    created_at: u64,
}

#[derive(RustcEncodable, Debug)]
struct Payload {
    channel: String,
    username: String,
    text: String,
    icon_emoji: String,
}

#[derive(Debug)]
enum ApiError {
    ClientError,
    ServerError,
}

#[derive(Debug)]
enum RequestError {
    Hyper(hyper::error::Error),
    Io(std::io::Error),
    JsonEnc(rustc_serialize::json::EncoderError),
    JsonDec(rustc_serialize::json::DecoderError),
    Api(ApiError),
}

// `env_err!(var, message)` gets `var` from the environment, and panics with
// `message` if that fails
// `env_err!(var)` gets `var` from the environment and panics with `"Failed to
// get env var $var"` if that fails
macro_rules! env_err {
    ( $var:expr, $error:expr ) => {
        env::var($var).expect($error)
    };
    ( $var:expr ) => {
        env_err!($var, &format!("Failed to get env var {}", $var))
    }
}

// Error handling code.  Expands to impl-ing From for enum_t from from_t to to_t
// See https://doc.rust-lang.org/book/error-handling.html for a full description
macro_rules! impl_from {
    ( $from_t:path, $to_t:path, $enum_t:path ) => {
        impl From<$from_t> for $enum_t {
            fn from(err: $from_t) -> $enum_t {
                $to_t(err)
            }
        }
    }
}

// All the impls for RequestError
impl_from!(hyper::error::Error, RequestError::Hyper, RequestError);
impl_from!(std::io::Error, RequestError::Io, RequestError);
impl_from!(rustc_serialize::json::DecoderError, RequestError::JsonDec,
           RequestError);
impl_from!(rustc_serialize::json::EncoderError, RequestError::JsonEnc,
           RequestError);
impl_from!(ApiError, RequestError::Api, RequestError);

// Checks for 4xx or 5xx errors and returns the appropriate ApiError
fn check_http_error(res: &Response) -> Result<(), ApiError> {
    match res.status.class() {
        StatusClass::ClientError => Err(ApiError::ClientError),
        StatusClass::ServerError => Err(ApiError::ServerError),
        _ => Ok(())
    }
}

// Do the OAUTH stuff for my.mlh.io
// TODO: Something better about the long api urls
fn do_request(code: &str) -> Result<Data, RequestError> {
    let id = env_err!("ID");
    let secret = env_err!("SECRET");
    let redirect = env_err!("REDIRECT");

    let url = format!("https://my.mlh.io/oauth/token?client_id={}&client_secret={}&code={}&redirect_uri={}&grant_type=authorization_code",
                      id, secret, code, redirect);

    let client = Client::new();
    let mut res = try!(client.post(&url)
        .header(Connection::close())
        .send());

    try!(check_http_error(&res));

    let mut body = String::new();
    try!(res.read_to_string(&mut body));

    let token: TokenResp = try!(json::decode(&body));
    let url2 = format!("https://my.mlh.io/api/v1/user?access_token={}",
                       token.access_token);

    res = try!(client.get(&url2)
        .header(Connection::close())
        .send());

    try!(check_http_error(&res));

    body = String::new();
    try!(res.read_to_string(&mut body));

    let person_data: Data = try!(json::decode(&body));

    Ok(person_data)
}

// Send a message to slack when a new user signs up
fn slack_send(user: User) -> Result<(), RequestError> {
    let url = env_err!("SLACKURL");
    let client = Client::new();
    let payload = Payload {
        channel: "#hackcwru".to_string(),
        username: "Signup bot".to_string(),
        icon_emoji: ":hackcwru:".to_string(),
        text: format!("{}, a {} major from {}, has signed up!",
                      user.first_name,
                      user.major,
                      user.school.name),
    };
    let payload_str = try!(json::encode(&payload));
    let res = try!(client.post(&url)
        .body(&payload_str)
        .send());

    try!(check_http_error(&res));

    Ok(())
}

// Create the table if it doesn't exist.  Runs on each startup
fn create_table(conn: PooledConnection<PostgresConnectionManager>) {
    let _r = conn.execute(
            "CREATE TABLE IF NOT EXISTS person (
                id SERIAL PRIMARY KEY,
                email VARCHAR NOT NULL,
                created_at VARCHAR NOT NULL,
                updated_at VARCHAR NOT NULL,
                first_name VARCHAR NOT NULL,
                last_name VARCHAR NOT NULL,
                graduation VARCHAR NOT NULL,
                major VARCHAR NOT NULL,
                shirt_size VARCHAR NOT NULL,
                dietary_restrictions VARCHAR NOT NULL,
                special_needs VARCHAR,
                date_of_birth VARCHAR NOT NULL,
                gender VARCHAR NOT NULL,
                phone_number VARCHAR NOT NULL,
                school_id integer,
                school_name VARCHAR
                )",
            &[]
        );
}

fn main() {
    let mut app = Nickel::new();

    let postgres_url = env_err!("DATABASE");
    let dbpool = PostgresMiddleware::new(&*postgres_url, SslMode::None, 5,
                                         Box::new(NopErrorHandler))
        .expect("Failed to start PostgresMiddleware");

    create_table(dbpool.pool.clone().get().unwrap());
    app.utilize(dbpool);

    app.get("/callback", middleware! { |request, mut response|
        let conn = request.db_conn();
        let redirect = env_err!("FINALREDIRECT");
        let code = match request.query().get("code") {
            Some(s) => s,
            None => {
                println!("No code, quitting");
                return response.error(StatusCode::BadRequest, "Failed");
            }
        };
        let user_data = match do_request(code) {
            Ok(s) => s,
            Err(e) => {
                println!("Get user data failed with error: {:?}", e);
                return response
                    .error(StatusCode::InternalServerError, "Failed");
            }
        }.data;

        // TODO: make this a function
        let r = conn.execute(
                "INSERT INTO person (id, email, created_at, updated_at,
                first_name, last_name, graduation, major, shirt_size,
                dietary_restrictions, special_needs, date_of_birth, gender,
                phone_number, school_id, school_name) VALUES ($1, $2, $3, $4,
                $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)",
                &[&user_data.id, &user_data.email, &user_data.created_at,
                  &user_data.updated_at, &user_data.first_name,
                  &user_data.last_name, &user_data.graduation, &user_data.major,
                  &user_data.shirt_size, &user_data.dietary_restrictions,
                  &user_data.special_needs, &user_data.date_of_birth,
                  &user_data.gender, &user_data.phone_number,
                  &user_data.school.id, &user_data.school.name]
            );
        match r {
            Ok(v) => {
                println!("Add to database succeeded with status {:?}", v);
                match slack_send(user_data) {
                    Ok(_) => println!("Slack send worked"),
                    Err(e) => println!("Slack send failed with error: {:?}", e)
                };
            },
            Err(e) => println!("Add to database failed: {:?}", e)
        }

        return response.redirect(&redirect[..]);
    });

    app.get("/start", middleware! { |_req, response|
        let id = env_err!("ID");
        let redirect = env_err!("REDIRECT");
        return response.redirect(
            format!(
                    "http://my.mlh.io/oauth/authorize?client_id={}&redirect_uri={}&response_type=code",
                    id, redirect
                )
            );
    });

    let bind = match env::var("BIND") {
        Ok(v) => v,
        Err(_) => "127.0.0.1:8080".to_string(),
    };

    app.listen(&bind[..]);
}
<|endoftext|>


<commit_before>extern crate piston_window;
extern crate find_folder;
extern crate websocket;
extern crate rustc_serialize;
extern crate mio;

use piston_window::{PistonWindow, WindowSettings, Glyphs, Button, MouseButton, clear,
                    text, ReleaseEvent, MouseCursorEvent, AdvancedWindow, Transformed,
                    FocusEvent};

mod board;
use board::{Board, Player};

use std::error::Error;

use rustc_serialize::json::{self, Json};

#[derive(RustcDecodable, Debug)]
struct Move {
    gameover: String,
    last_move: Vec<i8>,
}

#[derive(PartialEq)]
enum GameOver {
    Draw,
    Won,
    Lost,
    Quit,
}

fn main() {
    use websocket::{Message, Sender, Receiver, WebSocketStream};
    use websocket::message::Type;
    use websocket::client::request::Url;
    use websocket::Client;
    use websocket::result::WebSocketError;

    const USAGE: &'static str = "Usage: \n\tcargo run your_id [rival's id]";

    let player_id = match std::env::args().nth(1) {
        Some(player_id) => player_id,
        None => {
            println!("{}", USAGE);
            return;
        }
    };

    let rival_id = std::env::args().nth(2).unwrap_or(String::new());

    let url = Url::parse("ws://localhost:5000").unwrap();
    let request = Client::connect(url).expect("Couldn't connect to server");
    // Send the request and retrieve a response
    let response = request.send().expect("Failed to retrieve a response");
    // Validate the response
    response.validate().expect("Response invalid");

    let (mut sender, mut receiver) = response.begin().split();

    // Send the message
    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(false)
        .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 process_click = false;
    // mouse coords update flag
    let mut coords_updated = false;
    // the player starting the game
    let mut player = Player::O;
    let mut rival = Player::X;
    // current mouse cursor coordinates
    let mut coords = (0, 0);
    // websocket data
    let mut data = Move { gameover: String::new(), last_move: Vec::new() };
    // disable clicking events for opponent's turn
    let mut ignore_click_events = true;
    // disable incoming messages
    let mut ignore_incoming_messages = false;
    // gameover flag
    let mut gameover = None;
    // timer
    let mut timer = mio::timer::Timer::default();

    //set websocket receiver state to nonblocking
    match receiver.get_ref().get_ref() {
        &WebSocketStream::Tcp(ref inner) => inner.set_nonblocking(true).unwrap(),
	&WebSocketStream::Ssl(ref inner) => inner.get_ref().set_nonblocking(true).unwrap(),
    };

    sender.send_message(&Message::text(format!("{{\"message\":\"connect\",\"id\":\"{}\",\"rival\":\"{}\"}}", player_id, rival_id)))
        .unwrap_or_else(|e| {
            println!("Error: {:?}", e);
            sender.send_message(&Message::close()).unwrap();
	});

    loop {

        if !ignore_incoming_messages {
            let result: Result<Message, _> = receiver.recv_message();
            match result {
                Ok(message) => {
                    match message.opcode {

                        Type::Text => {
                            match std::str::from_utf8(&message.payload) {
                                Ok(ref s) => {
                                    let json = Json::from_str(s).expect("Error parsing JSON");
                                    let obj = json.as_object().unwrap();
                                    if let Some(msg) = obj.get("ok") {
                                        println!("{}", msg);
                                    }
                                    else if let Some(error) = obj.get("error") {
                                        println!("{}", error);
                                    }
                                    else if let Some(_) = obj.get("gameover") {
                                        println!("JSON: {:?}", obj);
                                        data = json::decode(s).unwrap();
                                        ignore_click_events = false;
                                        match &*data.gameover {
                                            "won" =>
                                                gameover = Some(GameOver::Won),
                                            "lost" =>
                                                gameover = Some(GameOver::Lost),
                                            "draw" =>
                                                gameover = Some(GameOver::Draw),
                                            "quit" =>
                                                gameover = Some(GameOver::Quit),
                                            "false" => {
                                                gameover = None;
                                                window.set_title(format!("Your turn, {}", player_id));
                                            }
                                            _ => ()
                                        }
                                        if gameover.is_some() {
                                            ignore_incoming_messages = true;
                                        }
                                    }
                                    else {
                                        println!("Unexpected data: {:?}", obj);
                                    }
                                }
                                Err(ref e) => {
                                    println!("Error: {}", e.description());
                                }
                            }
                        },

                        Type::Close => break,

                        _ => (),
                    }
                },

	        Err(e) => {
                    match e {
                        WebSocketError::IoError(_) => (),
                        _ => {
                            println!("Error: {:?}", e);
                            break;
                        }
                    }
	        }
            }
        }

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

            if !ignore_click_events && gameover.is_none() {

                if let Some(_) = e.focus_args() {
                    process_click = false;
                    ignore_click_events = false;
                    continue;
                }

                if data.last_move.len() == 1 && data.last_move[0] == -1 {
                    player = Player::X;
                    rival = Player::O;
                }
                else if data.gameover != "lost" && data.gameover != "draw" && data.gameover != "quit" {
                    let m = data.last_move.clone();
                    board[m[0] as usize][m[1] as usize] = Some(rival);
                }

                if let Some(button) = e.release_args() {
                    if button == Button::Mouse(MouseButton::Left) {
                        if coords_updated {
                            process_click = true;
                            ignore_click_events = true;
                        }
                    }
                }

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

                if process_click && coords_updated {
                    if coords == (0, 0) {
                        process_click = false;
                        ignore_click_events = false;
                        continue;
                    }
                    let x = match coords.0 {
                          0 ...  99 => 0,
                        100 ... 199 => 1,
                        200 ... 299 => 2,
                        _ => {
                            process_click = false;
                            ignore_click_events = false;
                            continue;
                        }
                    };
                    let y = match coords.1 {
                          0 ...  99 => 0,
                        100 ... 199 => 1,
                        200 ... 299 => 2,
                        _ => {
                            process_click = false;
                            ignore_click_events = false;
                            continue;
                        }
                    };
                    if board[y][x].is_none() {
                        board[y][x] = Some(player);
                        window.set_title("Waiting for opponent's move".to_string());
                        sender.send_message(&Message::text(format!("{{\"move\":[{},{}]}}", y, x))).unwrap();
                    }
                    else {
                        ignore_click_events = false;
                    }

                    process_click = false;
                    coords_updated = false;
                }
            }

            if gameover.is_some() {
                match gameover {
                    Some(GameOver::Won) =>
                        window.set_title("You won!".to_string()),
                    Some(GameOver::Lost) => {
                        window.set_title("You lost!".to_string());
                        let m = data.last_move.clone();
                        board[m[0] as usize][m[1] as usize] = Some(rival);
                    },
                    Some(GameOver::Draw) => {
                        window.set_title("It's a draw!".to_string());
                        let m = data.last_move.clone();
                        if board[m[0] as usize][m[1] as usize].is_none() {
                            board[m[0] as usize][m[1] as usize] = Some(rival);
                        }
                    },
                    Some(GameOver::Quit) => {
                        window.set_title("Opponent quit".to_string());
                    },
                    None => (),
                }

                let _timeout = timer.set_timeout(std::time::Duration::from_secs(5), ());
                match timer.poll() {
                    Some(()) => {
                        ignore_incoming_messages = false;
                        board = Board::new();
                        if let Some(quit) = gameover {
                            if quit == GameOver::Quit {
                                break;
                            }
                        }
                        gameover = None;
                        timer = mio::timer::Timer::default();
                    },
                    None => (),
                }
            }

            // Draw the board
            window.draw_2d(&e, |c, g| {
                clear(white, g);
                for (y, row) in board.0.iter().enumerate() {
                    let y = y as f64;
                    for (x, cell) in row.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 => {}
                        }
                    }
                }
            });
        }
        else {
            break;
        }
    }
}
<commit_msg>Updated server address<commit_after>extern crate piston_window;
extern crate find_folder;
extern crate websocket;
extern crate rustc_serialize;
extern crate mio;

use piston_window::{PistonWindow, WindowSettings, Glyphs, Button, MouseButton, clear,
                    text, ReleaseEvent, MouseCursorEvent, AdvancedWindow, Transformed,
                    FocusEvent};

mod board;
use board::{Board, Player};

use std::error::Error;

use rustc_serialize::json::{self, Json};

#[derive(RustcDecodable, Debug)]
struct Move {
    gameover: String,
    last_move: Vec<i8>,
}

#[derive(PartialEq)]
enum GameOver {
    Draw,
    Won,
    Lost,
    Quit,
}

fn main() {
    use websocket::{Message, Sender, Receiver, WebSocketStream};
    use websocket::message::Type;
    use websocket::client::request::Url;
    use websocket::Client;
    use websocket::result::WebSocketError;

    const USAGE: &'static str = "Usage: \n\tcargo run your_id [rival's id]";

    let player_id = match std::env::args().nth(1) {
        Some(player_id) => player_id,
        None => {
            println!("{}", USAGE);
            return;
        }
    };

    let rival_id = std::env::args().nth(2).unwrap_or(String::new());

    let url = Url::parse("wss://tictactoe-serv.herokuapp.com").unwrap();
    let request = Client::connect(url).expect("Couldn't connect to server");
    // Send the request and retrieve a response
    let response = request.send().expect("Failed to retrieve a response");
    // Validate the response
    response.validate().expect("Response invalid");

    let (mut sender, mut receiver) = response.begin().split();

    // Send the message
    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(false)
        .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 process_click = false;
    // mouse coords update flag
    let mut coords_updated = false;
    // the player starting the game
    let mut player = Player::O;
    let mut rival = Player::X;
    // current mouse cursor coordinates
    let mut coords = (0, 0);
    // websocket data
    let mut data = Move { gameover: String::new(), last_move: Vec::new() };
    // disable clicking events for opponent's turn
    let mut ignore_click_events = true;
    // disable incoming messages
    let mut ignore_incoming_messages = false;
    // gameover flag
    let mut gameover = None;
    // timer
    let mut timer = mio::timer::Timer::default();

    //set websocket receiver state to nonblocking
    match receiver.get_ref().get_ref() {
        &WebSocketStream::Tcp(ref inner) => inner.set_nonblocking(true).unwrap(),
	&WebSocketStream::Ssl(ref inner) => inner.get_ref().set_nonblocking(true).unwrap(),
    };

    sender.send_message(&Message::text(format!("{{\"message\":\"connect\",\"id\":\"{}\",\"rival\":\"{}\"}}", player_id, rival_id)))
        .unwrap_or_else(|e| {
            println!("Error: {:?}", e);
            sender.send_message(&Message::close()).unwrap();
	});

    loop {

        if !ignore_incoming_messages {
            let result: Result<Message, _> = receiver.recv_message();
            match result {
                Ok(message) => {
                    match message.opcode {

                        Type::Text => {
                            match std::str::from_utf8(&message.payload) {
                                Ok(ref s) => {
                                    let json = Json::from_str(s).expect("Error parsing JSON");
                                    let obj = json.as_object().unwrap();
                                    if let Some(msg) = obj.get("ok") {
                                        println!("{}", msg);
                                    }
                                    else if let Some(error) = obj.get("error") {
                                        println!("{}", error);
                                    }
                                    else if let Some(_) = obj.get("gameover") {
                                        println!("JSON: {:?}", obj);
                                        data = json::decode(s).unwrap();
                                        ignore_click_events = false;
                                        match &*data.gameover {
                                            "won" =>
                                                gameover = Some(GameOver::Won),
                                            "lost" =>
                                                gameover = Some(GameOver::Lost),
                                            "draw" =>
                                                gameover = Some(GameOver::Draw),
                                            "quit" =>
                                                gameover = Some(GameOver::Quit),
                                            "false" => {
                                                gameover = None;
                                                window.set_title(format!("Your turn, {}", player_id));
                                            }
                                            _ => ()
                                        }
                                        if gameover.is_some() {
                                            ignore_incoming_messages = true;
                                        }
                                    }
                                    else {
                                        println!("Unexpected data: {:?}", obj);
                                    }
                                }
                                Err(ref e) => {
                                    println!("Error: {}", e.description());
                                }
                            }
                        },

                        Type::Close => break,

                        _ => (),
                    }
                },

	        Err(e) => {
                    match e {
                        WebSocketError::IoError(_) => (),
                        _ => {
                            println!("Error: {:?}", e);
                            break;
                        }
                    }
	        }
            }
        }

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

            if !ignore_click_events && gameover.is_none() {

                if let Some(_) = e.focus_args() {
                    process_click = false;
                    ignore_click_events = false;
                    continue;
                }

                if data.last_move.len() == 1 && data.last_move[0] == -1 {
                    player = Player::X;
                    rival = Player::O;
                }
                else if data.gameover != "lost" && data.gameover != "draw" && data.gameover != "quit" {
                    let m = data.last_move.clone();
                    board[m[0] as usize][m[1] as usize] = Some(rival);
                }

                if let Some(button) = e.release_args() {
                    if button == Button::Mouse(MouseButton::Left) {
                        if coords_updated {
                            process_click = true;
                            ignore_click_events = true;
                        }
                    }
                }

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

                if process_click && coords_updated {
                    if coords == (0, 0) {
                        process_click = false;
                        ignore_click_events = false;
                        continue;
                    }
                    let x = match coords.0 {
                          0 ...  99 => 0,
                        100 ... 199 => 1,
                        200 ... 299 => 2,
                        _ => {
                            process_click = false;
                            ignore_click_events = false;
                            continue;
                        }
                    };
                    let y = match coords.1 {
                          0 ...  99 => 0,
                        100 ... 199 => 1,
                        200 ... 299 => 2,
                        _ => {
                            process_click = false;
                            ignore_click_events = false;
                            continue;
                        }
                    };
                    if board[y][x].is_none() {
                        board[y][x] = Some(player);
                        window.set_title("Waiting for opponent's move".to_string());
                        sender.send_message(&Message::text(format!("{{\"move\":[{},{}]}}", y, x))).unwrap();
                    }
                    else {
                        ignore_click_events = false;
                    }

                    process_click = false;
                    coords_updated = false;
                }
            }

            if gameover.is_some() {
                match gameover {
                    Some(GameOver::Won) =>
                        window.set_title("You won!".to_string()),
                    Some(GameOver::Lost) => {
                        window.set_title("You lost!".to_string());
                        let m = data.last_move.clone();
                        board[m[0] as usize][m[1] as usize] = Some(rival);
                    },
                    Some(GameOver::Draw) => {
                        window.set_title("It's a draw!".to_string());
                        let m = data.last_move.clone();
                        if board[m[0] as usize][m[1] as usize].is_none() {
                            board[m[0] as usize][m[1] as usize] = Some(rival);
                        }
                    },
                    Some(GameOver::Quit) => {
                        window.set_title("Opponent quit".to_string());
                    },
                    None => (),
                }

                let _timeout = timer.set_timeout(std::time::Duration::from_secs(5), ());
                match timer.poll() {
                    Some(()) => {
                        ignore_incoming_messages = false;
                        board = Board::new();
                        if let Some(quit) = gameover {
                            if quit == GameOver::Quit {
                                break;
                            }
                        }
                        gameover = None;
                        timer = mio::timer::Timer::default();
                    },
                    None => (),
                }
            }

            // Draw the board
            window.draw_2d(&e, |c, g| {
                clear(white, g);
                for (y, row) in board.0.iter().enumerate() {
                    let y = y as f64;
                    for (x, cell) in row.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 => {}
                        }
                    }
                }
            });
        }
        else {
            break;
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Schema Compiler Plugin Executable
//!
//! [See this.](http://kentonv.github.io/capnproto/otherlang.html#how-to-write-compiler-plugins)
//!
//!

#![crate_name="capnpc-rust"]
#![crate_type = "bin"]

#![allow(unstable)]

extern crate capnp;
extern crate capnpc;

pub fn main() {
    //! Generate Rust code according to a `schema_capnp::code_generator_request` read from stdin.

    match ::capnpc::codegen::main(&mut ::std::io::stdin()) {
        Ok(()) => {}
        Err(e) => {
            std::os::set_exit_status(1);
            println!("error: {}", e)
        }
    }
}
<commit_msg>missed this one<commit_after>// Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! # Cap'n Proto Schema Compiler Plugin Executable
//!
//! [See this.](http://kentonv.github.io/capnproto/otherlang.html#how-to-write-compiler-plugins)
//!
//!

#![crate_name="capnpc-rust"]
#![crate_type = "bin"]

#![allow(unstable)]

extern crate capnp;
extern crate capnpc;

pub fn main() {
    //! Generate Rust code according to a `schema_capnp::code_generator_request` read from stdin.

    match ::capnpc::codegen::main(&mut ::std::old_io::stdin()) {
        Ok(()) => {}
        Err(e) => {
            std::os::set_exit_status(1);
            println!("error: {}", e)
        }
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::net::TcpStream;

extern crate cdrs;
use cdrs::frame::Frame;
use cdrs::parser::parse_frame;
use cdrs::IntoBytes;
// use cadrs::frame_startup::BodyReqStartup;

fn main() {
    println!("connecting");
    let startup_message = Frame::new_req_startup(None);
    match TcpStream::connect("127.0.0.1:9042") {
        Err(err) => println!("{:?}", err),
        Ok(mut stream) => {
            println!("Ok. Starting connection");
            let vec: Vec<u8> = startup_message.into_bytes();
            println!("Frame {:?}", vec);
            println!("Frame text {:?}", String::from_utf8(vec.clone()).unwrap());
            match stream.write(vec.as_slice()) {
                Ok(_) => {
                    println!("frame sent");
                },
                Err(err) => panic!("Error during writing into socket {}", err)
            }

            loop {
                let mut res = [0; 1024];
                match stream.read(&mut res) {
                    Ok(n) => {
                        if n > 0 {
                            // println!("Server response {:?}", &res[..]);
                            let parsed = parse_frame(res[..].to_vec());
                            println!("Parsed response {:?}", parsed);
                            continue;
                        } else {
                            println!("waiting...");
                        }

                    },
                    Err(err) => panic!("Error during reading from socket {}", err)
                }
            }
        }
    }
}
<commit_msg>Change name to cdrs<commit_after>// NOTE: for development purposes only. Will be removed soon
use std::io::prelude::*;
use std::net::TcpStream;

extern crate cdrs;
use cdrs::frame::Frame;
use cdrs::parser::parse_frame;
use cdrs::IntoBytes;
// use cadrs::frame_startup::BodyReqStartup;

fn main() {
    println!("connecting");
    let startup_message = Frame::new_req_startup(None);
    match TcpStream::connect("127.0.0.1:9042") {
        Err(err) => println!("{:?}", err),
        Ok(mut stream) => {
            println!("Ok. Starting connection");
            let vec: Vec<u8> = startup_message.into_bytes();
            println!("Frame {:?}", vec);
            println!("Frame text {:?}", String::from_utf8(vec.clone()).unwrap());
            match stream.write(vec.as_slice()) {
                Ok(_) => {
                    println!("frame sent");
                },
                Err(err) => panic!("Error during writing into socket {}", err)
            }

            loop {
                let mut res = [0; 1024];
                match stream.read(&mut res) {
                    Ok(n) => {
                        if n > 0 {
                            // println!("Server response {:?}", &res[..]);
                            let parsed = parse_frame(res[..].to_vec());
                            println!("Parsed response {:?}", parsed);
                            continue;
                        } else {
                            println!("waiting...");
                        }

                    },
                    Err(err) => panic!("Error during reading from socket {}", err)
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::ffi::{OsStr, OsString};
use std::io::{self, Write};
use std::path::PathBuf;
use std::process::{self, Command};

#[cfg(unix)]
use std::process::{Child, Stdio};

extern crate isatty;
use isatty::{stdout_isatty, stderr_isatty};

#[cfg(unix)]
extern crate tempdir;
#[cfg(unix)]
use tempdir::TempDir;

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

#[cfg(windows)]
fn cargo_expand() -> io::Result<i32> {
    // Build cargo command
    let mut cmd = Command::new("cargo");
    cmd.args(&wrap_args(env::args_os(), None));
    run(cmd)
}

#[cfg(unix)]
fn cargo_expand() -> io::Result<i32> {
    let args: Vec<_> = env::args_os().collect();
    match args.last().unwrap().to_str().unwrap_or("") {
        "--filter-cargo" => filter_err(ignore_cargo_err),
        "--filter-rustfmt" => filter_err(ignore_rustfmt_err),
        _ => {}
    }

    macro_rules! shell {
        ($($arg:expr)*) => {
            &[$(OsStr::new(&$arg)),*]
        };
    }

    let which_rustfmt = which(&["rustfmt"]);
    let which_pygmentize = if stdout_isatty() {
        which(&["pygmentize", "-l", "rust"])
    } else {
        None
    };

    let outdir = if which_rustfmt.is_some() || which_pygmentize.is_some() {
        Some(TempDir::new("cargo-expand").expect("failed to create tmp file"))
    } else {
        None
    };
    let outfile = outdir.as_ref().map(|dir| dir.path().join("expanded"));

    // Build cargo command
    let mut cmd = Command::new("cargo");
    cmd.args(&wrap_args(args.clone(), outfile.as_ref()));

    // Pipe to a tmp file to separate out any println output from build scripts
    if let Some(outfile) = outfile {
        let mut filter_cargo = Vec::new();
        filter_cargo.extend(args.iter().map(OsString::as_os_str));
        filter_cargo.push(OsStr::new("--filter-cargo"));

        let _wait = cmd.pipe_to(shell!("cat"), Some(&filter_cargo))?;
        run(cmd)?;
        drop(_wait);

        cmd = Command::new("cat");
        cmd.arg(outfile);
    }

    // Pipe to rustfmt
    let _wait = match which_rustfmt {
        Some(ref fmt) => {
            let args: Vec<_> = env::args_os().collect();
            let mut filter_rustfmt = Vec::new();
            filter_rustfmt.extend(args.iter().map(OsString::as_os_str));
            filter_rustfmt.push(OsStr::new("--filter-rustfmt"));

            Some(cmd.pipe_to(shell!(fmt), Some(&filter_rustfmt))?)
        }
        None => None,
    };

    // Pipe to pygmentize
    let _wait = match which_pygmentize {
        Some(pyg) => Some(cmd.pipe_to(shell!(pyg "-l" "rust"), None)?),
        None => None,
    };

    run(cmd)
}

fn run(mut cmd: Command) -> io::Result<i32> {
    cmd.status().map(|status| status.code().unwrap_or(1))
}

#[cfg(unix)]
struct Wait(Vec<Child>);

#[cfg(unix)]
impl Drop for Wait {
    fn drop(&mut self) {
        for child in &mut self.0 {
            if let Err(err) = child.wait() {
                let _ = writeln!(&mut io::stderr(), "{}", err);
            }
        }
    }
}

#[cfg(unix)]
trait PipeTo {
    fn pipe_to(&mut self, out: &[&OsStr], err: Option<&[&OsStr]>) -> io::Result<Wait>;
}

#[cfg(unix)]
impl PipeTo for Command {
    fn pipe_to(&mut self, out: &[&OsStr], err: Option<&[&OsStr]>) -> io::Result<Wait> {
        use std::os::unix::io::{AsRawFd, FromRawFd};

        self.stdout(Stdio::piped());
        if err.is_some() {
            self.stderr(Stdio::piped());
        }

        let child = self.spawn()?;

        *self = Command::new(out[0]);
        self.args(&out[1..]);
        self.stdin(unsafe {
            Stdio::from_raw_fd(child.stdout.as_ref().map(AsRawFd::as_raw_fd).unwrap())
        });

        match err {
            None => {
                Ok(Wait(vec![child]))
            }
            Some(err) => {
                let mut errcmd = Command::new(err[0]);
                errcmd.args(&err[1..]);
                errcmd.stdin(unsafe {
                    Stdio::from_raw_fd(child.stderr.as_ref().map(AsRawFd::as_raw_fd).unwrap())
                });
                errcmd.stdout(Stdio::null());
                errcmd.stderr(Stdio::inherit());
                let spawn = errcmd.spawn()?;
                Ok(Wait(vec![spawn, child]))
            }
        }
    }
}

// Based on https://github.com/rsolomo/cargo-check
fn wrap_args<I>(it: I, outfile: Option<&PathBuf>) -> Vec<OsString>
    where I: IntoIterator<Item=OsString>
{
    let mut args = vec!["rustc".into()];
    let mut ends_with_test = false;
    let mut ends_with_example = false;
    let mut has_color = false;

    let mut it = it.into_iter().skip(2);
    for arg in &mut it {
        if arg == *"--" {
            break;
        }
        ends_with_test = arg == *"--test";
        ends_with_example = arg == *"--example";
        has_color |= arg.to_str().unwrap_or("").starts_with("--color");
        args.push(arg.into());
    }

    if ends_with_test {
        // Expand the `test.rs` test by default.
        args.push("test".into());
    }

    if ends_with_example {
        // Expand the `example.rs` example by default.
        args.push("example".into());
    }

    if !has_color {
        let color = stderr_isatty();
        let setting = if color { "always" } else { "never" };
        args.push(format!("--color={}", setting).into());
    }

    args.push("--".into());
    if let Some(path) = outfile {
        args.push("-o".into());
        args.push(path.into());
    }
    args.push("-Zunstable-options".into());
    args.push("--pretty=expanded".into());
    args.extend(it);
    args
}

#[cfg(unix)]
fn which(cmd: &[&str]) -> Option<OsString> {
    if env::args_os().find(|arg| arg == "--help").is_some() {
        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
    }
}

#[cfg(unix)]
fn filter_err(ignore: fn(&str) -> bool) -> ! {
    let mut line = String::new();
    while let Ok(n) = io::stdin().read_line(&mut line) {
        if n == 0 {
            break;
        }
        if !ignore(&line) {
            let _ = write!(&mut io::stderr(), "{}", line);
        }
        line.clear();
    }
    process::exit(0);
}

#[cfg(unix)]
fn ignore_rustfmt_err(line: &str) -> bool {
    line.trim().is_empty()
        || line.contains(": line exceeded maximum length (")
        || line.trim_right().ends_with("left behind trailing whitespace (sorry)")
}

#[cfg(unix)]
fn ignore_cargo_err(line: &str) -> bool {
    line.trim().is_empty()
        || line.contains("ignoring specified output filename because multiple outputs were requested")
        || line.contains("ignoring specified output filename for 'link' output because multiple outputs were requested")
        || line.contains("ignoring --out-dir flag due to -o flag.")
        || line.contains("due to multiple output types requested, the explicitly specified output file name will be adapted for each output type")
}
<commit_msg>Just suppress all rustfmt error output<commit_after>use std::env;
use std::ffi::{OsStr, OsString};
use std::io::{self, Write};
use std::path::PathBuf;
use std::process::{self, Command};

#[cfg(unix)]
use std::process::{Child, Stdio};

extern crate isatty;
use isatty::{stdout_isatty, stderr_isatty};

#[cfg(unix)]
extern crate tempdir;
#[cfg(unix)]
use tempdir::TempDir;

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

#[cfg(windows)]
fn cargo_expand() -> io::Result<i32> {
    // Build cargo command
    let mut cmd = Command::new("cargo");
    cmd.args(&wrap_args(env::args_os(), None));
    run(cmd)
}

#[cfg(unix)]
fn cargo_expand() -> io::Result<i32> {
    let args: Vec<_> = env::args_os().collect();
    match args.last().unwrap().to_str().unwrap_or("") {
        "--filter-cargo" => filter_err(ignore_cargo_err),
        "--filter-rustfmt" => filter_err(ignore_rustfmt_err),
        _ => {}
    }

    macro_rules! shell {
        ($($arg:expr)*) => {
            &[$(OsStr::new(&$arg)),*]
        };
    }

    let which_rustfmt = which(&["rustfmt"]);
    let which_pygmentize = if stdout_isatty() {
        which(&["pygmentize", "-l", "rust"])
    } else {
        None
    };

    let outdir = if which_rustfmt.is_some() || which_pygmentize.is_some() {
        Some(TempDir::new("cargo-expand").expect("failed to create tmp file"))
    } else {
        None
    };
    let outfile = outdir.as_ref().map(|dir| dir.path().join("expanded"));

    // Build cargo command
    let mut cmd = Command::new("cargo");
    cmd.args(&wrap_args(args.clone(), outfile.as_ref()));

    // Pipe to a tmp file to separate out any println output from build scripts
    if let Some(outfile) = outfile {
        let mut filter_cargo = Vec::new();
        filter_cargo.extend(args.iter().map(OsString::as_os_str));
        filter_cargo.push(OsStr::new("--filter-cargo"));

        let _wait = cmd.pipe_to(shell!("cat"), Some(&filter_cargo))?;
        run(cmd)?;
        drop(_wait);

        cmd = Command::new("cat");
        cmd.arg(outfile);
    }

    // Pipe to rustfmt
    let _wait = match which_rustfmt {
        Some(ref fmt) => {
            let args: Vec<_> = env::args_os().collect();
            let mut filter_rustfmt = Vec::new();
            filter_rustfmt.extend(args.iter().map(OsString::as_os_str));
            filter_rustfmt.push(OsStr::new("--filter-rustfmt"));

            Some((
                cmd.pipe_to(shell!(fmt), None)?,
                cmd.pipe_to(shell!("cat"), Some(&filter_rustfmt))?,
            ))
        }
        None => None,
    };

    // Pipe to pygmentize
    let _wait = match which_pygmentize {
        Some(pyg) => Some(cmd.pipe_to(shell!(pyg "-l" "rust"), None)?),
        None => None,
    };

    run(cmd)
}

fn run(mut cmd: Command) -> io::Result<i32> {
    cmd.status().map(|status| status.code().unwrap_or(1))
}

#[cfg(unix)]
struct Wait(Vec<Child>);

#[cfg(unix)]
impl Drop for Wait {
    fn drop(&mut self) {
        for child in &mut self.0 {
            if let Err(err) = child.wait() {
                let _ = writeln!(&mut io::stderr(), "{}", err);
            }
        }
    }
}

#[cfg(unix)]
trait PipeTo {
    fn pipe_to(&mut self, out: &[&OsStr], err: Option<&[&OsStr]>) -> io::Result<Wait>;
}

#[cfg(unix)]
impl PipeTo for Command {
    fn pipe_to(&mut self, out: &[&OsStr], err: Option<&[&OsStr]>) -> io::Result<Wait> {
        use std::os::unix::io::{AsRawFd, FromRawFd};

        self.stdout(Stdio::piped());
        if err.is_some() {
            self.stderr(Stdio::piped());
        }

        let child = self.spawn()?;

        *self = Command::new(out[0]);
        self.args(&out[1..]);
        self.stdin(unsafe {
            Stdio::from_raw_fd(child.stdout.as_ref().map(AsRawFd::as_raw_fd).unwrap())
        });

        match err {
            None => {
                Ok(Wait(vec![child]))
            }
            Some(err) => {
                let mut errcmd = Command::new(err[0]);
                errcmd.args(&err[1..]);
                errcmd.stdin(unsafe {
                    Stdio::from_raw_fd(child.stderr.as_ref().map(AsRawFd::as_raw_fd).unwrap())
                });
                errcmd.stdout(Stdio::null());
                errcmd.stderr(Stdio::inherit());
                let spawn = errcmd.spawn()?;
                Ok(Wait(vec![spawn, child]))
            }
        }
    }
}

// Based on https://github.com/rsolomo/cargo-check
fn wrap_args<I>(it: I, outfile: Option<&PathBuf>) -> Vec<OsString>
    where I: IntoIterator<Item=OsString>
{
    let mut args = vec!["rustc".into()];
    let mut ends_with_test = false;
    let mut ends_with_example = false;
    let mut has_color = false;

    let mut it = it.into_iter().skip(2);
    for arg in &mut it {
        if arg == *"--" {
            break;
        }
        ends_with_test = arg == *"--test";
        ends_with_example = arg == *"--example";
        has_color |= arg.to_str().unwrap_or("").starts_with("--color");
        args.push(arg.into());
    }

    if ends_with_test {
        // Expand the `test.rs` test by default.
        args.push("test".into());
    }

    if ends_with_example {
        // Expand the `example.rs` example by default.
        args.push("example".into());
    }

    if !has_color {
        let color = stderr_isatty();
        let setting = if color { "always" } else { "never" };
        args.push(format!("--color={}", setting).into());
    }

    args.push("--".into());
    if let Some(path) = outfile {
        args.push("-o".into());
        args.push(path.into());
    }
    args.push("-Zunstable-options".into());
    args.push("--pretty=expanded".into());
    args.extend(it);
    args
}

#[cfg(unix)]
fn which(cmd: &[&str]) -> Option<OsString> {
    if env::args_os().find(|arg| arg == "--help").is_some() {
        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
    }
}

#[cfg(unix)]
fn filter_err(ignore: fn(&str) -> bool) -> ! {
    let mut line = String::new();
    while let Ok(n) = io::stdin().read_line(&mut line) {
        if n == 0 {
            break;
        }
        if !ignore(&line) {
            let _ = write!(&mut io::stderr(), "{}", line);
        }
        line.clear();
    }
    process::exit(0);
}

#[cfg(unix)]
fn ignore_rustfmt_err(_line: &str) -> bool {
    true
}

#[cfg(unix)]
fn ignore_cargo_err(line: &str) -> bool {
    line.trim().is_empty()
        || line.contains("ignoring specified output filename because multiple outputs were requested")
        || line.contains("ignoring specified output filename for 'link' output because multiple outputs were requested")
        || line.contains("ignoring --out-dir flag due to -o flag.")
        || line.contains("due to multiple output types requested, the explicitly specified output file name will be adapted for each output type")
}
<|endoftext|>