<commit_before>#[macro_use]
extern crate lazy_static;

extern crate clap;
extern crate qrcode;
extern crate termion;
extern crate image;
extern crate regex;

use clap::{App, Arg, SubCommand};
use qrcode::{QrCode, EcLevel};
use termion::color;

mod payloads;

const WIFI_COMMAND: &'static str = "wifi";
const MAIL_COMMAND: &'static str = "mail";
// const SMS_COMMAND: &'static str = "sms";
// const MMS_COMMAND: &'static str = "mms";
// const GEO_COMMAND: &'static str = "geo";
const PHONE_COMMAND: &'static str = "phone";
// const SKYPE_COMMAND: &'static str = "skype";
const URL_COMMAND: &'static str = "url";
// const BOOKMARK_COMMAND: &'static str = "bookmark";
// const BITCOIN_COMMAND: &'static str = "bitcoin";
// const GIRO_COMMAND: &'static str = "giro";
// const CALENDAR_COMMAND: &'static str = "calendar";

/*TODO: add arguments for:
- ec Level
- size of qr code
- implement different types of qr payloads
*/
fn main() {
    let app = App::new("qrterm")
        .version("0.1")
        .author("Lukas R. <lukas@bootsmann-games.de>")
        .about("Generates and displays terminal friendly QR-Codes from input strings")
        .arg(Arg::with_name("safe_zone") //TODO: change this into an off switch
            .global(true)
            .required(false)
            .short("s")
            .long("safe-zone")
            .help("Sets wether the safe zone around the code should be drawn or not.")
            .takes_value(false)
            )
            //TODO: subcmds are not working like expected, if you have one the system assumes you have many
        .subcommand(SubCommand::with_name(WIFI_COMMAND)
            .about("formats to a wifi access string")
            .arg(Arg::with_name("ssid").required(true))
            .arg(Arg::with_name("pwd").required(true))
            .arg(Arg::with_name("mode")
                .possible_values(&["WEP", "WPA", "nopass"])
                .default_value("WPA")
                .value_name("MODE"))
            .arg(Arg::with_name("hidden")
                .required(false)
                .possible_values(&["true", "false"])
                .default_value("false")
                .value_name("HIDDEN")))
        .subcommand(SubCommand::with_name(MAIL_COMMAND)
            .about("formats to a mail adress string")
            .arg(Arg::with_name("receiver").required(true))
            .arg(Arg::with_name("subject"))
            .arg(Arg::with_name("message"))
            .arg(Arg::with_name("encoding")
                .possible_values(&["MAILTO", "MATMSG", "SMTP"])
                .default_value("MAILTO")
                .value_name("ENCODING")))
        .subcommand(SubCommand::with_name(URL_COMMAND)
            .about("formats to an URL")
            .arg(Arg::with_name("url")
                .required(true)
                .value_name("URL")))
        .subcommand(SubCommand::with_name(PHONE_COMMAND)
            .about("formats to a phone number")
            .arg(Arg::with_name("number")
                .required(true)
                .value_name("NUMBER")))
        .arg(Arg::with_name("INPUT")
            .help("The input string to use")
            .required_unless_one(&[WIFI_COMMAND, MAIL_COMMAND, URL_COMMAND, PHONE_COMMAND]));

    let matches = app.get_matches();

    let payload: String;
    if let Some(sub) = matches.subcommand_matches(WIFI_COMMAND) {
        let auth = match sub.value_of("mode") {
            Some("WEP") => payloads::Authentication::WEP,
            Some("WPA") => payloads::Authentication::WPA,
            _ => payloads::Authentication::nopass,
        };
        payload = payloads::wifi_string(sub.value_of("ssid").unwrap(),
                                        sub.value_of("pwd").unwrap(),
                                        &auth,
                                        sub.value_of("hidden").unwrap() == "true");
    } else if let Some(sub) = matches.subcommand_matches(MAIL_COMMAND) {
        let encoding = match sub.value_of("encoding") {
            Some("MAILTO") => payloads::MailEncoding::MAILTO,
            Some("MATMSG") => payloads::MailEncoding::MATMSG,
            Some("SMTP") => payloads::MailEncoding::SMTP,
            _ => payloads::MailEncoding::MAILTO,
        };
        payload = payloads::mail_string(sub.value_of("receiver").unwrap(),
                                        sub.value_of("subject").unwrap(),
                                        sub.value_of("message").unwrap(),
                                        &encoding);
    } else if let Some(sub) = matches.subcommand_matches(URL_COMMAND) {
        payload = payloads::url_string(sub.value_of("url").unwrap());
    } else if let Some(sub) = matches.subcommand_matches(PHONE_COMMAND) {
        payload = payloads::phone_string(sub.value_of("phone").unwrap());
    } else {
        payload = String::from(matches.value_of("INPUT").unwrap());
    }

    let safe: bool = match matches.occurrences_of("safe_zone") {
        0 => true,
        _ => false,
    };

    let code = QrCode::with_error_correction_level(payload, EcLevel::H).unwrap();

    let bit_array = code.to_vec();

    let w = code.width();
    let wide = w + 6;

    //Draw the first white safe zone
    if safe {
        for a in 1..(wide * 3) + 1 {
            print!("{}  ", color::Bg(color::LightWhite));
            if a % wide == 0 {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }

    for (i, item) in bit_array.iter().enumerate() {
        //left safe zone
        if safe && i % w == 0 {
            print!("{}      ", color::Bg(color::LightWhite));
        }

        if *item {
            print!("{}  ", color::Bg(color::Black));
        } else {
            print!("{}  ", color::Bg(color::LightWhite));
        }

        if (i + 1) % w == 0 {
            if safe {
                //draw right safe zone
                println!("{}      {}",
                         color::Bg(color::LightWhite),
                         color::Bg(color::Reset));
            } else {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }

    //Draw the last white safe zone
    if safe {
        for a in 1..(wide * 3) + 1 {
            print!("{}  ", color::Bg(color::LightWhite));
            if a % wide == 0 {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }
}
<commit_msg>changed deprecated method<commit_after>#[macro_use]
extern crate lazy_static;

extern crate clap;
extern crate qrcode;
extern crate termion;
extern crate image;
extern crate regex;

use clap::{App, Arg, SubCommand};
use qrcode::{QrCode, EcLevel};
use termion::color;

mod payloads;

const WIFI_COMMAND: &'static str = "wifi";
const MAIL_COMMAND: &'static str = "mail";
// const SMS_COMMAND: &'static str = "sms";
// const MMS_COMMAND: &'static str = "mms";
// const GEO_COMMAND: &'static str = "geo";
const PHONE_COMMAND: &'static str = "phone";
// const SKYPE_COMMAND: &'static str = "skype";
const URL_COMMAND: &'static str = "url";
// const BOOKMARK_COMMAND: &'static str = "bookmark";
// const BITCOIN_COMMAND: &'static str = "bitcoin";
// const GIRO_COMMAND: &'static str = "giro";
// const CALENDAR_COMMAND: &'static str = "calendar";

/*TODO: add arguments for:
- ec Level
- size of qr code
- implement different types of qr payloads
*/
fn main() {
    let app = App::new("qrterm")
        .version("0.1")
        .author("Lukas R. <lukas@bootsmann-games.de>")
        .about("Generates and displays terminal friendly QR-Codes from input strings")
        .arg(Arg::with_name("safe_zone") //TODO: change this into an off switch
            .global(true)
            .required(false)
            .short("s")
            .long("safe-zone")
            .help("Sets wether the safe zone around the code should be drawn or not.")
            .takes_value(false)
            )
            //TODO: subcmds are not working like expected, if you have one the system assumes you have many
        .subcommand(SubCommand::with_name(WIFI_COMMAND)
            .about("formats to a wifi access string")
            .arg(Arg::with_name("ssid").required(true))
            .arg(Arg::with_name("pwd").required(true))
            .arg(Arg::with_name("mode")
                .possible_values(&["WEP", "WPA", "nopass"])
                .default_value("WPA")
                .value_name("MODE"))
            .arg(Arg::with_name("hidden")
                .required(false)
                .possible_values(&["true", "false"])
                .default_value("false")
                .value_name("HIDDEN")))
        .subcommand(SubCommand::with_name(MAIL_COMMAND)
            .about("formats to a mail adress string")
            .arg(Arg::with_name("receiver").required(true))
            .arg(Arg::with_name("subject"))
            .arg(Arg::with_name("message"))
            .arg(Arg::with_name("encoding")
                .possible_values(&["MAILTO", "MATMSG", "SMTP"])
                .default_value("MAILTO")
                .value_name("ENCODING")))
        .subcommand(SubCommand::with_name(URL_COMMAND)
            .about("formats to an URL")
            .arg(Arg::with_name("url")
                .required(true)
                .value_name("URL")))
        .subcommand(SubCommand::with_name(PHONE_COMMAND)
            .about("formats to a phone number")
            .arg(Arg::with_name("number")
                .required(true)
                .value_name("NUMBER")))
        .arg(Arg::with_name("INPUT")
            .help("The input string to use")
            .required_unless_one(&[WIFI_COMMAND, MAIL_COMMAND, URL_COMMAND, PHONE_COMMAND]));

    let matches = app.get_matches();

    let payload: String;
    if let Some(sub) = matches.subcommand_matches(WIFI_COMMAND) {
        let auth = match sub.value_of("mode") {
            Some("WEP") => payloads::Authentication::WEP,
            Some("WPA") => payloads::Authentication::WPA,
            _ => payloads::Authentication::nopass,
        };
        payload = payloads::wifi_string(sub.value_of("ssid").unwrap(),
                                        sub.value_of("pwd").unwrap(),
                                        &auth,
                                        sub.value_of("hidden").unwrap() == "true");
    } else if let Some(sub) = matches.subcommand_matches(MAIL_COMMAND) {
        let encoding = match sub.value_of("encoding") {
            Some("MAILTO") => payloads::MailEncoding::MAILTO,
            Some("MATMSG") => payloads::MailEncoding::MATMSG,
            Some("SMTP") => payloads::MailEncoding::SMTP,
            _ => payloads::MailEncoding::MAILTO,
        };
        payload = payloads::mail_string(sub.value_of("receiver").unwrap(),
                                        sub.value_of("subject").unwrap(),
                                        sub.value_of("message").unwrap(),
                                        &encoding);
    } else if let Some(sub) = matches.subcommand_matches(URL_COMMAND) {
        payload = payloads::url_string(sub.value_of("url").unwrap());
    } else if let Some(sub) = matches.subcommand_matches(PHONE_COMMAND) {
        payload = payloads::phone_string(sub.value_of("phone").unwrap());
    } else {
        payload = String::from(matches.value_of("INPUT").unwrap());
    }

    let safe: bool = match matches.occurrences_of("safe_zone") {
        0 => true,
        _ => false,
    };

    let code = QrCode::with_error_correction_level(payload, EcLevel::H).unwrap();

    let bit_array = code.to_colors();

    let w = code.width();
    let wide = w + 6;

    //Draw the first white safe zone
    if safe {
        for a in 1..(wide * 3) + 1 {
            print!("{}  ", color::Bg(color::LightWhite));
            if a % wide == 0 {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }

    for (i, item) in bit_array.iter().enumerate() {
        //left safe zone
        if safe && i % w == 0 {
            print!("{}      ", color::Bg(color::LightWhite));
        }

        if *item == qrcode::types::Color::Dark {
            print!("{}  ", color::Bg(color::Black));
        } else {
            print!("{}  ", color::Bg(color::LightWhite));
        }

        if (i + 1) % w == 0 {
            if safe {
                //draw right safe zone
                println!("{}      {}",
                         color::Bg(color::LightWhite),
                         color::Bg(color::Reset));
            } else {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }

    //Draw the last white safe zone
    if safe {
        for a in 1..(wide * 3) + 1 {
            print!("{}  ", color::Bg(color::LightWhite));
            if a % wide == 0 {
                println!("{}", color::Bg(color::Reset));
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate ansi_term;
extern crate getopts;
extern crate isatty;
extern crate regex;
extern crate walkdir;

use std::collections::HashMap;
use std::env;
use std::error::Error;
use std::ffi::OsStr;
use std::fs::File;
use std::io::{Write, BufReader,BufRead};
use std::path::{Path, Component};
use std::process;

use ansi_term::Colour;
use getopts::Options;
use isatty::stdout_isatty;
use regex::{Regex, RegexBuilder};
use walkdir::{WalkDir, DirEntry, WalkDirIterator};

/// Maps file extensions to ANSI colors / styles.
type ExtensionStyles = HashMap<String, ansi_term::Style>;

/// Configuration options for *fd*.
struct FdOptions {
    case_sensitive: bool,
    search_full_path: bool,
    search_hidden: bool,
    follow_links: bool,
    colored: bool,
    max_depth: usize,
    extension_styles: Option<ExtensionStyles>
}

/// The default maximum recursion depth.
const MAX_DEPTH_DEFAULT : usize = 25;

/// Print a search result to the console.
fn print_entry(path_root: &Path, path_entry: &Path, config: &FdOptions) {
    let path_full = path_root.join(path_entry);

    let path_str = match path_entry.to_str() {
        Some(p) => p,
        None    => return
    };

    if !config.colored {
        println!("{}", path_str);
    } else {
        let mut component_path = path_root.to_path_buf();

        // Traverse the path and colorize each component
        for component in path_entry.components() {
            let comp_str = match component {
                Component::Normal(p) => p,
                _                    => error("Unexpected path component")
            };

            component_path.push(Path::new(comp_str));

            let style =
                if component_path.symlink_metadata()
                                 .map(|md| md.file_type().is_symlink())
                                 .unwrap_or(false) {
                    Colour::Cyan.normal()
                } else if component_path.is_dir() {
                    Colour::Blue.bold()
                } else {
                    // Loop up file extension
                    if let Some(ref ext_styles) = config.extension_styles {
                        component_path.extension()
                                      .and_then(|e| e.to_str())
                                      .and_then(|e| ext_styles.get(e))
                                      .map(|r| r.clone())
                                      .unwrap_or(Colour::White.normal())
                    }
                    else {
                        Colour::White.normal()
                    }
                };

            print!("{}", style.paint(comp_str.to_str().unwrap()));

            if component_path.is_dir() && component_path != path_full {
                let sep = std::path::MAIN_SEPARATOR.to_string();
                print!("{}", style.paint(sep));
            }
        }
        println!();
    }
}

/// Check if filename of entry starts with a dot.
fn is_hidden(entry: &DirEntry) -> bool {
    entry.file_name()
         .to_str()
         .map(|s| s.starts_with("."))
         .unwrap_or(false)
}

/// Recursively scan the given root path and search for files / pathnames
/// matching the pattern.
fn scan(root: &Path, pattern: &Regex, config: &FdOptions) {
    let walker = WalkDir::new(root)
                     .follow_links(config.follow_links)
                     .max_depth(config.max_depth)
                     .into_iter()
                     .filter_entry(|e| config.search_hidden || !is_hidden(e))
                     .filter_map(|e| e.ok())
                     .filter(|e| e.path() != root);

    for entry in walker {
        let path_rel = match entry.path().strip_prefix(root) {
            Ok(p) => p,
            Err(_) => continue
        };

        let search_str =
            if config.search_full_path {
                path_rel.to_str()
            } else {
                if !path_rel.is_file() { continue }

                path_rel.file_name()
                        .and_then(OsStr::to_str)
            };

        search_str.and_then(|s| pattern.find(s))
                  .map(|_| print_entry(&root, path_rel, &config));
    }
}

/// Print error message to stderr and exit with status `1`.
fn error(message: &str) -> ! {
    writeln!(&mut std::io::stderr(), "{}", message)
        .expect("Failed writing to stderr");
    process::exit(1);
}

/// Parse `dircolors` file.
fn parse_dircolors(path: &Path) -> std::io::Result<ExtensionStyles> {
    let file = File::open(path)?;
    let mut ext_styles = HashMap::new();

    let pattern =
        Regex::new(r"^\.([A-Za-z0-9]+)\s*38;5;([0-9]+)\b").unwrap();

    for line in BufReader::new(file).lines() {
        if let Some(caps) = pattern.captures(line.unwrap().as_str()) {
            if let Some(ext) = caps.get(1).map(|m| m.as_str()) {
                let fg = caps.get(2)
                             .map(|m| m.as_str())
                             .and_then(|n| u8::from_str_radix(n, 10).ok())
                             .unwrap_or(7); // white
                ext_styles.insert(String::from(ext),
                                  Colour::Fixed(fg).normal());
            }
        }
    }
    Ok(ext_styles)
}

fn main() {
    let args: Vec<String> = env::args().collect();

    let mut opts = Options::new();
    opts.optflag("h", "help", "print this help message");
    opts.optflag("s", "sensitive",
                      "case-sensitive search (default: smart case)");
    opts.optflag("f", "filename",
                      "search filenames only (default: full path)");
    opts.optflag("H", "hidden",
                      "search hidden files/directories (default: off)");
    opts.optflag("F", "follow", "follow symlinks (default: off)");
    opts.optflag("n", "no-color", "do not colorize output (default: on)");
    opts.optopt("d", "max-depth",
                     format!("maximum search depth (default: {})",
                             MAX_DEPTH_DEFAULT).as_str(),
                     "D");

    let matches = match opts.parse(&args[1..]) {
        Ok(m)  => m,
        Err(e) => error(e.description())
    };

    if matches.opt_present("h") {
        let brief = "Usage: fd [options] [PATTERN]";
        print!("{}", opts.usage(&brief));
        process::exit(1);
    }

    let empty = String::new();
    let pattern = matches.free.get(0).unwrap_or(&empty);

    let current_dir_buf = match env::current_dir() {
        Ok(cd) => cd,
        Err(_) => error("Could not get current directory!")
    };
    let current_dir = current_dir_buf.as_path();

    let ext_styles = env::home_dir()
                         .map(|h| h.join(".dir_colors"))
                         .and_then(|path| parse_dircolors(&path).ok());

    let config = FdOptions {
        // The search will be case-sensitive if the command line flag is set or
        // if the pattern has an uppercase character (smart case).
        case_sensitive:    matches.opt_present("sensitive") ||
                           pattern.chars().any(char::is_uppercase),
        search_full_path: !matches.opt_present("filename"),
        search_hidden:     matches.opt_present("hidden"),
        colored:          !matches.opt_present("no-color") &&
                           stdout_isatty(),
        follow_links:      matches.opt_present("follow"),
        max_depth:
            matches.opt_str("max-depth")
                   .and_then(|ds| usize::from_str_radix(&ds, 10).ok())
                   .unwrap_or(MAX_DEPTH_DEFAULT),
        extension_styles:  ext_styles
    };

    match RegexBuilder::new(pattern)
              .case_insensitive(!config.case_sensitive)
              .build() {
        Ok(re)   => scan(&current_dir, &re, &config),
        Err(err) => error(err.description())
    }
}
<commit_msg>Support for normal ANSI colors<commit_after>extern crate ansi_term;
extern crate getopts;
extern crate isatty;
extern crate regex;
extern crate walkdir;

use std::collections::HashMap;
use std::env;
use std::error::Error;
use std::ffi::OsStr;
use std::fs::File;
use std::io::{Write, BufReader,BufRead};
use std::path::{Path, Component};
use std::process;

use ansi_term::{Style, Colour};
use getopts::Options;
use isatty::stdout_isatty;
use regex::{Regex, RegexBuilder};
use walkdir::{WalkDir, DirEntry, WalkDirIterator};

/// Maps file extensions to ANSI colors / styles.
type ExtensionStyles = HashMap<String, ansi_term::Style>;

/// Configuration options for *fd*.
struct FdOptions {
    case_sensitive: bool,
    search_full_path: bool,
    search_hidden: bool,
    follow_links: bool,
    colored: bool,
    max_depth: usize,
    extension_styles: Option<ExtensionStyles>
}

/// The default maximum recursion depth.
const MAX_DEPTH_DEFAULT : usize = 25;

/// Print a search result to the console.
fn print_entry(path_root: &Path, path_entry: &Path, config: &FdOptions) {
    let path_full = path_root.join(path_entry);

    let path_str = match path_entry.to_str() {
        Some(p) => p,
        None    => return
    };

    if !config.colored {
        println!("{}", path_str);
    } else {
        let mut component_path = path_root.to_path_buf();

        // Traverse the path and colorize each component
        for component in path_entry.components() {
            let comp_str = match component {
                Component::Normal(p) => p,
                _                    => error("Unexpected path component")
            };

            component_path.push(Path::new(comp_str));

            let style =
                if component_path.symlink_metadata()
                                 .map(|md| md.file_type().is_symlink())
                                 .unwrap_or(false) {
                    Colour::Cyan.normal()
                } else if component_path.is_dir() {
                    Colour::Blue.bold()
                } else {
                    // Loop up file extension
                    if let Some(ref ext_styles) = config.extension_styles {
                        component_path.extension()
                                      .and_then(|e| e.to_str())
                                      .and_then(|e| ext_styles.get(e))
                                      .map(|r| r.clone())
                                      .unwrap_or(Style::new())
                    }
                    else {
                        Style::new()
                    }
                };

            print!("{}", style.paint(comp_str.to_str().unwrap()));

            if component_path.is_dir() && component_path != path_full {
                let sep = std::path::MAIN_SEPARATOR.to_string();
                print!("{}", style.paint(sep));
            }
        }
        println!();
    }
}

/// Check if filename of entry starts with a dot.
fn is_hidden(entry: &DirEntry) -> bool {
    entry.file_name()
         .to_str()
         .map(|s| s.starts_with("."))
         .unwrap_or(false)
}

/// Recursively scan the given root path and search for files / pathnames
/// matching the pattern.
fn scan(root: &Path, pattern: &Regex, config: &FdOptions) {
    let walker = WalkDir::new(root)
                     .follow_links(config.follow_links)
                     .max_depth(config.max_depth)
                     .into_iter()
                     .filter_entry(|e| config.search_hidden || !is_hidden(e))
                     .filter_map(|e| e.ok())
                     .filter(|e| e.path() != root);

    for entry in walker {
        let path_rel = match entry.path().strip_prefix(root) {
            Ok(p) => p,
            Err(_) => continue
        };

        let search_str =
            if config.search_full_path {
                path_rel.to_str()
            } else {
                if !path_rel.is_file() { continue }

                path_rel.file_name()
                        .and_then(OsStr::to_str)
            };

        search_str.and_then(|s| pattern.find(s))
                  .map(|_| print_entry(&root, path_rel, &config));
    }
}

/// Print error message to stderr and exit with status `1`.
fn error(message: &str) -> ! {
    writeln!(&mut std::io::stderr(), "{}", message)
        .expect("Failed writing to stderr");
    process::exit(1);
}

/// Parse `dircolors` file.
fn parse_dircolors(path: &Path) -> std::io::Result<ExtensionStyles> {
    let file = File::open(path)?;
    let mut ext_styles = HashMap::new();

    let pattern_ansi_256 =
        Regex::new(r"^\.([A-Za-z0-9]+)\s*(?:00;)?38;5;([0-9]+)\b")
            .unwrap();

    let pattern_ansi =
        Regex::new(r"^\.([A-Za-z0-9]+)\s*([0-9][0-9]);([0-9][0-9])\b")
            .unwrap();

    for line in BufReader::new(file).lines() {
        let line_s = line.unwrap();
        if let Some(caps) = pattern_ansi_256.captures(line_s.as_str()) {
            if let Some(ext) = caps.get(1).map(|m| m.as_str()) {
                let fg = caps.get(2)
                             .map(|m| m.as_str())
                             .and_then(|n| u8::from_str_radix(n, 10).ok())
                             .unwrap_or(7); // white
                ext_styles.insert(String::from(ext),
                                  Colour::Fixed(fg).normal());
            }
        } else if let Some(caps) = pattern_ansi.captures(line_s.as_str()) {
            if let Some(ext) = caps.get(1).map(|m| m.as_str()) {
                let color_s = caps.get(3)
                                  .map_or("", |m| m.as_str());
                let color = match color_s {
                    "31" => Colour::Red,
                    "32" => Colour::Green,
                    "33" => Colour::Yellow,
                    "34" => Colour::Blue,
                    "35" => Colour::Purple,
                    "36" => Colour::Cyan,
                    _    => Colour::White
                };
                let style_s = caps.get(2)
                                  .map_or("", |m| m.as_str());
                let style = match style_s {
                    "01" => color.bold(),
                    "03" => color.italic(),
                    "04" => color.underline(),
                    _    => color.normal()
                };
                ext_styles.insert(String::from(ext), style);
            }
        }
    }
    Ok(ext_styles)
}

fn main() {
    let args: Vec<String> = env::args().collect();

    let mut opts = Options::new();
    opts.optflag("h", "help", "print this help message");
    opts.optflag("s", "sensitive",
                      "case-sensitive search (default: smart case)");
    opts.optflag("f", "filename",
                      "search filenames only (default: full path)");
    opts.optflag("H", "hidden",
                      "search hidden files/directories (default: off)");
    opts.optflag("F", "follow", "follow symlinks (default: off)");
    opts.optflag("n", "no-color", "do not colorize output (default: on)");
    opts.optopt("d", "max-depth",
                     format!("maximum search depth (default: {})",
                             MAX_DEPTH_DEFAULT).as_str(),
                     "D");

    let matches = match opts.parse(&args[1..]) {
        Ok(m)  => m,
        Err(e) => error(e.description())
    };

    if matches.opt_present("h") {
        let brief = "Usage: fd [options] [PATTERN]";
        print!("{}", opts.usage(&brief));
        process::exit(1);
    }

    let empty = String::new();
    let pattern = matches.free.get(0).unwrap_or(&empty);

    let current_dir_buf = match env::current_dir() {
        Ok(cd) => cd,
        Err(_) => error("Could not get current directory!")
    };
    let current_dir = current_dir_buf.as_path();

    let ext_styles = env::home_dir()
                         .map(|h| h.join(".dir_colors"))
                         .and_then(|path| parse_dircolors(&path).ok());

    let config = FdOptions {
        // The search will be case-sensitive if the command line flag is set or
        // if the pattern has an uppercase character (smart case).
        case_sensitive:    matches.opt_present("sensitive") ||
                           pattern.chars().any(char::is_uppercase),
        search_full_path: !matches.opt_present("filename"),
        search_hidden:     matches.opt_present("hidden"),
        colored:          !matches.opt_present("no-color") &&
                           stdout_isatty(),
        follow_links:      matches.opt_present("follow"),
        max_depth:
            matches.opt_str("max-depth")
                   .and_then(|ds| usize::from_str_radix(&ds, 10).ok())
                   .unwrap_or(MAX_DEPTH_DEFAULT),
        extension_styles:  ext_styles
    };

    match RegexBuilder::new(pattern)
              .case_insensitive(!config.case_sensitive)
              .build() {
        Ok(re)   => scan(&current_dir, &re, &config),
        Err(err) => error(err.description())
    }
}
<|endoftext|>


<commit_before>use address::{Address, Addressable};
use messages;
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket, IpAddr, Ipv4Addr};
use std::collections::HashMap;
use std::cmp;
use time;
use transaction::TransactionId;

/// The maximum number of queries sent without a response before a node is considered bad.
pub const FAILED_TO_RESPOND_THRESHOLD: usize = 5;

/// A node becomes questionable if it hasn't been heard from in this many minutes.
pub const MINUTES_UNTIL_QUESTIONABLE: i64 = 15;

/// Deserialize a `Node` from a protobuf.
pub fn deserialize(message: &messages::protobufs::Node) -> Node {
    let ip = message.get_ip_address();
    let ip = Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]);
    let port = message.get_port() as u16;
    let address = Address::from_str(message.get_id()).unwrap();
    Node::from_socket_addrs(address, (ip, port)).unwrap()
}

/// Anything that needs to be serialized for transfer or storage.
///
/// TODO: this and `deserialize` should probably both be a part of a `Serializable` trait so that
/// other types can impl it instead of the `incoming` and `outgoing` functions in `messages`.
pub trait Serialize {
    fn serialize(&self) -> messages::protobufs::Node;
}

#[derive(Debug, PartialEq)]
pub enum Status {
    Good,
    Questionable,
    Bad
}

/// A `Node` is a peer in the network. It represents another network participant such as ourself.
/// It has an address, and a means to be sent messages. When we receive messages, they come from
/// other nodes.
///
/// Currently, a node is connected via UDP socket, but in a future iteration, a Node will be
/// decoupled from the underlying connection method. A Node semantically represents a
/// "participant," i.e. a person, robot, agent, etc. Not a single device, or single IP address.
///
/// That participant may be connected to the network via a variety of means. Most common would be
/// over the internet via UDP, but it could very well include more connections via LAN, Bluetooth,
/// shortwave radio, signal lamp, or any other medium that can transmit packets.
///
/// This in an important feature to the goals of comm. The comm network should be able to overlay
/// partitioned networks. If a subnetwork is connected via Bluetooth, and at least one participant
/// has a connection to the larger network, all participants are thereby connected to the larger
/// network.
#[derive(Debug)]
pub struct Node {
    address: Address,
    socket_address: SocketAddr,
    pending_queries: HashMap<TransactionId, time::Tm>,
    has_ever_responded: bool,
    last_received_query: time::Tm,
    last_received_response: time::Tm,
}

impl Node {
    pub fn from_socket_addrs<S: ToSocketAddrs>(address: Address, socket_address: S) -> Result<Node, String> {
        match socket_address.to_socket_addrs().ok().and_then(|mut addrs| addrs.next()) {
            Some(s) => {
                Ok(Node {
                    address: address,
                    socket_address: s,
                    pending_queries: HashMap::new(),
                    has_ever_responded: false,
                    last_received_query: time::now_utc(),
                    last_received_response: time::now_utc()
                })
            }

            None => {
                Err(String::from("Couldn't parse socket address"))
            }
        }
    }

    fn status(&self) -> Status {
        let time_since_last_seen = time::now_utc() - self.last_seen();

        if self.has_ever_responded &&
            time_since_last_seen < time::Duration::minutes(MINUTES_UNTIL_QUESTIONABLE) {
            Status::Good
        } else if self.pending_query_count() < FAILED_TO_RESPOND_THRESHOLD {
            Status::Questionable
        } else {
            Status::Bad
        }
    }

    /// Whether the node should be considered bad or unreliable. A bad node has not been heard from
    /// in the last `MINUTES_UNTIL_QUESTIONABLE` minutes, and hasn't responded to at least
    /// `FAILED_TO_RESPOND_THRESHOLD` queries.
    ///
    /// Generally, a bad node SHOULD NOT be sent queries, since it's likely to be a waste of
    /// network traffic. However, the node should not forgotten until its bucket is full, cannot be
    /// split, and a new node is being inserted into it. At that point, it's advantageous to remove
    /// the worst node from the bucket and insert another in its place.
    ///
    /// If a bad node begins responding to queries, it can become good again. The goal is to
    /// minimize wasted network traffic, but also to minimize network volatility. Repeatedly
    /// ejecting and reintroducing flaky nodes makes for a volatile network.
    ///
    /// TODO: Should we forgive a bad node's `pending_query_count()` if it becomes good again?
    pub fn is_bad(&self) -> bool {
        self.status() == Status::Bad
    }

    /// Whether the node is questionable and should therefore be pinged. A questionable node SHOULD
    /// still be sent relevant queries, and SHOULD be given every benefit of being treated as if it
    /// were good. Questionable only means that we don't know whether it's still good, and we
    /// should ask it.
    pub fn is_questionable(&self) -> bool {
        self.status() == Status::Questionable
    }

    /// The last time we received either a query or a response from a node.
    pub fn last_seen(&self) -> time::Tm {
        cmp::max(self.last_received_query, self.last_received_response)
    }

    /// How many unanswered queries we've sent to a node.
    pub fn pending_query_count(&self) -> usize {
        self.pending_queries.len()
    }

    /// Update the `last_received_query` timestamp for a node. Any time the network receives a
    /// query from a node, this method should be called, passing in the query's `TransactionId`.
    ///
    /// The TID is currently unused, but may be useful in the future.
    pub fn received_query(&mut self, _: TransactionId) {
        self.last_received_query = time::now_utc();
    }

    /// Update the `last_received_response` timestamp if we're indeed waiting for a response to
    /// a query we previously sent with a TID of `transaction_id`.
    ///
    /// If we're not expecting a response from this node for a query we sent previously, this
    /// method call is ignored and the timestamp is left as is.
    pub fn received_response(&mut self, transaction_id: TransactionId) {
        self.last_received_response = time::now_utc();
        if let Some(_queried_at) = self.pending_queries.remove(&transaction_id) {
            self.has_ever_responded = true;
            //let time_to_respond = time::now_utc() - queried_at;
            //debug!("{} took {:?} to respond", transaction_id, time_to_respond);
        } else {
            debug!("{:?} was not expecting response to {}", self.address, transaction_id);
            debug!("pending queries: {:?}", self.pending_queries.len());
        }
    }

    /// Send an encoded message to a node via its UDP socket.
    ///
    /// In the future, a node will support numerous connection types, and it should be send using
    /// all connections that are live (i.e. not bad)
    pub fn send(&self, message: Vec<u8>) {
        let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
        socket.send_to(&message[..], self.socket_address).unwrap();
    }

    /// Records that we're expecting a response from this node for the TID `transaction_id`.
    ///
    /// TODO: Perhaps this method should be rolled together with a method like `send_query` that
    /// records the TID and calls `send`.
    pub fn sent_query(&mut self, transaction_id: TransactionId) {
        self.pending_queries.insert(transaction_id, time::now_utc());
    }

    /// Update the socket address and port of a node. This is useful for when a node disconnects
    /// and reconnects to the internet, or changes IP addresses, etc.
    ///
    /// In the future, a node will have n connections instead of one socket address, and we'd just
    /// add another to the set, and keep track of which are good, eventually ejecting dead
    /// connections.
    ///
    /// TODO: this is a temporary measure until a node can support multiple connections. Rather
    /// than updating its only connection, it should just add another to the set and keep track of
    /// the most reliable connection.
    pub fn update_connection(&mut self, other_node: Self) {
        self.socket_address = other_node.socket_address;
    }
}

impl PartialEq for Node {
    fn eq(&self, other: &Self) -> bool {
        self.address() == other.address()
    }
}

impl Serialize for Node {
    fn serialize(&self) -> messages::protobufs::Node {
        let mut message = messages::protobufs::Node::new();
        message.set_id(self.address.to_str());
        match self.socket_address.ip() {
            IpAddr::V4(ipv4_addr) => {
                message.set_ip_address(ipv4_addr.octets().iter().cloned().collect());
            }
            IpAddr::V6(_) => {
                // TODO ipv6 node support
            }
        }
        message.set_port(self.socket_address.port() as u32);
        message
    }
}

impl Addressable for Node {
    fn address(&self) -> Address {
        self.address
    }
}

#[cfg(test)]
pub mod tests {
    use address::Address;
    use std::collections::HashMap;
    use std::net::ToSocketAddrs;
    use super::{FAILED_TO_RESPOND_THRESHOLD, MINUTES_UNTIL_QUESTIONABLE, Node, Serialize};
    use time;
    use transaction::TransactionId;

    pub fn new(address: Address, last_received_response: time::Tm, pending_queries: HashMap<TransactionId, time::Tm>) -> Node {
        use rand::{thread_rng, Rng};
        let port = thread_rng().gen_range(1000, 10000);
        Node {
            address: address,
            socket_address: ("0.0.0.0", port).to_socket_addrs().unwrap().next().unwrap(),
            pending_queries: pending_queries,
            has_ever_responded: false,
            last_received_query: time::empty_tm(),
            last_received_response: last_received_response
        }
    }

    pub fn good(address: Address) -> Node {
        new(address, time::now_utc(), HashMap::new())
    }

    pub fn questionable(address: Address) -> Node {
        let last_received_response = time::now_utc() -
            time::Duration::minutes(MINUTES_UNTIL_QUESTIONABLE);

        new(address, last_received_response, HashMap::new())
    }

    pub fn bad(address: Address) -> Node {
        let last_received_response = time::now_utc() -
            time::Duration::minutes(MINUTES_UNTIL_QUESTIONABLE + 1);
        let mut pending_queries = HashMap::new();
        let n_queries = FAILED_TO_RESPOND_THRESHOLD + 1;
        for i in 0..n_queries {
            pending_queries.insert(i as TransactionId, time::now_utc());
        }

        new(address, last_received_response, pending_queries)
    }

    #[test]
    fn test_received_response() {
        let address = Address::for_content("some string");
        let mut node = Node::from_socket_addrs(address, ("0.0.0.0", 9000)).unwrap();

        // When it's not expecting the response
        node.received_response(1);
        assert!(!node.has_ever_responded);

        // When it's expecting the response
        let last_seen_before = node.last_seen();
        let transaction_id = 2;
        node.sent_query(transaction_id);
        node.received_response(transaction_id);
        let last_seen_after = node.last_seen();
        assert!(last_seen_before < last_seen_after);
        assert!(node.has_ever_responded);
    }

    #[test]
    fn test_serialize() {
        use messages;
        let mut protobuf = messages::protobufs::Node::new();
        protobuf.set_id("8b45e4bd1c6acb88bebf6407d16205f567e62a3e".to_string());
        protobuf.set_ip_address(vec![192, 168, 1, 2]);
        protobuf.set_port(9000);
        let address = Address::for_content("some string");
        let node = Node::from_socket_addrs(address, ("192.168.1.2", 9000)).unwrap();
        assert_eq!(node.serialize(), protobuf);
    }
}
<commit_msg>Add better logging to Node<commit_after>use address::{Address, Addressable};
use messages;
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket, IpAddr, Ipv4Addr};
use std::collections::HashMap;
use std::cmp;
use time;
use transaction::TransactionId;

/// The maximum number of queries sent without a response before a node is considered bad.
pub const FAILED_TO_RESPOND_THRESHOLD: usize = 5;

/// A node becomes questionable if it hasn't been heard from in this many minutes.
pub const MINUTES_UNTIL_QUESTIONABLE: i64 = 15;

/// Deserialize a `Node` from a protobuf.
pub fn deserialize(message: &messages::protobufs::Node) -> Node {
    let ip = message.get_ip_address();
    let ip = Ipv4Addr::new(ip[0], ip[1], ip[2], ip[3]);
    let port = message.get_port() as u16;
    let address = Address::from_str(message.get_id()).unwrap();
    Node::from_socket_addrs(address, (ip, port)).unwrap()
}

/// Anything that needs to be serialized for transfer or storage.
///
/// TODO: this and `deserialize` should probably both be a part of a `Serializable` trait so that
/// other types can impl it instead of the `incoming` and `outgoing` functions in `messages`.
pub trait Serialize {
    fn serialize(&self) -> messages::protobufs::Node;
}

#[derive(Debug, PartialEq)]
pub enum Status {
    Good,
    Questionable,
    Bad
}

/// A `Node` is a peer in the network. It represents another network participant such as ourself.
/// It has an address, and a means to be sent messages. When we receive messages, they come from
/// other nodes.
///
/// Currently, a node is connected via UDP socket, but in a future iteration, a Node will be
/// decoupled from the underlying connection method. A Node semantically represents a
/// "participant," i.e. a person, robot, agent, etc. Not a single device, or single IP address.
///
/// That participant may be connected to the network via a variety of means. Most common would be
/// over the internet via UDP, but it could very well include more connections via LAN, Bluetooth,
/// shortwave radio, signal lamp, or any other medium that can transmit packets.
///
/// This in an important feature to the goals of comm. The comm network should be able to overlay
/// partitioned networks. If a subnetwork is connected via Bluetooth, and at least one participant
/// has a connection to the larger network, all participants are thereby connected to the larger
/// network.
#[derive(Debug)]
pub struct Node {
    address: Address,
    socket_address: SocketAddr,
    pending_queries: HashMap<TransactionId, time::Tm>,
    has_ever_responded: bool,
    last_received_query: time::Tm,
    last_received_response: time::Tm,
}

impl Node {
    pub fn from_socket_addrs<S: ToSocketAddrs>(address: Address, socket_address: S) -> Result<Node, String> {
        match socket_address.to_socket_addrs().ok().and_then(|mut addrs| addrs.next()) {
            Some(s) => {
                Ok(Node {
                    address: address,
                    socket_address: s,
                    pending_queries: HashMap::new(),
                    has_ever_responded: false,
                    last_received_query: time::now_utc(),
                    last_received_response: time::now_utc()
                })
            }

            None => {
                Err(String::from("Couldn't parse socket address"))
            }
        }
    }

    fn status(&self) -> Status {
        let time_since_last_seen = time::now_utc() - self.last_seen();

        if self.has_ever_responded &&
            time_since_last_seen < time::Duration::minutes(MINUTES_UNTIL_QUESTIONABLE) {
            Status::Good
        } else if self.pending_query_count() < FAILED_TO_RESPOND_THRESHOLD {
            Status::Questionable
        } else {
            Status::Bad
        }
    }

    /// Whether the node should be considered bad or unreliable. A bad node has not been heard from
    /// in the last `MINUTES_UNTIL_QUESTIONABLE` minutes, and hasn't responded to at least
    /// `FAILED_TO_RESPOND_THRESHOLD` queries.
    ///
    /// Generally, a bad node SHOULD NOT be sent queries, since it's likely to be a waste of
    /// network traffic. However, the node should not forgotten until its bucket is full, cannot be
    /// split, and a new node is being inserted into it. At that point, it's advantageous to remove
    /// the worst node from the bucket and insert another in its place.
    ///
    /// If a bad node begins responding to queries, it can become good again. The goal is to
    /// minimize wasted network traffic, but also to minimize network volatility. Repeatedly
    /// ejecting and reintroducing flaky nodes makes for a volatile network.
    ///
    /// TODO: Should we forgive a bad node's `pending_query_count()` if it becomes good again?
    pub fn is_bad(&self) -> bool {
        self.status() == Status::Bad
    }

    /// Whether the node is questionable and should therefore be pinged. A questionable node SHOULD
    /// still be sent relevant queries, and SHOULD be given every benefit of being treated as if it
    /// were good. Questionable only means that we don't know whether it's still good, and we
    /// should ask it.
    pub fn is_questionable(&self) -> bool {
        self.status() == Status::Questionable
    }

    /// The last time we received either a query or a response from a node.
    pub fn last_seen(&self) -> time::Tm {
        cmp::max(self.last_received_query, self.last_received_response)
    }

    /// How many unanswered queries we've sent to a node.
    pub fn pending_query_count(&self) -> usize {
        self.pending_queries.len()
    }

    /// Update the `last_received_query` timestamp for a node. Any time the network receives a
    /// query from a node, this method should be called, passing in the query's `TransactionId`.
    ///
    /// The TID is currently unused, but may be useful in the future.
    pub fn received_query(&mut self, transaction_id: TransactionId) {
        self.last_received_query = time::now_utc();
        debug!("Received query {} from {:?}", &transaction_id, &self);
    }

    /// Update the `last_received_response` timestamp if we're indeed waiting for a response to
    /// a query we previously sent with a TID of `transaction_id`.
    ///
    /// If we're not expecting a response from this node for a query we sent previously, this
    /// method call is ignored and the timestamp is left as is.
    pub fn received_response(&mut self, transaction_id: TransactionId) {
        self.last_received_response = time::now_utc();
        if let Some(queried_at) = self.pending_queries.remove(&transaction_id) {
            self.has_ever_responded = true;
            debug!("Receivd response from {:?} for transaction {} in {}ms",
                   &self, &transaction_id, time::now_utc() - queried_at);
        } else {
            debug!("Received unexpected response from {:?} for transaction {}",
                   &self, transaction_id);
            debug!("  pending queries: {:?}", self.pending_queries.len());
        }
    }

    /// Send an encoded message to a node via its UDP socket.
    ///
    /// In the future, a node will support numerous connection types, and it should be send using
    /// all connections that are live (i.e. not bad)
    pub fn send(&self, message: Vec<u8>) {
        let socket = UdpSocket::bind("0.0.0.0:0").unwrap();
        socket.send_to(&message[..], self.socket_address).unwrap();
    }

    /// Records that we're expecting a response from this node for the TID `transaction_id`.
    ///
    /// TODO: Perhaps this method should be rolled together with a method like `send_query` that
    /// records the TID and calls `send`.
    pub fn sent_query(&mut self, transaction_id: TransactionId) {
        self.pending_queries.insert(transaction_id, time::now_utc());
    }

    /// Update the socket address and port of a node. This is useful for when a node disconnects
    /// and reconnects to the internet, or changes IP addresses, etc.
    ///
    /// In the future, a node will have n connections instead of one socket address, and we'd just
    /// add another to the set, and keep track of which are good, eventually ejecting dead
    /// connections.
    ///
    /// TODO: this is a temporary measure until a node can support multiple connections. Rather
    /// than updating its only connection, it should just add another to the set and keep track of
    /// the most reliable connection.
    pub fn update_connection(&mut self, other_node: Self) {
        self.socket_address = other_node.socket_address;
    }
}

impl PartialEq for Node {
    fn eq(&self, other: &Self) -> bool {
        self.address() == other.address()
    }
}

impl Serialize for Node {
    fn serialize(&self) -> messages::protobufs::Node {
        let mut message = messages::protobufs::Node::new();
        message.set_id(self.address.to_str());
        match self.socket_address.ip() {
            IpAddr::V4(ipv4_addr) => {
                message.set_ip_address(ipv4_addr.octets().iter().cloned().collect());
            }
            IpAddr::V6(_) => {
                // TODO ipv6 node support
            }
        }
        message.set_port(self.socket_address.port() as u32);
        message
    }
}

impl Addressable for Node {
    fn address(&self) -> Address {
        self.address
    }
}

#[cfg(test)]
pub mod tests {
    use address::Address;
    use std::collections::HashMap;
    use std::net::ToSocketAddrs;
    use super::{FAILED_TO_RESPOND_THRESHOLD, MINUTES_UNTIL_QUESTIONABLE, Node, Serialize};
    use time;
    use transaction::TransactionId;

    pub fn new(address: Address, last_received_response: time::Tm, pending_queries: HashMap<TransactionId, time::Tm>) -> Node {
        use rand::{thread_rng, Rng};
        let port = thread_rng().gen_range(1000, 10000);
        Node {
            address: address,
            socket_address: ("0.0.0.0", port).to_socket_addrs().unwrap().next().unwrap(),
            pending_queries: pending_queries,
            has_ever_responded: false,
            last_received_query: time::empty_tm(),
            last_received_response: last_received_response
        }
    }

    pub fn good(address: Address) -> Node {
        new(address, time::now_utc(), HashMap::new())
    }

    pub fn questionable(address: Address) -> Node {
        let last_received_response = time::now_utc() -
            time::Duration::minutes(MINUTES_UNTIL_QUESTIONABLE);

        new(address, last_received_response, HashMap::new())
    }

    pub fn bad(address: Address) -> Node {
        let last_received_response = time::now_utc() -
            time::Duration::minutes(MINUTES_UNTIL_QUESTIONABLE + 1);
        let mut pending_queries = HashMap::new();
        let n_queries = FAILED_TO_RESPOND_THRESHOLD + 1;
        for i in 0..n_queries {
            pending_queries.insert(i as TransactionId, time::now_utc());
        }

        new(address, last_received_response, pending_queries)
    }

    #[test]
    fn test_received_response() {
        let address = Address::for_content("some string");
        let mut node = Node::from_socket_addrs(address, ("0.0.0.0", 9000)).unwrap();

        // When it's not expecting the response
        node.received_response(1);
        assert!(!node.has_ever_responded);

        // When it's expecting the response
        let last_seen_before = node.last_seen();
        let transaction_id = 2;
        node.sent_query(transaction_id);
        node.received_response(transaction_id);
        let last_seen_after = node.last_seen();
        assert!(last_seen_before < last_seen_after);
        assert!(node.has_ever_responded);
    }

    #[test]
    fn test_serialize() {
        use messages;
        let mut protobuf = messages::protobufs::Node::new();
        protobuf.set_id("8b45e4bd1c6acb88bebf6407d16205f567e62a3e".to_string());
        protobuf.set_ip_address(vec![192, 168, 1, 2]);
        protobuf.set_port(9000);
        let address = Address::for_content("some string");
        let node = Node::from_socket_addrs(address, ("192.168.1.2", 9000)).unwrap();
        assert_eq!(node.serialize(), protobuf);
    }
}
<|endoftext|>


<commit_before>// xfail-test

use std::cast::transmute;
use std::from_str::FromStr;
use std::libc::{STDOUT_FILENO, c_char, c_int, c_uint, c_void, fdopen, fputc};
use std::libc::{fputs};
use std::ptr::null;

struct mpz_t {
    _mp_alloc: c_int,
    _mp_size: c_int,
    _mp_limb_t: *c_void,
}

impl mpz_t {
    fn new() -> mpz_t {
        mpz_t {
            _mp_alloc: 0,
            _mp_size: 0,
            _mp_limb_t: null(),
        }
    }
}

#[link_args="-lgmp"]
extern {
    #[link_name="__gmpz_add"]
    fn mpz_add(x: *mpz_t, y: *mpz_t, z: *mpz_t);
    #[link_name="__gmpz_cmp"]
    fn mpz_cmp(x: *mpz_t, y: *mpz_t) -> c_int;
    #[link_name="__gmpz_fdiv_qr"]
    fn mpz_fdiv_qr(a: *mpz_t, b: *mpz_t, c: *mpz_t, d: *mpz_t);
    #[link_name="__gmpz_get_ui"]
    fn mpz_get_ui(x: *mpz_t) -> c_uint;
    #[link_name="__gmpz_init"]
    fn mpz_init(x: *mpz_t);
    #[link_name="__gmpz_init_set_ui"]
    fn mpz_init_set_ui(x: *mpz_t, y: c_uint);
    #[link_name="__gmpz_mul_2exp"]
    fn mpz_mul_2exp(x: *mpz_t, y: *mpz_t, z: c_uint);
    #[link_name="__gmpz_mul_ui"]
    fn mpz_mul_ui(x: *mpz_t, y: *mpz_t, z: c_uint);
    #[link_name="__gmpz_submul_ui"]
    fn mpz_submul_ui(x: *mpz_t, y: *mpz_t, z: c_uint);
}

struct Context {
    numer: mpz_t,
    accum: mpz_t,
    denom: mpz_t,
    tmp1: mpz_t,
    tmp2: mpz_t,
}

impl Context {
    fn new() -> Context {
        unsafe {
            let mut result = Context {
                numer: mpz_t::new(),
                accum: mpz_t::new(),
                denom: mpz_t::new(),
                tmp1: mpz_t::new(),
                tmp2: mpz_t::new(),
            };
            mpz_init(&result.tmp1);
            mpz_init(&result.tmp2);
            mpz_init_set_ui(&result.numer, 1);
            mpz_init_set_ui(&result.accum, 0);
            mpz_init_set_ui(&result.denom, 1);
            result
        }
    }

    fn extract_digit(&mut self) -> i32 {
        unsafe {
            if mpz_cmp(&self.numer, &self.accum) > 0 {
                return -1;
            }

            // Compute (numer * 3 + accum) / denom
            mpz_mul_2exp(&self.tmp1, &self.numer, 1);
            mpz_add(&self.tmp1, &self.tmp1, &self.numer);
            mpz_add(&self.tmp1, &self.tmp1, &self.accum);
            mpz_fdiv_qr(&self.tmp1, &self.tmp2, &self.tmp1, &self.denom);

            // Now, if (numer * 4 + accum) % denom...
            mpz_add(&self.tmp2, &self.tmp2, &self.numer);

            // ... is normalized, then the two divisions have the same result.
            if mpz_cmp(&self.tmp2, &self.denom) >= 0 {
                return -1;
            }

            mpz_get_ui(&self.tmp1) as i32
        }
    }

    fn next_term(&mut self, k: u32) {
        unsafe {
            let y2 = k*2 + 1;

            mpz_mul_2exp(&self.tmp1, &self.numer, 1);
            mpz_add(&self.accum, &self.accum, &self.tmp1);
            mpz_mul_ui(&self.accum, &self.accum, y2);
            mpz_mul_ui(&self.numer, &self.numer, k);
            mpz_mul_ui(&self.denom, &self.denom, y2);
        }
    }

    fn eliminate_digit(&mut self, d: u32) {
        unsafe {
            mpz_submul_ui(&self.accum, &self.denom, d);
            mpz_mul_ui(&self.accum, &self.accum, 10);
            mpz_mul_ui(&self.numer, &self.numer, 10);
        }
    }
}

fn pidigits(n: u32) {
    unsafe {
        let mode = "w";
        let stdout = fdopen(STDOUT_FILENO as c_int, transmute(&mode[0]));

        let mut d: i32;
        let mut i: u32 = 0, k: u32 = 0, m: u32;

        let mut context = Context::new();
        loop {
            loop {
                k += 1;
                context.next_term(k);
                d = context.extract_digit();
                if d != -1 {
                    break;
                }
            }

            fputc((d as c_int) + ('0' as c_int), stdout);

            i += 1;
            m = i % 10;
            if m == 0 {
                let res = fmt!("\t:%d\n", i as int);
                fputs(transmute(&res[0]), stdout);
            }
            if i >= n {
                break;
            }
            context.eliminate_digit(d as u32);
        }

        if m != 0 {
            m = 10 - m;
            while m != 0 {
                m -= 1;
                fputc(' ' as c_int, stdout);
            }
            let res = fmt!("\t:%d\n", i as int);
            fputs(transmute(&res[0]), stdout);
        }
    }
}

fn main() {
    let n: u32 = FromStr::from_str(os::args()[1]).get();
    pidigits(n);
}
<commit_msg>pidigits resurected<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

extern mod extra;

use std::from_str::FromStr;
use std::num::One;
use std::num::Zero;
use std::num::FromPrimitive;
use extra::bigint::BigInt;

struct Context {
    numer: BigInt,
    accum: BigInt,
    denom: BigInt,
}

impl Context {
    fn new() -> Context {
        Context {
            numer: One::one(),
            accum: Zero::zero(),
            denom: One::one(),
        }
    }

    fn from_int(i: int) -> BigInt {
        FromPrimitive::from_int(i).unwrap()
    }

    fn extract_digit(&self) -> int {
        if self.numer > self.accum {return -1;}
        let (q, r) =
            (self.numer * Context::from_int(3) + self.accum)
            .div_rem(&self.denom);
        if r + self.numer >= self.denom {return -1;}
        q.to_int().unwrap()
    }

    fn next_term(&mut self, k: int) {
        let y2 = Context::from_int(k * 2 + 1);
        self.accum = (self.accum + (self.numer << 1)) * y2;
        self.numer = self.numer * Context::from_int(k);
        self.denom = self.denom * y2;
    }

    fn eliminate_digit(&mut self, d: int) {
        let d = Context::from_int(d);
        let ten = Context::from_int(10);
        self.accum = (self.accum - self.denom * d) * ten;
        self.numer = self.numer * ten;
    }
}

fn pidigits(n: int) {
    let mut k = 0;
    let mut context = Context::new();

    for i in range(1, n + 1) {
        let mut d;
        loop {
            k += 1;
            context.next_term(k);
            d = context.extract_digit();
            if d != -1 {break;}
        }

        print!("{}", d);
        if i % 10 == 0 {print!("\t:{}\n", i);}

        context.eliminate_digit(d);
    }

    let m = n % 10;
    if m != 0 {
        for _ in range(m, 10) {print(" ");}
        print!("\t:{}\n", n);
    }
}

fn main() {
    let args = std::os::args();
    let n = if args.len() < 2 {
        512
    } else {
        FromStr::from_str(args[1]).unwrap()
    };
    pidigits(n);
}
<|endoftext|>


<commit_before>extern crate csv;
extern crate prettytable;
extern crate regex;
extern crate rustyline;
extern crate sqlite3;

use std::env;

fn _normalize_col(col: &String) -> String {
    let re = regex::Regex::new(r"\(.*?\)").unwrap();
    return re.replace_all(col, "")
        .to_lowercase()
        .trim()
        .replace(" ", "_")
        .replace(".", "_")
        .replace("?", "");
}

fn _create_table(db: &mut sqlite3::DatabaseConnection, table_name: &str, cols: &Vec<String>) {
    let create_columns =
        cols.iter().map(|c| format!("{} varchar", c)).collect::<Vec<String>>().join(", ");
    db.exec(&format!("CREATE TABLE {} ({})", table_name, create_columns)).unwrap();
}

fn _insert_row(db: &mut sqlite3::DatabaseConnection,
               table_name: &str,
               row: Vec<String>,
               cols: &Vec<String>) {
    let placeholders = cols.iter()
        .enumerate()
        .map(|(idx, _)| format!("${}", idx + 1))
        .collect::<Vec<String>>()
        .join(", ");
    let mut stmt = db.prepare(&format!("INSERT INTO {} VALUES ({})", table_name, placeholders))
        .unwrap();

    for (idx, value) in row.iter().enumerate() {
        stmt.bind_text((idx + 1) as sqlite3::ParamIx, value).unwrap();
    }
    assert!(stmt.execute().step().unwrap().is_none());
}

fn _load_table_from_path(db: &mut sqlite3::DatabaseConnection,
                         table_name: &str,
                         path: String)
                         -> Vec<String> {
    let mut num_rows = 0;
    let mut reader = csv::Reader::from_file(path).unwrap();

    let normalized_cols = reader.headers().unwrap().iter().map(_normalize_col).collect();
    _create_table(db, table_name, &normalized_cols);

    for row in reader.decode() {
        _insert_row(db, table_name, row.unwrap(), &normalized_cols);
        num_rows += 1;
    }

    println!(
        "Loaded {} rows into {}({})",
        num_rows,
        table_name,
        normalized_cols.join(", "),
    );
    return normalized_cols;
}

fn _print_table(conn: &mut sqlite3::DatabaseConnection, line: &str) {
    let mut table = prettytable::Table::new();
    table.set_format(*prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
    let mut stmt = match conn.prepare(&line) {
        Ok(stmt) => stmt,
        Err(e) => {
            println!("{}", e.detail.unwrap());
            return;
        }
    };
    let mut results = stmt.execute();
    while let Some(r) = results.step().unwrap() {
        let mut row = prettytable::row::Row::new(vec![]);
        for i in 0..r.column_count() {
            row.add_cell(prettytable::cell::Cell::new(&r.column_text(i).unwrap_or("".to_string())));
        }
        table.add_row(row);
    }
    table.printstd();
}

struct SimpleWordCompleter {
    words: Vec<String>,
}

static BREAK_CHARS: [char; 4] = [' ', '(', ')', ','];
impl SimpleWordCompleter {
    fn new(words: Vec<String>) -> SimpleWordCompleter {
        return SimpleWordCompleter { words: words };
    }
}

impl rustyline::completion::Completer for SimpleWordCompleter {
    fn complete(&self, line: &str, pos: usize) -> rustyline::Result<(usize, Vec<String>)> {
        let (start, word) =
            rustyline::completion::extract_word(line, pos, &BREAK_CHARS.iter().cloned().collect());

        let matches = self.words.iter().filter(|w| w.starts_with(word)).cloned().collect();
        return Ok((start, matches));
    }
}

fn main() {
    let mut paths = env::args().skip(1);

    let mut conn = sqlite3::DatabaseConnection::in_memory().unwrap();

    let mut base_words = vec!["select", "from", "group", "by", "order", "count"]
        .iter()
        .map(|s| s.to_string())
        .collect::<Vec<String>>();

    if paths.len() == 1 {
        let mut col_names = _load_table_from_path(&mut conn, "t", paths.next().unwrap());
        base_words.append(&mut col_names);
    } else {
        for (idx, path) in paths.enumerate() {
            let mut col_names = _load_table_from_path(&mut conn, &format!("t{}", idx + 1), path);
            base_words.append(&mut col_names);
        }
    }

    let completer = SimpleWordCompleter::new(base_words);
    let mut rl = rustyline::Editor::new();
    rl.set_completer(Some(completer));
    loop {
        match rl.readline("> ") {
            Ok(line) => {
                if line.trim().is_empty() {
                    continue;
                }
                rl.add_history_entry(&line);
                _print_table(&mut conn, &line);
            }
            Err(rustyline::error::ReadlineError::Interrupted) => {
                println!("Interrupted");
                continue;
            }
            Err(rustyline::error::ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                println!("Error: {}", err);
                break;
            }
        }
    }
}
<commit_msg>distinct is a good word<commit_after>extern crate csv;
extern crate prettytable;
extern crate regex;
extern crate rustyline;
extern crate sqlite3;

use std::env;

fn _normalize_col(col: &String) -> String {
    let re = regex::Regex::new(r"\(.*?\)").unwrap();
    return re.replace_all(col, "")
        .to_lowercase()
        .trim()
        .replace(" ", "_")
        .replace(".", "_")
        .replace("?", "");
}

fn _create_table(db: &mut sqlite3::DatabaseConnection, table_name: &str, cols: &Vec<String>) {
    let create_columns =
        cols.iter().map(|c| format!("{} varchar", c)).collect::<Vec<String>>().join(", ");
    db.exec(&format!("CREATE TABLE {} ({})", table_name, create_columns)).unwrap();
}

fn _insert_row(db: &mut sqlite3::DatabaseConnection,
               table_name: &str,
               row: Vec<String>,
               cols: &Vec<String>) {
    let placeholders = cols.iter()
        .enumerate()
        .map(|(idx, _)| format!("${}", idx + 1))
        .collect::<Vec<String>>()
        .join(", ");
    let mut stmt = db.prepare(&format!("INSERT INTO {} VALUES ({})", table_name, placeholders))
        .unwrap();

    for (idx, value) in row.iter().enumerate() {
        stmt.bind_text((idx + 1) as sqlite3::ParamIx, value).unwrap();
    }
    assert!(stmt.execute().step().unwrap().is_none());
}

fn _load_table_from_path(db: &mut sqlite3::DatabaseConnection,
                         table_name: &str,
                         path: String)
                         -> Vec<String> {
    let mut num_rows = 0;
    let mut reader = csv::Reader::from_file(path).unwrap();

    let normalized_cols = reader.headers().unwrap().iter().map(_normalize_col).collect();
    _create_table(db, table_name, &normalized_cols);

    for row in reader.decode() {
        _insert_row(db, table_name, row.unwrap(), &normalized_cols);
        num_rows += 1;
    }

    println!(
        "Loaded {} rows into {}({})",
        num_rows,
        table_name,
        normalized_cols.join(", "),
    );
    return normalized_cols;
}

fn _print_table(conn: &mut sqlite3::DatabaseConnection, line: &str) {
    let mut table = prettytable::Table::new();
    table.set_format(*prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
    let mut stmt = match conn.prepare(&line) {
        Ok(stmt) => stmt,
        Err(e) => {
            println!("{}", e.detail.unwrap());
            return;
        }
    };
    let mut results = stmt.execute();
    while let Some(r) = results.step().unwrap() {
        let mut row = prettytable::row::Row::new(vec![]);
        for i in 0..r.column_count() {
            row.add_cell(prettytable::cell::Cell::new(&r.column_text(i).unwrap_or("".to_string())));
        }
        table.add_row(row);
    }
    table.printstd();
}

struct SimpleWordCompleter {
    words: Vec<String>,
}

static BREAK_CHARS: [char; 4] = [' ', '(', ')', ','];
impl SimpleWordCompleter {
    fn new(words: Vec<String>) -> SimpleWordCompleter {
        return SimpleWordCompleter { words: words };
    }
}

impl rustyline::completion::Completer for SimpleWordCompleter {
    fn complete(&self, line: &str, pos: usize) -> rustyline::Result<(usize, Vec<String>)> {
        let (start, word) =
            rustyline::completion::extract_word(line, pos, &BREAK_CHARS.iter().cloned().collect());

        let matches = self.words.iter().filter(|w| w.starts_with(word)).cloned().collect();
        return Ok((start, matches));
    }
}

fn main() {
    let mut paths = env::args().skip(1);

    let mut conn = sqlite3::DatabaseConnection::in_memory().unwrap();

    let mut base_words = vec!["distinct", "select", "from", "group", "by", "order", "count"]
        .iter()
        .map(|s| s.to_string())
        .collect::<Vec<String>>();

    if paths.len() == 1 {
        let mut col_names = _load_table_from_path(&mut conn, "t", paths.next().unwrap());
        base_words.append(&mut col_names);
    } else {
        for (idx, path) in paths.enumerate() {
            let mut col_names = _load_table_from_path(&mut conn, &format!("t{}", idx + 1), path);
            base_words.append(&mut col_names);
        }
    }

    let completer = SimpleWordCompleter::new(base_words);
    let mut rl = rustyline::Editor::new();
    rl.set_completer(Some(completer));
    loop {
        match rl.readline("> ") {
            Ok(line) => {
                if line.trim().is_empty() {
                    continue;
                }
                rl.add_history_entry(&line);
                _print_table(&mut conn, &line);
            }
            Err(rustyline::error::ReadlineError::Interrupted) => {
                println!("Interrupted");
                continue;
            }
            Err(rustyline::error::ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                println!("Error: {}", err);
                break;
            }
        }
    }
}
<|endoftext|>


<commit_before>//#![feature(rustc_private)]
extern crate bufstream;
extern crate getopts;

use getopts::Options;
use std::env;
use std::net::{TcpListener, TcpStream};
use std::io::{Write, BufRead, Read};
use bufstream::BufStream;
use std::error::Error;
use std::process::{Command, Stdio};

struct Config {
    die: bool,
    port: String
}

fn main(){
    // argument parsing to create the initial configuration
    let args: Vec<String> = env::args().collect();
    let mut opts = Options::new();
    let brief = format!("Usage: {} [options]", args[0].clone());
    opts.optopt("p", "port", "set binding port", "PORT");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => (m),
        Err(why) => {
            println!("{}", why);
            print!("{}", opts.usage(&brief));
            return
        }
    };
    let port;
    match matches.opt_str("p"){
        None => {
            println!("must specify a port");
            print!("{}", opts.usage(&brief));
            return;
        },
        Some(p) => port = p
    }
    let mut config = Config{die:false, port:port};
    let mut accept = true;

    while accept{
        let addr_string = "127.0.0.1:".to_string() + &config.port;
        match TcpListener::bind(&*addr_string) {
            Err(why) => println!("{}", why),
            Ok(listener) => for stream in listener.incoming() {
                match stream {
                    Err(why) => println!("accept err {}", why.description()),
                    Ok(stream) => {
                        config = handler(&config, &mut BufStream::new(stream));
                        if config.die {
                            accept = false;
                        }
                        break
                    }
                }
            }
        }
    }
}

fn echo_ln(s: &mut BufStream<TcpStream>){
    match s.write_all(b"\n") {
        Err(_) => {},
        Ok(_) =>{},
    }
    match s.flush() {
        Err(_) => {},
        Ok(_) =>{},
    }
}

fn echo_str(str: std::string::String, s: &mut BufStream<TcpStream>){
    match s.write_all(str.as_bytes()){
        Err(why) => println!("could not reply {:?}", why),
        Ok(_) => {}
    }
    echo_ln(s);
}

fn handler(config: &Config, s: &mut BufStream<TcpStream>) -> Config{
    // Until the user does not request to close.
    loop{
        let _ = s.write(b"> ");
        let _ = s.flush();
        let mut cmd = std::string::String::new();
        s.read_line(&mut cmd).unwrap();
        let cmd_splt : Vec<_> = cmd.as_str().split_whitespace().collect();
        let mut args = Vec::new();
        for i in 1..cmd_splt.len() {
            args.push(cmd_splt[i]);
        }
        let main_cmd = cmd_splt[0];
        // Here goes the command processing.
        match main_cmd{
            "exit" => return Config{die:false, port:config.port.to_string()},
            "kill" => return Config{die:true, port:config.port.to_string()},
            "cfgport" => {
                if cmd_splt.len() == 1{
                    echo_str("[USAGE] cfgport [newport]".to_string(), s)
                }else{
                    match cmd_splt[1].parse::<i32>(){
                        Err(_) => echo_str("[USAGE] cfgport [newport] (newport must be an integer)".to_string(), s),
                        Ok(_) => {
                            let new_port = cmd_splt[1]; // just for clarity
                            let addr_string = "127.0.0.1:".to_string() + new_port;
                            match TcpListener::bind(&*addr_string) {
                                Err(_) => echo_str("[NOK] port ".to_string() + new_port + " unavailable", s),
                                Ok(_) => {
                                    echo_str("[OK] reconnect via port ".to_string() + new_port, s);
                                    return Config{die:false, port:new_port.to_string()}
                                },
                            }
                        }
                    };
                }
            },
            "cfgpwd" => echo_str("passwords not yet implemented".to_string(), s),
            _ => match Command::new(main_cmd).args(&args).stdout(Stdio::piped()).spawn() {
                Err(why) => echo_str(why.description().to_string(), s),
                Ok(process) => {
                    let mut stde = String::new();
                    match process.stderr {
                        Some(mut err) => {
                            match err.read_to_string(&mut stde) {
                                Err(why) => echo_str(why.description().to_string(), s),
                                Ok(_) => echo_str(stde.to_string(), s)
                            };
                        },
                        None => {
                            let mut stdo = String::new();
                            match process.stdout.unwrap().read_to_string(&mut stdo) {
                                Err(why) => echo_str(why.description().to_string(), s),
                                Ok(_) => echo_str(stdo.to_string(), s)
                            }
                        }
                    }
                },
            }
        }
    }
}
<commit_msg>Attempting to use a `&'static str` for port breaks<commit_after>extern crate bufstream;
use std::net::{TcpListener, TcpStream};
use std::io::{Write, BufRead, Read};
use bufstream::BufStream;
use std::error::Error;
use std::process::{Command, Stdio};

#[derive(Clone)]
struct Config {
    die: bool,
    port: String
}

const DEFAULT_PORT: &'static str = "8000";

fn main(){
    let mut config = Config{die:false, port:DEFAULT_PORT.to_string()};
    let mut accept = true;

    while accept{
        let addr_string = "127.0.0.1:".to_string() + &config.port;
        match TcpListener::bind(&*addr_string) {
            Err(why) => println!("{}", why),
            Ok(listener) => for stream in listener.incoming() {
                match stream {
                    Err(why) => println!("accept err {}", why.description()),
                    Ok(stream) => {
                        config = handler(&config, &mut BufStream::new(stream));
                        if config.die {
                            accept = false;
                        }
                        break
                    }
                }
            }
        }
    }
}

fn echo_ln(s: &mut BufStream<TcpStream>){
    match s.write_all(b"\n") {
        Err(_) => {},
        Ok(_) =>{},
    }
    match s.flush() {
        Err(_) => {},
        Ok(_) =>{},
    }
}

fn echo_str(str: std::string::String, s: &mut BufStream<TcpStream>){
    match s.write_all(str.as_bytes()){
        Err(why) => println!("could not reply {:?}", why),
        Ok(_) => {}
    }
    echo_ln(s);
}

fn handler(config: &Config, s: &mut BufStream<TcpStream>) -> Config{
    // Until the user does not request to close.
    loop{
        let _ = s.write(b"> ");
        let _ = s.flush();
        let mut cmd = std::string::String::new();
        s.read_line(&mut cmd).unwrap();
        let cmd_splt : Vec<_> = cmd.as_str().split_whitespace().collect();
        let mut args = Vec::new();
        for i in 1..cmd_splt.len() {
            args.push(cmd_splt[i]);
        }
        let main_cmd = cmd_splt[0];
        // Here goes the command processing.
        match main_cmd{
            "exit" => return config.clone(),
            "kill" => {
                let mut clone = config.clone();
                clone.die = true;
                return clone
            },
            "cfgport" => {
                if cmd_splt.len() == 1{
                    echo_str("[USAGE] cfgport [newport]".to_string(), s)
                }else{
                    match cmd_splt[1].parse::<i32>(){
                        Err(_) => echo_str("[USAGE] cfgport [newport] (newport must be an integer)".to_string(), s),
                        Ok(_) => {
                            let new_port = cmd_splt[1]; // just for clarity
                            let addr_string = "127.0.0.1:".to_string() + new_port;
                            match TcpListener::bind(&*addr_string) {
                                Err(_) => echo_str("[NOK] port ".to_string() + new_port + " unavailable", s),
                                Ok(_) => {
                                    echo_str("[OK] reconnect via port ".to_string() + new_port, s);
                                    let mut clone = config.clone();
                                    clone.port = new_port.to_string();
                                    return clone
                                },
                            }
                        }
                    };
                }
            },
            "cfgpwd" => echo_str("passwords not yet implemented".to_string(), s),
            _ => match Command::new(main_cmd).args(&args).stdout(Stdio::piped()).spawn() {
                Err(why) => echo_str(why.description().to_string(), s),
                Ok(process) => {
                    let mut stde = String::new();
                    match process.stderr {
                        Some(mut err) => {
                            match err.read_to_string(&mut stde) {
                                Err(why) => echo_str(why.description().to_string(), s),
                                Ok(_) => echo_str(stde.to_string(), s)
                            };
                        },
                        None => {
                            let mut stdo = String::new();
                            match process.stdout.unwrap().read_to_string(&mut stdo) {
                                Err(why) => echo_str(why.description().to_string(), s),
                                Ok(_) => echo_str(stdo.to_string(), s)
                            }
                        }
                    }
                },
            }
        }
    }
}
<|endoftext|>