<commit_before>extern crate ansi_term;
extern crate docopt;
extern crate rustc_serialize;

use ansi_term::Colour;
use docopt::Docopt;

use std::collections;
use std::io;
use std::path;
use std::process;

use std::os::unix::fs::FileTypeExt;

const USAGE: &'static str = "
srch, a command-line file search utility written in Rust.

Usage:
    srch [options] [<path>] <pattern>
    srch --help
    srch --version

Options:
    -h, --help      Show this help screen
    -v, --version   Show this program's version
    -d              Also search inside directories starting with a . character
";

#[derive(RustcDecodable)]
struct Args {
    arg_pattern: String,
    arg_path: String,
    flag_d: bool,
}

fn main() {
    let args: Args = Docopt::new(USAGE).unwrap()
                            .help(true)
                            .version(Some(String::from("srch, version ") + option_env!("CARGO_PKG_VERSION").unwrap_or("unknown")))
                            .decode()
                            .unwrap_or_else(|e| e.exit());

    let dir = path::PathBuf::from(&args.arg_path);
    if args.arg_path.is_empty() {
        let curdir = path::PathBuf::from(".");
        handle(&curdir, &args);
    } else if !dir.exists() {
        println!("Invalid search path: {}", Colour::Red.bold().paint(args.arg_path.as_str()));
        process::exit(1);
    } else {
        handle(&dir, &args);
    }
}

fn ignore (path: &path::PathBuf, args: &Args) -> io::Result<bool> {
    if !path.is_dir() {
        return Ok(true)
    }

    let m = try!(path.symlink_metadata()).file_type();
    if m.is_symlink() || m.is_block_device() || m.is_char_device() || m.is_fifo() || m.is_socket() {
        return Ok(true)
    }

    if args.flag_d {
        return Ok(false)
    }

    let fname = path.file_name();
    if fname == None {
        return Ok(false)
    }

    let fname = fname.unwrap().to_str().unwrap();
    if fname.chars().next().unwrap() == '.' {
        return Ok(true)
    }

    Ok(false)
}

trait Misc {
    fn display_colour(&self) -> io::Result<String>;
    fn matches(&self, pattern: &String) -> bool;
}

impl Misc for path::PathBuf {
    fn display_colour(&self) -> io::Result<String> {
        let s: &str = self.to_str().unwrap();

        if self.is_dir() {
            Ok(Colour::Purple.paint(s).to_string())
        } else {
            Ok(s.to_string())
        }
    }

    fn matches(&self, pattern: &String) -> bool {
        let fname = self.file_name();
        if fname == None {
            return false
        }

        let fname = fname.unwrap().to_str().unwrap().to_string();
        if fname == *pattern {
            return true
        }
        false
    }
}

fn handle(path: &path::PathBuf, args: &Args) -> () {
    let mut q: collections::VecDeque<path::PathBuf> = collections::VecDeque::new();
    let mut results = (0, 0);

    let pattern = &args.arg_pattern;

    println!("Searching {} for {}", Colour::Yellow.bold().paint(path.to_str().unwrap()), Colour::Green.bold().paint(pattern.as_str()));
    q.push_back(path.clone());
    while q.len() > 0 {
        let p = q.pop_front().unwrap();
        let i = ignore(&p, args);
        match i {
            Ok(tf) => {
                if tf {
                    continue;
                }
            },
            Err(_) => continue,
        };

        let r = explore(&mut q, &p, pattern);
        match r {
            Ok(n) => {
                results.0 += n.0;
                results.1 += n.1;
            },
            Err(_) => (),
        };
    }

    let (directories, files) = results;
    println!("Search results: {} directories, {} files", Colour::Cyan.bold().paint(directories.to_string()), Colour::Blue.bold().paint(files.to_string()));
}

fn explore(q: &mut collections::VecDeque<path::PathBuf>, path: &path::PathBuf, pattern: &String) -> std::io::Result<(i32, i32)> {
    let mut directories = 0;
    let mut files = 0;

    for item in try!(path.read_dir()) {
        let f = try!(item); // f is a DirEntry
        let dir: bool;
        if f.path().is_dir() {
            q.push_back(f.path());
            dir = true;
        } else {
            dir = false;
        }

        if f.path().matches(&pattern) {
            println!("{}", try!(f.path().display_colour()));
            if dir {
                directories += 1;
            } else {
                files += 1;
            }
        }
    }

    Ok((directories, files))
}
<commit_msg>Rename -d to -i and add -f flag<commit_after>extern crate ansi_term;
extern crate docopt;
extern crate rustc_serialize;

use ansi_term::Colour;
use docopt::Docopt;

use std::collections;
use std::io;
use std::path;
use std::process;

use std::os::unix::fs::FileTypeExt;

const USAGE: &'static str = "
srch, a command-line file search utility written in Rust.

Usage:
    srch [options] [<path>] <pattern>
    srch --help
    srch --version

Options:
    -h, --help        Show this help screen
    -v, --version     Show this program's version
    -i, --invisible   Also search inside directories starting with a . character
    -f, --filesonly   Only search filenames and NOT directory names
";

#[derive(RustcDecodable)]
struct Args {
    arg_pattern: String,
    arg_path: String,

    flag_i: bool,
    flag_invisible: bool,

    flag_f: bool,
    flag_filesonly: bool,
}

fn main() {
    let args: Args = Docopt::new(USAGE).unwrap()
                            .help(true)
                            .version(Some(String::from("srch, version ") + option_env!("CARGO_PKG_VERSION").unwrap_or("unknown")))
                            .decode()
                            .unwrap_or_else(|e| e.exit());

    let dir = path::PathBuf::from(&args.arg_path);
    if args.arg_path.is_empty() {
        let curdir = path::PathBuf::from(".");
        handle(&curdir, &args);
    } else if !dir.exists() {
        println!("Invalid search path: {}", Colour::Red.bold().paint(args.arg_path.as_str()));
        process::exit(1);
    } else {
        handle(&dir, &args);
    }
}

fn ignore (path: &path::PathBuf, args: &Args) -> io::Result<bool> {
    if !path.is_dir() {
        return Ok(true)
    }

    let m = try!(path.symlink_metadata()).file_type();
    if m.is_symlink() || m.is_block_device() || m.is_char_device() || m.is_fifo() || m.is_socket() {
        return Ok(true)
    }

    if args.flag_i || args.flag_invisible {
        return Ok(false)
    }

    let fname = path.file_name();
    if fname == None {
        return Ok(false)
    }

    let fname = fname.unwrap().to_str().unwrap();
    if fname.chars().next().unwrap() == '.' {
        return Ok(true)
    }

    Ok(false)
}

trait Misc {
    fn display_colour(&self) -> io::Result<String>;
    fn matches(&self, pattern: &String) -> bool;
}

impl Misc for path::PathBuf {
    fn display_colour(&self) -> io::Result<String> {
        let s: &str = self.to_str().unwrap();

        if self.is_dir() {
            Ok(Colour::Purple.paint(s).to_string())
        } else {
            Ok(s.to_string())
        }
    }

    fn matches(&self, pattern: &String) -> bool {
        let fname = self.file_name();
        if fname == None {
            return false
        }

        let fname = fname.unwrap().to_str().unwrap().to_string();
        if fname == *pattern {
            return true
        }
        false
    }
}

fn handle(path: &path::PathBuf, args: &Args) -> () {
    let mut q: collections::VecDeque<path::PathBuf> = collections::VecDeque::new();
    let mut results = (0, 0);

    let pattern = &args.arg_pattern;

    println!("Searching {} for {}", Colour::Yellow.bold().paint(path.to_str().unwrap()), Colour::Green.bold().paint(pattern.as_str()));
    q.push_back(path.clone());
    while q.len() > 0 {
        let p = q.pop_front().unwrap();
        let i = ignore(&p, args);
        match i {
            Ok(tf) => {
                if tf {
                    continue;
                }
            },
            Err(_) => continue,
        };

        let r = explore(&mut q, &p, pattern, args.flag_f || args.flag_filesonly);
        match r {
            Ok(n) => {
                results.0 += n.0;
                results.1 += n.1;
            },
            Err(_) => (),
        };
    }

    let (directories, files) = results;
    println!("Search results: {} directories, {} files", Colour::Cyan.bold().paint(directories.to_string()), Colour::Blue.bold().paint(files.to_string()));
}

fn explore(q: &mut collections::VecDeque<path::PathBuf>, path: &path::PathBuf, pattern: &String, ignore_dirs: bool) -> std::io::Result<(i32, i32)> {
    let mut directories = 0;
    let mut files = 0;

    for item in try!(path.read_dir()) {
        let f = try!(item); // f is a DirEntry
        let dir: bool;
        if f.path().is_dir() {
            q.push_back(f.path());
            if ignore_dirs {
                continue;
            }
            dir = true;
        } else {
            dir = false;
        }

        if f.path().matches(&pattern) {
            println!("{}", try!(f.path().display_colour()));
            if dir {
                directories += 1;
            } else {
                files += 1;
            }
        }
    }

    Ok((directories, files))
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
#[macro_use]
extern crate lazy_static;

extern crate libc;
extern crate scmp;
extern crate tempdir;

use std::fs;
use std::env;
use std::ffi::OsStr;
use std::ffi::CString;
use std::io::Error;
use std::os::unix::process::CommandExt;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use scmp::*;

fn setup_seccomp() -> Result<(), Error> {
    unsafe {
        let ctx0 = seccomp_init(SCMP_ACT_TRAP);
        assert!(!ctx0.is_null());
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_execve as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_brk as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_access as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_mmap as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_open as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_read as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_write as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_stat as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_fstat as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_close as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_mprotect as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_arch_prctl as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_munmap as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_set_tid_address as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_set_robust_list as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_rt_sigaction as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_rt_sigprocmask as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_getrlimit as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_statfs as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_fcntl as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_geteuid as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_umask as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_pipe as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_clone as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_wait4 as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_exit_group as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_dup as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_ioctl as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_getpid as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_gettid as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_tgkill as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_rt_sigreturn as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_socket as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_connect as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_lseek as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_openat as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_unlinkat as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_utimensat as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_lstat as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_fchmod as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_unlink as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_utime as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_futex as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_chmod as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_load(ctx0) == 0);
    }
    return Ok(());
}

const RENAME_NOREPLACE : u64 = 1;

fn rename_noreplace(path0 : &Path, path1 : &Path) -> Result<(), Error> {
    unsafe {
        if libc::syscall(__NR_renameat2 as i64, libc::AT_FDCWD, CString::new(path0.as_os_str().as_bytes()).unwrap().as_ptr(), libc::AT_FDCWD, CString::new(path1.as_os_str().as_bytes()).unwrap().as_ptr(), RENAME_NOREPLACE, 0) == 0 {
            return Ok(());
        } else {
            return Err(Error::last_os_error());
        }
    }
}

fn rename_or_suffix(path0 : &Path, path1 : &Path) -> Result<PathBuf, Error> {
    let rv = rename_noreplace(path0, path1);
    if let Err(err) = rv {
        if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
            return Err(err);
        }
        for suffix in 1.. {
            let mut builder = path1.as_os_str().to_os_string();
            builder.push(format!(".{}", suffix));
            let rv = rename_noreplace(path0, Path::new(&builder));
            if let Err(err) = rv {
                if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
                    return Err(err);
                }
                continue;
            }
            return Ok(Path::new(&builder).to_path_buf());
        }
        return Ok(PathBuf::new()); // XXX Unreachable
    } else {
        return Ok(path1.to_path_buf());
    }
}

struct ArchiveType {
    extensions: Vec<&'static str>,
    extract_cmd: Vec<&'static str>,
}

lazy_static! {
    static ref ARCHIVE_TYPES : Vec<ArchiveType> = vec![
        ArchiveType {
            extensions: vec![
                ".tgz",
                ".tar.gz",
                ".tar.Z",
                ".tbz2",
                ".tar.bz2",
                ".tlz",
                ".tar.lz",
                ".tar.lzma",
                ".tar.lzo",
                ".tar.xz",
            ],
            extract_cmd: vec!["tar", "-xf"],
        },
        ArchiveType {
            extensions: vec![
                ".zip",
            ],
            extract_cmd: vec!["unzip", "--"],
        },
        ArchiveType {
            extensions: vec![
                ".rar",
            ],
            extract_cmd: vec!["unrar", "x", "--"],
        },
    ];
}

fn main() {
    let matches = clap_app!(myapp =>
        (@arg ARCHIVE: +required ... "Archives to extract")
    ).get_matches();

    let mut found = false;

    for arch in matches.values_of_os("ARCHIVE").unwrap() {
        let arch = Path::new(arch);
        println!("Extract {:?}", arch);
        for at in ARCHIVE_TYPES.iter() {
            for &ext in &at.extensions {
                if !arch.as_os_str().as_bytes().ends_with(ext.as_bytes()) {
                    continue;
                }
                found = true;

                let noext : &OsStr = OsStrExt::from_bytes(&arch.as_os_str().as_bytes()[0..arch.as_os_str().as_bytes().len()-ext.as_bytes().len()]);
                let stripped =
                    if let Some(noext) = Path::new(noext).file_name() {
                        noext
                    } else {
                        OsStr::new("extracted")
                    };
                let cmd = at.extract_cmd[0];
                let tmpdir = tempdir::TempDir::new_in(
                    env::current_dir().expect("Unable to get the current directory"),
                    stripped.to_string_lossy().to_mut().as_str()).expect("Unable to create temporary directory");
                let status = Command::new(cmd)
                    .args(&at.extract_cmd[1..])
                    .arg(&arch)
                    .current_dir(&tmpdir)
                    .before_exec(setup_seccomp)
                    .status()
                    .expect(format!("Failed to launch {}", cmd).as_str());
                assert!(status.success(), format!("{} wasn't successful", cmd));
                let extracted_path = tmpdir.into_path();
                let mut dir_list = fs::read_dir(&extracted_path).expect("Unable to read the extraction directory");
                if let Some(path) = dir_list.next() {
                    let path = path.expect("Unable to iterate the extraction directory");
                    if let Some(path1) = dir_list.next() {
                        path1.expect("Unable to iterate the extraction directory");
                        rename_or_suffix(&extracted_path, Path::new(stripped)).expect("Failed to rename");
                    } else {
                        rename_or_suffix(&path.path(), Path::new(stripped)).expect("Failed to rename");
                        fs::remove_dir(&extracted_path).expect("Failed to remove empty extraction directory");
                    }
                } else {
                    println!("No files were extracted");
                }
                break;
            }
        }
        if !found {
            println!("Can't handle {:?}", arch);
        }
    }
}

<commit_msg>Print extraction path<commit_after>#[macro_use]
extern crate clap;
#[macro_use]
extern crate lazy_static;

extern crate libc;
extern crate scmp;
extern crate tempdir;

use std::fs;
use std::env;
use std::ffi::OsStr;
use std::ffi::CString;
use std::io::Error;
use std::os::unix::process::CommandExt;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use scmp::*;

fn setup_seccomp() -> Result<(), Error> {
    unsafe {
        let ctx0 = seccomp_init(SCMP_ACT_TRAP);
        assert!(!ctx0.is_null());
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_execve as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_brk as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_access as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_mmap as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_open as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_read as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_write as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_stat as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_fstat as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_close as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_mprotect as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_arch_prctl as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_munmap as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_set_tid_address as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_set_robust_list as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_rt_sigaction as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_rt_sigprocmask as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_getrlimit as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_statfs as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_fcntl as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_geteuid as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_umask as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_pipe as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_clone as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_wait4 as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_exit_group as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_dup as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_ioctl as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_getpid as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_gettid as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_tgkill as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_rt_sigreturn as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_socket as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_connect as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_lseek as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_openat as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_unlinkat as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_utimensat as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_lstat as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_fchmod as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_unlink as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_utime as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_futex as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_rule_add_array(ctx0, SCMP_ACT_ALLOW, __NR_chmod as i32, 0, std::ptr::null()) == 0);
        assert!(seccomp_load(ctx0) == 0);
    }
    return Ok(());
}

const RENAME_NOREPLACE : u64 = 1;

fn rename_noreplace(path0 : &Path, path1 : &Path) -> Result<(), Error> {
    unsafe {
        if libc::syscall(__NR_renameat2 as i64, libc::AT_FDCWD, CString::new(path0.as_os_str().as_bytes()).unwrap().as_ptr(), libc::AT_FDCWD, CString::new(path1.as_os_str().as_bytes()).unwrap().as_ptr(), RENAME_NOREPLACE, 0) == 0 {
            return Ok(());
        } else {
            return Err(Error::last_os_error());
        }
    }
}

fn rename_or_suffix(path0 : &Path, path1 : &Path) -> Result<PathBuf, Error> {
    let rv = rename_noreplace(path0, path1);
    if let Err(err) = rv {
        if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
            return Err(err);
        }
        for suffix in 1.. {
            let mut builder = path1.as_os_str().to_os_string();
            builder.push(format!(".{}", suffix));
            let rv = rename_noreplace(path0, Path::new(&builder));
            if let Err(err) = rv {
                if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
                    return Err(err);
                }
                continue;
            }
            return Ok(Path::new(&builder).to_path_buf());
        }
        return Ok(PathBuf::new()); // XXX Unreachable
    } else {
        return Ok(path1.to_path_buf());
    }
}

struct ArchiveType {
    extensions: Vec<&'static str>,
    extract_cmd: Vec<&'static str>,
}

lazy_static! {
    static ref ARCHIVE_TYPES : Vec<ArchiveType> = vec![
        ArchiveType {
            extensions: vec![
                ".tgz",
                ".tar.gz",
                ".tar.Z",
                ".tbz2",
                ".tar.bz2",
                ".tlz",
                ".tar.lz",
                ".tar.lzma",
                ".tar.lzo",
                ".tar.xz",
            ],
            extract_cmd: vec!["tar", "-xf"],
        },
        ArchiveType {
            extensions: vec![
                ".zip",
            ],
            extract_cmd: vec!["unzip", "--"],
        },
        ArchiveType {
            extensions: vec![
                ".rar",
            ],
            extract_cmd: vec!["unrar", "x", "--"],
        },
    ];
}

fn main() {
    let matches = clap_app!(myapp =>
        (@arg ARCHIVE: +required ... "Archives to extract")
    ).get_matches();

    let mut found = false;

    for arch in matches.values_of_os("ARCHIVE").unwrap() {
        let arch = Path::new(arch);
        println!("Extract {:?}", arch);
        for at in ARCHIVE_TYPES.iter() {
            for &ext in &at.extensions {
                if !arch.as_os_str().as_bytes().ends_with(ext.as_bytes()) {
                    continue;
                }
                found = true;

                let noext : &OsStr = OsStrExt::from_bytes(&arch.as_os_str().as_bytes()[0..arch.as_os_str().as_bytes().len()-ext.as_bytes().len()]);
                let stripped =
                    if let Some(noext) = Path::new(noext).file_name() {
                        noext
                    } else {
                        OsStr::new("extracted")
                    };
                let cmd = at.extract_cmd[0];
                let tmpdir = tempdir::TempDir::new_in(
                    env::current_dir().expect("Unable to get the current directory"),
                    stripped.to_string_lossy().to_mut().as_str()).expect("Unable to create temporary directory");
                let status = Command::new(cmd)
                    .args(&at.extract_cmd[1..])
                    .arg(&arch)
                    .current_dir(&tmpdir)
                    .before_exec(setup_seccomp)
                    .status()
                    .expect(format!("Failed to launch {}", cmd).as_str());
                assert!(status.success(), format!("{} wasn't successful", cmd));
                let extracted_path = tmpdir.into_path();
                let mut dir_list = fs::read_dir(&extracted_path).expect("Unable to read the extraction directory");
                if let Some(path) = dir_list.next() {
                    let path = path.expect("Unable to iterate the extraction directory");
                    if let Some(path1) = dir_list.next() {
                        path1.expect("Unable to iterate the extraction directory");
                        let newname = rename_or_suffix(&extracted_path, Path::new(stripped)).expect("Failed to rename");
                        println!("Extracted to {:?}", newname);
                    } else {
                        let newname = rename_or_suffix(&path.path(), Path::new(stripped)).expect("Failed to rename");
                        println!("Extracted to {:?}", newname);
                        fs::remove_dir(&extracted_path).expect("Failed to remove empty extraction directory");
                    }
                } else {
                    println!("No files were extracted");
                }
                break;
            }
        }
        if !found {
            println!("Can't handle {:?}", arch);
        }
    }
}

<|endoftext|>


<commit_before>//! Main module of way-cooler

#[macro_use]
extern crate lazy_static;
extern crate bitflags;
extern crate dbus_macros;
#[cfg(not(test))]
extern crate rustwlc;
extern crate getopts;
#[cfg(test)]
extern crate dummy_rustwlc as rustwlc;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate hlua;
extern crate rustc_serialize;
extern crate json_macro;
extern crate nix;
extern crate petgraph;
extern crate uuid;
extern crate dbus;
extern crate cairo;
#[macro_use]
extern crate wayland_sys;
extern crate wayland_server;

#[macro_use]
mod macros;
mod convert;
mod callbacks;
mod keys;
mod lua;
mod registry;
mod commands;
mod ipc;
mod layout;
mod render;

mod wayland;
mod modes;

use std::env;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;

use getopts::Options;
use log::LogLevel;
use nix::sys::signal::{self, SigHandler, SigSet, SigAction, SaFlags};

use rustwlc::types::LogType;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const GIT_VERSION: &'static str = include_str!(concat!(env!("OUT_DIR"), "/git-version.txt"));
const DRIVER_MOD_PATH: &'static str = "/proc/modules";

/// Callback to route wlc logs into env_logger
fn log_handler(level: LogType, message: &str) {
    match level {
        LogType::Info => info!("wlc: {}", message),
        LogType::Warn => warn!("wlc: {}", message),
        LogType::Error => error!("wlc: {}", message),
        LogType::Wayland => info!("wayland: {}", message)
    }
}

/// Formats the log strings properly
fn log_format(record: &log::LogRecord) -> String {
    let color = match record.level() {
        LogLevel::Info => "",
        LogLevel::Trace => "\x1B[37m",
        LogLevel::Debug => "\x1B[44m",
        LogLevel::Warn =>  "\x1B[33m",
        LogLevel::Error => "\x1B[31m",
    };
    let location = record.location();
    let file = location.file();
    let line = location.line();
    let mut module_path = location.module_path();
    if let Some(index) = module_path.find("way_cooler::") {
        let index = index + "way_cooler::".len();
        module_path = &module_path[index..];
    }
    format!("{} {} [{}] \x1B[37m{}:{}\x1B[0m{0} {} \x1B[0m",
            color, record.level(), module_path, file, line, record.args())
}

/// Checks the loaded modules, and reports any problematic proprietary ones
fn detect_proprietary() {
    // If DISPLAY is present, we are running embedded
    if env::var("DISPLAY").is_ok() {
        return
    }
    match File::open(Path::new(DRIVER_MOD_PATH)) {
        Ok(file) => {
            let reader = BufReader::new(&file);
            for line in reader.lines() {
                if let Ok(line) = line {
                    if line.contains("nvidia") {
                        error!("Warning: Proprietary nvidia graphics drivers are installed, \
                               but they are not compatible with Wayland. \
                               Consider using nouveau drivers for Wayland.");
                        break;
                    } else if line.contains("fglrx") {
                        error!("Warning: Proprietary AMD graphics drivers are installed, \
                                but they are not compatible with Wayland. \
                               Consider using radeon drivers for Waylad.");
                        break;
                    }
                }
            }
        },
        Err(err) => {
            warn!("Could not read proprietary modules at \"{}\", because: {:#?}",
                  DRIVER_MOD_PATH, err);
            warn!("If you are running proprietary AMD or Nvidia graphics drivers, \
                   Way Cooler may not work for you");
        }
    }
}

#[inline(always)]
/// Determines if we should build with debug symbols.
pub fn debug_enabled() -> bool {
    cfg!(not(disable_debug))
}

/// Initializes the logging system.
pub fn init_logs() {
    let mut builder = env_logger::LogBuilder::new();
    builder.format(log_format);
    builder.filter(None, log::LogLevelFilter::Trace);
    if env::var("WAY_COOLER_LOG").is_ok() {
        builder.parse(&env::var("WAY_COOLER_LOG")
                      .expect("WAY_COOLER_LOG not defined"));
    }
    builder.init().expect("Unable to initialize logging!");
    info!("Logger initialized, setting wlc handlers.");
}

fn log_environment() {
    for (key, value) in env::vars() {
        info!("{}: {}", key, value);
    }
}

/// Handler for signals
extern "C" fn sig_handle(_: nix::libc::c_int) {
    rustwlc::terminate();
}

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

    let mut opts = Options::new();
    opts.optflag("", "version", "show version information");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            println!("{}", f.to_string());
            std::process::exit(1);
        }
    };
    if matches.opt_present("version") {
        if !GIT_VERSION.is_empty() {
            println!("Way Cooler {} @ {}", VERSION, GIT_VERSION);
        } else {
            println!("Way Cooler {}", VERSION);
        }
        println!("Way Cooler IPC version {}", ipc::VERSION);
        return
    }
    println!("Launching way-cooler...");

    let sig_action = SigAction::new(SigHandler::Handler(sig_handle), SaFlags::empty(),
                                    SigSet::empty());
    unsafe {signal::sigaction(signal::SIGINT, &sig_action).unwrap() };

    init_logs();
    log_environment();
    detect_proprietary();
    // This prepares wlc, doesn't run main loop until run_wlc is called
    let run_wlc = rustwlc::init()
        .expect("Unable to initialize wlc!");
    wayland::init_wayland_protocols();
    rustwlc::log_set_rust_handler(log_handler);
    callbacks::init();
    commands::init();
    registry::init();
    lua::init();
    ipc::init();

    info!("Running wlc...");
    run_wlc();
}
<commit_msg>Fixes #294, error out when XDG_RUNTIME_DIR not set<commit_after>//! Main module of way-cooler

#[macro_use]
extern crate lazy_static;
extern crate bitflags;
extern crate dbus_macros;
#[cfg(not(test))]
extern crate rustwlc;
extern crate getopts;
#[cfg(test)]
extern crate dummy_rustwlc as rustwlc;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate hlua;
extern crate rustc_serialize;
extern crate json_macro;
extern crate nix;
extern crate petgraph;
extern crate uuid;
extern crate dbus;
extern crate cairo;
#[macro_use]
extern crate wayland_sys;
extern crate wayland_server;

#[macro_use]
mod macros;
mod convert;
mod callbacks;
mod keys;
mod lua;
mod registry;
mod commands;
mod ipc;
mod layout;
mod render;

mod wayland;
mod modes;

use std::env;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::Path;

use getopts::Options;
use log::LogLevel;
use nix::sys::signal::{self, SigHandler, SigSet, SigAction, SaFlags};

use rustwlc::types::LogType;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const GIT_VERSION: &'static str = include_str!(concat!(env!("OUT_DIR"), "/git-version.txt"));
const DRIVER_MOD_PATH: &'static str = "/proc/modules";

/// Callback to route wlc logs into env_logger
fn log_handler(level: LogType, message: &str) {
    match level {
        LogType::Info => info!("wlc: {}", message),
        LogType::Warn => warn!("wlc: {}", message),
        LogType::Error => error!("wlc: {}", message),
        LogType::Wayland => info!("wayland: {}", message)
    }
}

/// Formats the log strings properly
fn log_format(record: &log::LogRecord) -> String {
    let color = match record.level() {
        LogLevel::Info => "",
        LogLevel::Trace => "\x1B[37m",
        LogLevel::Debug => "\x1B[44m",
        LogLevel::Warn =>  "\x1B[33m",
        LogLevel::Error => "\x1B[31m",
    };
    let location = record.location();
    let file = location.file();
    let line = location.line();
    let mut module_path = location.module_path();
    if let Some(index) = module_path.find("way_cooler::") {
        let index = index + "way_cooler::".len();
        module_path = &module_path[index..];
    }
    format!("{} {} [{}] \x1B[37m{}:{}\x1B[0m{0} {} \x1B[0m",
            color, record.level(), module_path, file, line, record.args())
}

/// Ensures that the environment is set up correctly. E.g:
/// * XDG_RUNTIME_DIR is set to a directory that exists.
fn ensure_good_env() {
    use std::env::VarError;
    match env::var("XDG_RUNTIME_DIR") {
        Ok(_) => {/* Do nothing, logged in `log_environment` */},
        Err(VarError::NotUnicode(string)) => {
            error!("The value set for XDG_RUNTIME_DIR ({:?}) \
                    is not valid unicode!",
                   string);
            std::process::exit(1);
        },
        Err(VarError::NotPresent) => {
            error!("XDG_RUNTIME_DIR is not set!");
            std::process::exit(1);
        }
    }
}

/// Checks the loaded modules, and reports any problematic proprietary ones
fn detect_proprietary() {
    // If DISPLAY is present, we are running embedded
    if env::var("DISPLAY").is_ok() {
        return
    }
    match File::open(Path::new(DRIVER_MOD_PATH)) {
        Ok(file) => {
            let reader = BufReader::new(&file);
            for line in reader.lines() {
                if let Ok(line) = line {
                    if line.contains("nvidia") {
                        error!("Warning: Proprietary nvidia graphics drivers are installed, \
                               but they are not compatible with Wayland. \
                               Consider using nouveau drivers for Wayland.");
                        break;
                    } else if line.contains("fglrx") {
                        error!("Warning: Proprietary AMD graphics drivers are installed, \
                                but they are not compatible with Wayland. \
                               Consider using radeon drivers for Waylad.");
                        break;
                    }
                }
            }
        },
        Err(err) => {
            warn!("Could not read proprietary modules at \"{}\", because: {:#?}",
                  DRIVER_MOD_PATH, err);
            warn!("If you are running proprietary AMD or Nvidia graphics drivers, \
                   Way Cooler may not work for you");
        }
    }
}

#[inline(always)]
/// Determines if we should build with debug symbols.
pub fn debug_enabled() -> bool {
    cfg!(not(disable_debug))
}

/// Initializes the logging system.
pub fn init_logs() {
    let mut builder = env_logger::LogBuilder::new();
    builder.format(log_format);
    builder.filter(None, log::LogLevelFilter::Trace);
    if env::var("WAY_COOLER_LOG").is_ok() {
        builder.parse(&env::var("WAY_COOLER_LOG")
                      .expect("WAY_COOLER_LOG not defined"));
    }
    builder.init().expect("Unable to initialize logging!");
    info!("Logger initialized, setting wlc handlers.");
}

fn log_environment() {
    for (key, value) in env::vars() {
        info!("{}: {}", key, value);
    }
}

/// Handler for signals
extern "C" fn sig_handle(_: nix::libc::c_int) {
    rustwlc::terminate();
}

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

    let mut opts = Options::new();
    opts.optflag("", "version", "show version information");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            println!("{}", f.to_string());
            std::process::exit(1);
        }
    };
    if matches.opt_present("version") {
        if !GIT_VERSION.is_empty() {
            println!("Way Cooler {} @ {}", VERSION, GIT_VERSION);
        } else {
            println!("Way Cooler {}", VERSION);
        }
        println!("Way Cooler IPC version {}", ipc::VERSION);
        return
    }
    println!("Launching way-cooler...");

    let sig_action = SigAction::new(SigHandler::Handler(sig_handle), SaFlags::empty(),
                                    SigSet::empty());
    unsafe {signal::sigaction(signal::SIGINT, &sig_action).unwrap() };

    init_logs();
    log_environment();
    detect_proprietary();
    ensure_good_env();
    // This prepares wlc, doesn't run main loop until run_wlc is called
    let run_wlc = rustwlc::init()
        .expect("Unable to initialize wlc!");
    wayland::init_wayland_protocols();
    rustwlc::log_set_rust_handler(log_handler);
    callbacks::init();
    commands::init();
    registry::init();
    lua::init();
    ipc::init();

    info!("Running wlc...");
    run_wlc();
}
<|endoftext|>


<commit_before>extern crate ddarecover;
extern crate ansi_escapes;

use ddarecover::block::{BlockDevice, Buffer, Request};
use ddarecover::map_file::{MapFile, SectorState};
use ddarecover::out_file::OutFile;
use std::cmp;
use std::error::Error;
use std::fs::File;
use std::ops::Range;
use std::time::Instant;
use std::path::{Path, PathBuf};
use std::io::{self, Seek, SeekFrom, Write};
use std::collections::HashMap;

const NUM_BUFFERS: usize = 256;
const READ_BATCH_SIZE: usize = 256;
const SYNC_INTERVAL: usize = 60;

struct Recover {
    block: BlockDevice,
    map_file: MapFile,
    map_file_path: PathBuf,
    out_file: OutFile,
    start: Instant,
    last_sync: Instant,
    histogram: HashMap<SectorState, u64>,
    phase_target: SectorState,
}

impl Recover {
    pub fn new(infile_path: &str, outfile_path: &str, mapfile_path: &str) -> io::Result<Recover> {
        let block = BlockDevice::open(infile_path).expect("Unable to open block device");
        let map_path = Path::new(mapfile_path);
        let map = if map_path.exists() {
            let map_file = File::open(map_path).expect("Unable to open existing map file");
            MapFile::read_from_stream(map_file).expect("Error reading map file")
        } else {
            let map = MapFile::new(block.get_size_bytes());
            map.write_to_path(map_path).expect("Unable to create new map file");
            map
        };
        assert_eq!(map.get_size_bytes(), block.get_size_bytes(), "Mismatch between device size and map file");
        let outfile_path = Path::new(outfile_path);
        let outfile = OutFile::open(outfile_path, block.get_size_bytes()).expect("Unable to open output file");

        let histogram = map.get_histogram();
        let result = Recover {
            block: block,
            map_file: map,
            map_file_path: map_path.to_path_buf(),
            out_file: outfile,
            start: Instant::now(),
            last_sync: Instant::now(),
            histogram: histogram,
            phase_target: SectorState::Untried,
        };
        Ok(result)
    }

    fn do_sync(&mut self) -> io::Result<()> {
        self.out_file.sync()?;
        self.map_file.write_to_path(&self.map_file_path)?;
        self.last_sync = Instant::now();
        Ok(())
    }

    fn print_status(&self, overwrite: bool) {
        if overwrite {
            print!("{}", ansi_escapes::EraseLines(5));
        }
        println!("Press Ctrl+C to exit.");
        println!("{:>15}: {:15} {:>15}: {:15} {:>15}: {:15}",
                 "ipos", self.format_bytes(self.map_file.get_pos()),
                 "rescued", self.get_histogram_value_formatted(SectorState::Rescued),
                 "bad", self.get_histogram_value_formatted(SectorState::Bad));

        println!("{:>15}: {:15} {:>15}: {:15} {:>15}: {:15}",
                 "non-tried", self.get_histogram_value_formatted(SectorState::Untried),
                 "non-trimmed", self.get_histogram_value_formatted(SectorState::Untrimmed),
                 "non-scraped", self.get_histogram_value_formatted(SectorState::Unscraped));

        let now = Instant::now();
        let run_time_seconds =  now.duration_since(self.start).as_secs();
        println!("{:>15}: {:15}", "run time", self.format_seconds(run_time_seconds));
    }

    fn format_bytes(&self, bytes: u64) -> String {
        let units = ["KiB", "MiB", "GiB"];
        let mut res_unit = "B";
        let mut res_bytes = bytes as f64;
        for unit in units.iter() {
            if res_bytes >= 1000000.0 {
                res_bytes /= 1024.0;
                res_unit = *unit;
            }
        }
        format!("{:.1} {}", res_bytes, res_unit)
    }

    fn format_seconds(&self, seconds: u64) -> String {
        let mut result = String::new();
        let mut value = seconds;
        for &(unit, multiple) in [("s", 60), ("m", 60), ("h", 24), ("d", usize::max_value())].iter() {
            let multiple = multiple as u64;
            result = format!(" {}{} {}", value % multiple, unit, result);
            value /= multiple;

            if value == 0 {
                break;
            }
        }
        result.trim().to_string()
    }

    fn get_histogram_value_formatted(&self, state: SectorState) -> String {
        self.format_bytes(self.get_histogram_value(state))
    }

    fn get_histogram_value(&self, state: SectorState) -> u64 {
        *self.histogram.get(&state).unwrap_or(&0)
    }

    fn update_histogram(&mut self, bytes: u64, from: SectorState, to: SectorState) {
        *self.histogram.entry(from).or_insert(0) -= bytes;
        *self.histogram.entry(to).or_insert(0) += bytes;
    }

    fn do_phase(&mut self) -> Result<(), Box<Error>> {
        let phase_target = self.phase_target;
        self.print_status(false);
        while self.get_histogram_value(phase_target) > 0 {
            self.do_pass()?;
            self.map_file.set_pos(0);
        }
        Ok(())
    }

    fn do_pass(&mut self) -> Result<(), Box<Error>> {
        let sectors_per_buffer = self.block.get_block_size_physical() / self.block.get_sector_size();
        let mut buffers: Vec<Buffer> = Vec::new();
        for _ in 0..NUM_BUFFERS {
            let buffer = self.block.create_io_buffer(sectors_per_buffer);
            buffers.push(buffer);
        }

        let mut pass_complete = false;
        while !pass_complete {
            let mut reads: Vec<Range<u64>> =
                (&self.map_file).iter_range(self.map_file.get_pos()..self.map_file.get_size())
                .filter(|r| r.tag == self.phase_target)
                .flat_map(|r| range_to_reads(&r.as_range(), &self.block))
                .take(READ_BATCH_SIZE).collect();

            pass_complete = reads.is_empty();
            while !reads.is_empty() || self.block.requests_pending() > 0 {
                while !reads.is_empty() && self.block.requests_avail() > 0 && !buffers.is_empty() {
                    let read = reads.pop().unwrap();
                    let mut buffer = buffers.pop().unwrap();
                    buffer.clear();
                    let request = Request::new(read.start, read.end - read.start, buffer);
                    self.block.submit_request(request)?;
                    let current_pos = self.map_file.get_pos();
                    self.map_file.set_pos(cmp::max(current_pos, read.end));
                }

                if (reads.is_empty() && self.block.requests_pending() > 0) || self.block.requests_avail() == 0 {
                    let request = self.block.get_completed_request()?;
                    let phase_target = self.phase_target;
                    if request.result > 0 {
                        if !request.is_data_zeros() {
                            self.out_file.seek(SeekFrom::Start(request.offset))?;
                            self.out_file.write_all(request.get_data())?;
                        }
                        self.update_histogram(request.result as u64, phase_target, SectorState::Rescued);
                        self.map_file.put(request.offset..(request.offset + request.result as u64), SectorState::Rescued);
                    } else {
                        self.update_histogram(request.size as u64, phase_target, SectorState::Bad);
                        self.map_file.put(request.offset..(request.offset + request.size), SectorState::Bad);
                    };
                    buffers.push(request.reclaim_buffer());

                    let now = Instant::now();
                    self.print_status(true);
                    if now.duration_since(self.last_sync.clone()).as_secs() >= SYNC_INTERVAL as u64 {
                        self.do_sync()?;
                    }
                }
            }
        }
        self.do_sync()?;
        Ok(())
        /*
        let end_time = Instant::now();
        let duration = end_time.duration_since(start_time);
        let duration_secs = (duration.as_secs() as f64) + (duration.subsec_nanos() as f64 * 1e-9);
        println!("Recovered: {} bytes, failed: {} bytes, duration: {:.2} seconds.", recovered, failed, duration_secs);
        println!("Recovered at {:.1} KiB/s, failed at {:.1} KiB/s, total: {:.1} KiB/s.",
                 recovered as f64 / 1024.0 / duration_secs,
                 failed as f64 / 1024.0 / duration_secs,
                 (recovered + failed) as f64 / 1024.0 / duration_secs);
        */
    }
}

fn main() {
    do_work().unwrap();
}

fn do_work() -> Result<(), Box<Error>> {
    let mut recover = Recover::new("/dev/sda", "./test.img", "./drive.map")?;
    recover.do_phase()?;
    Ok(())
}

struct ReadIter {
    start: u64,
    end: u64,
    physical_block_size: usize,
}

impl Iterator for ReadIter {
    type Item = Range<u64>;

    fn next(&mut self) -> Option<Self::Item> {
        let physical_block_size = self.physical_block_size as u64;
        if self.start < self.end {
            let read_end = cmp::min(((self.start + physical_block_size) / physical_block_size) * physical_block_size, self.end);
            let result = self.start..read_end;
            self.start = read_end;
            Some(result)
        } else {
            None
        }
    }
}

fn range_to_reads(range: &Range<u64>, block: &BlockDevice) -> ReadIter {
    let sector_size = block.get_sector_size();
    let physical_block_size = block.get_block_size_physical();
    let size_bytes = block.get_size_bytes();
    assert!(physical_block_size % sector_size == 0);

    let sector_size_u64 = sector_size as u64;
    let start = (range.start / sector_size_u64) * sector_size_u64;
    let end = cmp::max(((range.end + sector_size_u64 - 1) / sector_size_u64) * sector_size_u64, size_bytes);
    ReadIter {
        start: start,
        end: end,
        physical_block_size: physical_block_size,
    }
}
<commit_msg>Simplify buffer caching.<commit_after>extern crate ddarecover;
extern crate ansi_escapes;

use ddarecover::block::{BlockDevice, Buffer, Request};
use ddarecover::map_file::{MapFile, SectorState};
use ddarecover::out_file::OutFile;
use std::cmp;
use std::error::Error;
use std::fs::File;
use std::ops::Range;
use std::time::Instant;
use std::path::{Path, PathBuf};
use std::io::{self, Seek, SeekFrom, Write};
use std::collections::HashMap;

const READ_BATCH_SIZE: usize = 256;
const SYNC_INTERVAL: usize = 60;

struct Recover {
    block: BlockDevice,
    map_file: MapFile,
    map_file_path: PathBuf,
    out_file: OutFile,
    start: Instant,
    last_sync: Instant,
    histogram: HashMap<SectorState, u64>,
    phase_target: SectorState,
    buffer_cache: Vec<Buffer>,
}

impl Recover {
    pub fn new(infile_path: &str, outfile_path: &str, mapfile_path: &str) -> io::Result<Recover> {
        let block = BlockDevice::open(infile_path).expect("Unable to open block device");
        let map_path = Path::new(mapfile_path);
        let map = if map_path.exists() {
            let map_file = File::open(map_path).expect("Unable to open existing map file");
            MapFile::read_from_stream(map_file).expect("Error reading map file")
        } else {
            let map = MapFile::new(block.get_size_bytes());
            map.write_to_path(map_path).expect("Unable to create new map file");
            map
        };
        assert_eq!(map.get_size_bytes(), block.get_size_bytes(), "Mismatch between device size and map file");
        let outfile_path = Path::new(outfile_path);
        let outfile = OutFile::open(outfile_path, block.get_size_bytes()).expect("Unable to open output file");

        let histogram = map.get_histogram();
        let result = Recover {
            block: block,
            map_file: map,
            map_file_path: map_path.to_path_buf(),
            out_file: outfile,
            start: Instant::now(),
            last_sync: Instant::now(),
            histogram: histogram,
            phase_target: SectorState::Untried,
            buffer_cache: Vec::new(),
        };
        Ok(result)
    }

    fn do_sync(&mut self) -> io::Result<()> {
        self.out_file.sync()?;
        self.map_file.write_to_path(&self.map_file_path)?;
        self.last_sync = Instant::now();
        Ok(())
    }

    fn print_status(&self, overwrite: bool) {
        if overwrite {
            print!("{}", ansi_escapes::EraseLines(5));
        }
        println!("Press Ctrl+C to exit.");
        println!("{:>15}: {:15} {:>15}: {:15} {:>15}: {:15}",
                 "ipos", self.format_bytes(self.map_file.get_pos()),
                 "rescued", self.get_histogram_value_formatted(SectorState::Rescued),
                 "bad", self.get_histogram_value_formatted(SectorState::Bad));

        println!("{:>15}: {:15} {:>15}: {:15} {:>15}: {:15}",
                 "non-tried", self.get_histogram_value_formatted(SectorState::Untried),
                 "non-trimmed", self.get_histogram_value_formatted(SectorState::Untrimmed),
                 "non-scraped", self.get_histogram_value_formatted(SectorState::Unscraped));

        let now = Instant::now();
        let run_time_seconds =  now.duration_since(self.start).as_secs();
        println!("{:>15}: {:15}", "run time", self.format_seconds(run_time_seconds));
    }

    fn format_bytes(&self, bytes: u64) -> String {
        let units = ["KiB", "MiB", "GiB"];
        let mut res_unit = "B";
        let mut res_bytes = bytes as f64;
        for unit in units.iter() {
            if res_bytes >= 1000000.0 {
                res_bytes /= 1024.0;
                res_unit = *unit;
            }
        }
        format!("{:.1} {}", res_bytes, res_unit)
    }

    fn format_seconds(&self, seconds: u64) -> String {
        let mut result = String::new();
        let mut value = seconds;
        for &(unit, multiple) in [("s", 60), ("m", 60), ("h", 24), ("d", usize::max_value())].iter() {
            let multiple = multiple as u64;
            result = format!(" {}{} {}", value % multiple, unit, result);
            value /= multiple;

            if value == 0 {
                break;
            }
        }
        result.trim().to_string()
    }

    fn get_histogram_value_formatted(&self, state: SectorState) -> String {
        self.format_bytes(self.get_histogram_value(state))
    }

    fn get_histogram_value(&self, state: SectorState) -> u64 {
        *self.histogram.get(&state).unwrap_or(&0)
    }

    fn update_histogram(&mut self, bytes: u64, from: SectorState, to: SectorState) {
        *self.histogram.entry(from).or_insert(0) -= bytes;
        *self.histogram.entry(to).or_insert(0) += bytes;
    }

    fn do_phase(&mut self) -> Result<(), Box<Error>> {
        let phase_target = self.phase_target;
        self.print_status(false);
        while self.get_histogram_value(phase_target) > 0 {
            self.do_pass()?;
            self.map_file.set_pos(0);
        }
        Ok(())
    }

    fn get_cleared_buffer(&mut self) -> Buffer {
        let sectors_per_buffer = self.block.get_block_size_physical() / self.block.get_sector_size();
        let mut buffer = match self.buffer_cache.pop() {
            Some(buffer) => buffer,
            None => self.block.create_io_buffer(sectors_per_buffer),
        };
        buffer.clear();
        buffer
    }

    fn recycle_buffer(&mut self, buffer: Buffer) {
        self.buffer_cache.push(buffer)
    }

    fn do_pass(&mut self) -> Result<(), Box<Error>> {
        let mut pass_complete = false;
        while !pass_complete {
            let mut reads: Vec<Range<u64>> =
                (&self.map_file).iter_range(self.map_file.get_pos()..self.map_file.get_size())
                .filter(|r| r.tag == self.phase_target)
                .flat_map(|r| range_to_reads(&r.as_range(), &self.block))
                .take(READ_BATCH_SIZE).collect();

            pass_complete = reads.is_empty();
            while !reads.is_empty() || self.block.requests_pending() > 0 {
                while !reads.is_empty() && self.block.requests_avail() > 0 {
                    let read = reads.pop().unwrap();
                    let mut buffer = self.get_cleared_buffer();
                    buffer.clear();
                    let request = Request::new(read.start, read.end - read.start, buffer);
                    self.block.submit_request(request)?;
                    let current_pos = self.map_file.get_pos();
                    self.map_file.set_pos(cmp::max(current_pos, read.end));
                }

                if (reads.is_empty() && self.block.requests_pending() > 0) || self.block.requests_avail() == 0 {
                    let request = self.block.get_completed_request()?;
                    let phase_target = self.phase_target;
                    if request.result > 0 {
                        if !request.is_data_zeros() {
                            self.out_file.seek(SeekFrom::Start(request.offset))?;
                            self.out_file.write_all(request.get_data())?;
                        }
                        self.update_histogram(request.result as u64, phase_target, SectorState::Rescued);
                        self.map_file.put(request.offset..(request.offset + request.result as u64), SectorState::Rescued);
                    } else {
                        self.update_histogram(request.size as u64, phase_target, SectorState::Bad);
                        self.map_file.put(request.offset..(request.offset + request.size), SectorState::Bad);
                    };
                    self.recycle_buffer(request.reclaim_buffer());

                    let now = Instant::now();
                    self.print_status(true);
                    if now.duration_since(self.last_sync.clone()).as_secs() >= SYNC_INTERVAL as u64 {
                        self.do_sync()?;
                    }
                }
            }
        }
        self.do_sync()?;
        Ok(())
        /*
        let end_time = Instant::now();
        let duration = end_time.duration_since(start_time);
        let duration_secs = (duration.as_secs() as f64) + (duration.subsec_nanos() as f64 * 1e-9);
        println!("Recovered: {} bytes, failed: {} bytes, duration: {:.2} seconds.", recovered, failed, duration_secs);
        println!("Recovered at {:.1} KiB/s, failed at {:.1} KiB/s, total: {:.1} KiB/s.",
                 recovered as f64 / 1024.0 / duration_secs,
                 failed as f64 / 1024.0 / duration_secs,
                 (recovered + failed) as f64 / 1024.0 / duration_secs);
        */
    }
}

fn main() {
    do_work().unwrap();
}

fn do_work() -> Result<(), Box<Error>> {
    let mut recover = Recover::new("/dev/sda", "./test.img", "./drive.map")?;
    recover.do_phase()?;
    Ok(())
}

struct ReadIter {
    start: u64,
    end: u64,
    physical_block_size: usize,
}

impl Iterator for ReadIter {
    type Item = Range<u64>;

    fn next(&mut self) -> Option<Self::Item> {
        let physical_block_size = self.physical_block_size as u64;
        if self.start < self.end {
            let read_end = cmp::min(((self.start + physical_block_size) / physical_block_size) * physical_block_size, self.end);
            let result = self.start..read_end;
            self.start = read_end;
            Some(result)
        } else {
            None
        }
    }
}

fn range_to_reads(range: &Range<u64>, block: &BlockDevice) -> ReadIter {
    let sector_size = block.get_sector_size();
    let physical_block_size = block.get_block_size_physical();
    let size_bytes = block.get_size_bytes();
    assert!(physical_block_size % sector_size == 0);

    let sector_size_u64 = sector_size as u64;
    let start = (range.start / sector_size_u64) * sector_size_u64;
    let end = cmp::max(((range.end + sector_size_u64 - 1) / sector_size_u64) * sector_size_u64, size_bytes);
    ReadIter {
        start: start,
        end: end,
        physical_block_size: physical_block_size,
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Write;

#[derive(Debug, PartialEq, Clone)]
pub enum Token {
    Unknown(String), // Invalid test (basically non-ascii)
    Literal(String), // Numeric literal number
    Func(Function), // Pre-defined function (like cos() )
    Const(Constant), // Constant like pi or e
    Var(String), // str arbitrary single char variable name
    Op(Operator), // Any of the 4 operators (+-*/)
    Open, // Open parens '('
    Close, // Closing parens ')'
    Set(Vec<Token>), // [ (, tokens..., ) ]
}

#[derive(Debug, PartialEq, Clone)]
pub enum Function {
    Sqrt(Vec<Token>),
    Ln(Vec<Token>),
    Log(f64, Vec<Token>),
    Sin(Vec<Token>),
    Cos(Vec<Token>),
    Tan(Vec<Token>),
    Asin(Vec<Token>),
    Acos(Vec<Token>),
    Atan(Vec<Token>),
    Sinh(Vec<Token>),
    Cosh(Vec<Token>),
    Tanh(Vec<Token>),
    Asinh(Vec<Token>),
    Acosh(Vec<Token>),
    Atanh(Vec<Token>),
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Constant {
	Pi,
	E,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Operator {
    Add,
    Sub,
    Div,
    Mul,
    Pow,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
pub enum Assoc {
    Left,
    Right,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
pub enum Order {
    AddSub = 1,
    MulDiv = 2,
    IMul = 3, // Implicit multiplication
    Pow = 4,
    Paren = 5,
}

#[derive(Debug, PartialEq, Clone)]
struct Expression {
    tokens: Vec<Token>,
    constant: f64,
}

struct ExpressionIter<'a> {
	expr: &'a Expression,
	count: usize,
}

impl<'a> Iterator for ExpressionIter<'a> {
	type Item = &'a Token;
    fn next(&mut self) -> Option<&'a Token> {
    	let token = self.expr.get_tokens().get(self.count);
    	self.count += 1;
    	token
    }
}

#[allow(dead_code)]
impl Expression {
	fn new(tokens: Vec<Token>, constant: f64) -> Self {
		Expression {tokens: tokens, constant: constant}
	}

	fn push(&mut self, token: Token) {
		self.tokens.push(token);
	}

	fn update_constant(&mut self, constant: &f64) {
		self.constant += *constant;
	}

	fn get_constant(&self) -> f64 {
		self.constant
	}

	fn get_tokens(&self) -> &[Token] {
		self.tokens.as_slice()
	}

	fn get_mut_tokens(&mut self) -> &mut [Token] {
		self.tokens.as_mut_slice()
	}

	fn replace_token(&mut self, index: usize, new_token: Token) {
		self.tokens.remove(index);
		self.tokens.insert(index, new_token);
	}

	fn replace_all_tokens(&mut self, new_token: Vec<Token>) {
		self.tokens = new_token
	}

	fn find_first(&self, token: &Token) -> Option<usize> {
		for i in 0..self.tokens.len() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn find_last(&self, token: &Token) -> Option<usize> {
		for i in (0..self.tokens.len()).rev() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn split_at(&self, index: usize) -> (&[Token], &[Token]) {
		self.tokens.split_at(index)
	}

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

	fn iter(&self) -> ExpressionIter {
		ExpressionIter {expr: &self, count: 0}
	}
}

fn main() {
    println!("Welcome to Rust-Calculus!");
    println!("To evaluate an expression, simply type one in and hit RETURN.");
    println!("To set a variable, simply type VAR_NAME=EXPRESSION and hit RETURN.");
    println!("Valid commands are: sym_int, int, sym_def, and def.");
    println!("Type 'quit' to exit.");
    let mut input = String::new();
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    loop {
    	input.clear();
    	print!(">>>> ");
    	stdout.flush().ok();
        if let Err(x) = stdin.read_line(&mut input) {
        	println!("There was a problem reading stdin: {:?}", x);
        	print!("Exiting...");;
        	break;
        }
        input = strip_white_space(&input);
        input = input.to_lowercase();
        if input == "quit" {
        	print!("Exiting...");
        	break;
        }
        let expr = match parse_input(&input) {
        		Ok(x) => x,
        		Err(x) => {println!("Encountered an error while parsing: {:?}", x); print!("Exiting..."); break;},
        	};
        println!("{:?}", &expr);
    }
}

fn strip_white_space(input: &String) -> String {
	input.split_whitespace().collect::<Vec<&str>>().join("")
}

fn parse_input(input: &String) -> Result<Expression, String> {
	let mut expr: Expression = Expression::new(Vec::new(), 0.0);
	for c in input.chars() {
		match c {
			'-' => {
				expr.push(Token::Op(Operator::Sub));
			},
			'+' => {
				expr.push(Token::Op(Operator::Add));
			},
			'/' => {
				expr.push(Token::Op(Operator::Div));
			},
			'*' => {
				expr.push(Token::Op(Operator::Mul));
			},
			'^' => {
				expr.push(Token::Op(Operator::Pow));
			},
			'(' => {
				expr.push(Token::Open);
			},
			')' => {
				expr.push(Token::Close);
			},
			_ => continue,
		}
	}
	// Once we find an outermost (), split the rest of the expression after that off into a new vector
	//let mut expr_vecs: Vec<Vec<Token>> = Vec::new();
	while let Some(index) = expr.find_first(&Token::Open) { // If we find an index of an Open
		let end_set: usize = expr.find_last(&Token::Close).unwrap(); // Finds the last Close, need to find the one that actually matches the proper Open (if two Sets are on same depth)
		let mut lhs: Vec<Token> = Vec::new();
		{
			let (temp_lhs, temp_rhs) = expr.split_at(index); // [0, where set should be placed)
			lhs = temp_lhs.to_vec();
			let mut rhs = temp_rhs.to_vec(); // [where set should be placed, len)
			rhs.remove(0);
			let (left_rhs, right_rhs) = rhs.split_at(end_set-1);
			let (left_rhs, mut right_rhs) = (left_rhs.to_vec(), right_rhs.to_vec());
			right_rhs.remove(0);
			lhs.push(Token::Set(left_rhs));
			lhs.append(&mut right_rhs);
		}
		for i in (0..lhs.len()).rev() {
			if lhs.get(i).unwrap() == &Token::Close {
				lhs.remove(i);
				break;
			}
		}
		expr.replace_all_tokens(lhs);
	}
	Ok(expr)
}

#[test]
fn test_parse() {
	let input: String = String::from("+");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Add)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("-");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Sub)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("/");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Div)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("*");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Mul)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("^");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Pow)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("()");
	assert_eq!(Expression::new(vec![Token::Set(Vec::new())], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(+)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Add)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(-)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Sub)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(*)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Mul)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(/)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Div)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(^)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Pow)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(())");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Set(Vec::new())])], 0.0), parse_input(&input).unwrap());
}<commit_msg>Combined a function call into one line<commit_after>use std::io;
use std::io::Write;

#[derive(Debug, PartialEq, Clone)]
pub enum Token {
    Unknown(String), // Invalid test (basically non-ascii)
    Literal(String), // Numeric literal number
    Func(Function), // Pre-defined function (like cos() )
    Const(Constant), // Constant like pi or e
    Var(String), // str arbitrary single char variable name
    Op(Operator), // Any of the 4 operators (+-*/)
    Open, // Open parens '('
    Close, // Closing parens ')'
    Set(Vec<Token>), // [ (, tokens..., ) ]
}

#[derive(Debug, PartialEq, Clone)]
pub enum Function {
    Sqrt(Vec<Token>),
    Ln(Vec<Token>),
    Log(f64, Vec<Token>),
    Sin(Vec<Token>),
    Cos(Vec<Token>),
    Tan(Vec<Token>),
    Asin(Vec<Token>),
    Acos(Vec<Token>),
    Atan(Vec<Token>),
    Sinh(Vec<Token>),
    Cosh(Vec<Token>),
    Tanh(Vec<Token>),
    Asinh(Vec<Token>),
    Acosh(Vec<Token>),
    Atanh(Vec<Token>),
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Constant {
	Pi,
	E,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Operator {
    Add,
    Sub,
    Div,
    Mul,
    Pow,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
pub enum Assoc {
    Left,
    Right,
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[repr(u32)]
pub enum Order {
    AddSub = 1,
    MulDiv = 2,
    IMul = 3, // Implicit multiplication
    Pow = 4,
    Paren = 5,
}

#[derive(Debug, PartialEq, Clone)]
struct Expression {
    tokens: Vec<Token>,
    constant: f64,
}

struct ExpressionIter<'a> {
	expr: &'a Expression,
	count: usize,
}

impl<'a> Iterator for ExpressionIter<'a> {
	type Item = &'a Token;
    fn next(&mut self) -> Option<&'a Token> {
    	let token = self.expr.get_tokens().get(self.count);
    	self.count += 1;
    	token
    }
}

#[allow(dead_code)]
impl Expression {
	fn new(tokens: Vec<Token>, constant: f64) -> Self {
		Expression {tokens: tokens, constant: constant}
	}

	fn push(&mut self, token: Token) {
		self.tokens.push(token);
	}

	fn update_constant(&mut self, constant: &f64) {
		self.constant += *constant;
	}

	fn get_constant(&self) -> f64 {
		self.constant
	}

	fn get_tokens(&self) -> &[Token] {
		self.tokens.as_slice()
	}

	fn get_mut_tokens(&mut self) -> &mut [Token] {
		self.tokens.as_mut_slice()
	}

	fn replace_token(&mut self, index: usize, new_token: Token) {
		self.tokens.remove(index);
		self.tokens.insert(index, new_token);
	}

	fn replace_all_tokens(&mut self, new_token: Vec<Token>) {
		self.tokens = new_token
	}

	fn find_first(&self, token: &Token) -> Option<usize> {
		for i in 0..self.tokens.len() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn find_last(&self, token: &Token) -> Option<usize> {
		for i in (0..self.tokens.len()).rev() {
			if self.tokens.get(i).unwrap() == token {
				return Some(i);
			}
		}
		None
	}

	fn split_at(&self, index: usize) -> (&[Token], &[Token]) {
		self.tokens.split_at(index)
	}

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

	fn iter(&self) -> ExpressionIter {
		ExpressionIter {expr: &self, count: 0}
	}
}

fn main() {
    println!("Welcome to Rust-Calculus!");
    println!("To evaluate an expression, simply type one in and hit RETURN.");
    println!("To set a variable, simply type VAR_NAME=EXPRESSION and hit RETURN.");
    println!("Valid commands are: sym_int, int, sym_def, and def.");
    println!("Type 'quit' to exit.");
    let mut input = String::new();
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    loop {
    	input.clear();
    	print!(">>>> ");
    	stdout.flush().ok();
        if let Err(x) = stdin.read_line(&mut input) {
        	println!("There was a problem reading stdin: {:?}", x);
        	print!("Exiting...");;
        	break;
        }
        input = strip_white_space(&input).to_lowercase();
        if input == "quit" {
        	print!("Exiting...");
        	break;
        }
        let expr = match parse_input(&input) {
        		Ok(x) => x,
        		Err(x) => {println!("Encountered an error while parsing: {:?}", x); print!("Exiting..."); break;},
        	};
        println!("{:?}", &expr);
    }
}

fn strip_white_space(input: &String) -> String {
	input.split_whitespace().collect::<Vec<&str>>().join("")
}

fn parse_input(input: &String) -> Result<Expression, String> {
	let mut expr: Expression = Expression::new(Vec::new(), 0.0);
	for c in input.chars() {
		match c {
			'-' => {
				expr.push(Token::Op(Operator::Sub));
			},
			'+' => {
				expr.push(Token::Op(Operator::Add));
			},
			'/' => {
				expr.push(Token::Op(Operator::Div));
			},
			'*' => {
				expr.push(Token::Op(Operator::Mul));
			},
			'^' => {
				expr.push(Token::Op(Operator::Pow));
			},
			'(' => {
				expr.push(Token::Open);
			},
			')' => {
				expr.push(Token::Close);
			},
			_ => continue,
		}
	}
	// Once we find an outermost (), split the rest of the expression after that off into a new vector
	//let mut expr_vecs: Vec<Vec<Token>> = Vec::new();
	while let Some(index) = expr.find_first(&Token::Open) { // If we find an index of an Open
		let end_set: usize = expr.find_last(&Token::Close).unwrap(); // Finds the last Close, need to find the one that actually matches the proper Open (if two Sets are on same depth)
		let mut lhs: Vec<Token> = Vec::new();
		{
			let (temp_lhs, temp_rhs) = expr.split_at(index); // [0, where set should be placed)
			lhs = temp_lhs.to_vec();
			let mut rhs = temp_rhs.to_vec(); // [where set should be placed, len)
			rhs.remove(0);
			let (left_rhs, right_rhs) = rhs.split_at(end_set-1);
			let (left_rhs, mut right_rhs) = (left_rhs.to_vec(), right_rhs.to_vec());
			right_rhs.remove(0);
			lhs.push(Token::Set(left_rhs));
			lhs.append(&mut right_rhs);
		}
		for i in (0..lhs.len()).rev() {
			if lhs.get(i).unwrap() == &Token::Close {
				lhs.remove(i);
				break;
			}
		}
		expr.replace_all_tokens(lhs);
	}
	Ok(expr)
}

#[test]
fn test_parse() {
	let input: String = String::from("+");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Add)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("-");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Sub)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("/");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Div)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("*");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Mul)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("^");
	assert_eq!(Expression::new(vec![Token::Op(Operator::Pow)], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("()");
	assert_eq!(Expression::new(vec![Token::Set(Vec::new())], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(+)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Add)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(-)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Sub)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(*)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Mul)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(/)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Div)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(^)");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Op(Operator::Pow)])], 0.0), parse_input(&input).unwrap());
	let input: String = String::from("(())");
	assert_eq!(Expression::new(vec![Token::Set(vec![Token::Set(Vec::new())])], 0.0), parse_input(&input).unwrap());
}<|endoftext|>


<commit_before>/* Stones esoteric programming language
 * (c) 2016 Zack Hixon - see LICENSE.txt */

extern crate argparse;

use argparse::{ArgumentParser, StoreTrue, Store};

use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::error::Error;
use std::process;

#[derive(Debug)]
enum Color {
    Red,
    Orange,
    Yellow,
    Green,
    Blue,
    Purple,
    Invis
}

fn main() {
    let mut field: Vec<Vec<Color>> = /* so much for 80 columns */
        vec![vec![Color::Blue,  Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Orange,Color::Invis, Color::Invis, Color::Invis, Color::Invis ],
             vec![Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis ],
             vec![Color::Invis, Color::Invis, Color::Red,   Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Green, Color::Invis, Color::Invis ],
             vec![Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis ],
             vec![Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Yellow,Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Purple],
             vec![Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis ]];

    let mut debug = false;
    let mut filename: String = "".into();

    {
        let mut args = ArgumentParser::new();
        args.set_description("Run a stones language file");
        args.refer(&mut debug)
            .add_option(&["-d", "--debug"], StoreTrue, "Run debugging");
        args.refer(&mut filename)
            .add_argument("file", Store, "File to run")
            .required();
        args.parse_args_or_exit();
    }

    /* open file */
    let path = Path::new(&filename);
    let display = path.display();

    let mut file = match File::open(&path) {
        Ok(file) => file,
        Err(_) => {
                println!("File doesn't exist: {}", display);
                std::process::exit(1);
            }
    };

    let mut s = String::new();
    match file.read_to_string(&mut s) {
        Ok(_) => println!("Opened file, yay!"),
        Err(e) => panic!("Couldn't read {}: {}", display, e.description()),
    }

    /* split file into tokens */
    let tokens: Vec<&str> = s.split_whitespace().collect();

    for token in tokens {
        println!("{}", token);
    }

    if debug {
        for row in &field {
            for color in row {
                match color {
                    &Color::Red => print!("{:?}... ", color),
                    &Color::Orange => print!("{:?} ", color),
                    &Color::Yellow => print!("{:?} ", color),
                    &Color::Green => print!("{:?}. ", color),
                    &Color::Blue => print!("{:?}.. ", color),
                    &Color::Purple => print!("{:?} ", color),
                    &Color::Invis => print!("...... "), /* oh. */
                }
            }
            println!("");
        }
    }
}

<commit_msg>Move stuff around<commit_after>/* Stones esoteric programming language
 * (c) 2016 Zack Hixon - see LICENSE.txt */

extern crate argparse;

use argparse::{ArgumentParser, StoreTrue, Store};

use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::error::Error;
use std::process;

#[derive(Debug)]
enum Color {
    Red,
    Orange,
    Yellow,
    Green,
    Blue,
    Purple,
    Invis
}

fn main() {
    let mut debug = false;
    let mut filename: String = "".into();

    {
        let mut args = ArgumentParser::new();
        args.set_description("Run a stones language file");
        args.refer(&mut debug)
            .add_option(&["-d", "--debug"], StoreTrue, "Run debugging");
        args.refer(&mut filename)
            .add_argument("file", Store, "File to run")
            .required();
        args.parse_args_or_exit();
    }

    /* open file */
    let path = Path::new(&filename);
    let display = path.display();

    let mut file = match File::open(&path) {
        Ok(file) => file,
        Err(_) => {
                println!("File doesn't exist: {}", display);
                std::process::exit(1);
            }
    };

    let mut s = String::new();
    match file.read_to_string(&mut s) {
        Ok(_) => println!("Opened file, yay!"),
        Err(e) => panic!("Couldn't read {}: {}", display, e.description()),
    }

    /* split file into tokens */
    let tokens: Vec<&str> = s.split_whitespace().collect();

    let mut field: Vec<Vec<Color>> = /* so much for 80 columns */
        vec![vec![Color::Blue,  Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Orange,Color::Invis, Color::Invis, Color::Invis, Color::Invis ],
             vec![Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis ],
             vec![Color::Invis, Color::Invis, Color::Red,   Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Green, Color::Invis, Color::Invis ],
             vec![Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis ],
             vec![Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Yellow,Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Purple],
             vec![Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis, Color::Invis ]];

    let mut stack: Vec<i64> = vec![];

    let mut expect_number = false;
    let mut expect_direction = false;
    let mut expect_color = true;
    let mut current_stone = Color::Invis;

    /* execute program */
    for token in tokens {
        if debug {
            for row in &field {
                for color in row {
                    match color {
                        &Color::Red => print!("{:?}... ", color),
                        &Color::Orange => print!("{:?} ", color),
                        &Color::Yellow => print!("{:?} ", color),
                        &Color::Green => print!("{:?}. ", color),
                        &Color::Blue => print!("{:?}.. ", color),
                        &Color::Purple => print!("{:?} ", color),
                        &Color::Invis => print!("...... "), /* oh. */
                    }
                }
                println!("");
            }
        }
    }
}

<|endoftext|>


<commit_before>extern crate argparse;

extern crate marafet_parser as parser;
extern crate marafet_css as css;
extern crate marafet_es5citojs as es5citojs;

use std::fs::File;
use std::io::{Read, stdout};
use std::path::PathBuf;

use argparse::{ArgumentParser, Parse, ParseOption, Collect, StoreTrue};

fn main() {
    let mut source = PathBuf::new();
    let mut use_amd = false;
    let mut amd_name = None::<String>;
    let mut output_js = None::<PathBuf>;
    let mut output_css = None::<PathBuf>;
    let mut block_name = None::<String>;
    let mut vars = Vec::<String>::new();
    let mut print_ast = false;
    let mut css_load = false;
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Compiles .mft file to a CSS and/or JS file");
        ap.refer(&mut source)
            .required()
            .add_option(&["-f", "--file"], Parse, "Input file name");
        ap.refer(&mut output_js)
            .add_option(&["--js"], ParseOption, "Output JS file");
        ap.refer(&mut output_css)
            .add_option(&["--css"], ParseOption, "Output CSS file");
        ap.refer(&mut use_amd)
            .add_option(&["--amd"], StoreTrue, "Output AMD module");
        ap.refer(&mut amd_name)
            .add_option(&["--amd-name"], ParseOption,
                "Set AMD name for module");
        ap.refer(&mut block_name)
            .add_option(&["--block-name"], ParseOption,
                "Set block name (this is a name of CSS class that will be \
                 prepended to every classname in CSS and HTML to limit scope \
                 of style for this block only). By default derived from file \
                 name");
        ap.refer(&mut vars)
            .add_option(&["--css-var"], Collect, "Set CSS variable");
        ap.refer(&mut print_ast)
            .add_option(&["--print-ast"], StoreTrue, "Print AST to stdout");
        ap.refer(&mut css_load)
            .add_option(&["--auto-load-css"], StoreTrue,
                "Insert css load code to the Javascript code");
        ap.parse_args_or_exit();
    }

    let mut buf = Vec::new();
    File::open(&source).and_then(|mut f| f.read_to_end(&mut buf)).unwrap();
    let body = String::from_utf8(buf).unwrap();
    let ast = parser::parse_string(&body[..]).unwrap();

    println!("--- Ast ---");
    println!("{:?}", ast);

    let block_name = block_name.unwrap_or(
            String::from(source.file_stem().unwrap().to_str().unwrap()));

    println!("--- Css ---");
    css::generate(&mut stdout(), &ast, &css::Settings {
        block_name: &block_name,
        vars: &Default::default(),
        }).unwrap();
    println!("--- JS ---");
    let css_text = if css_load {
        let mut buf = Vec::new();
        css::generate(&mut buf, &ast, &css::Settings {
            block_name: &block_name,
            vars: &Default::default(),
            }).unwrap();
        Some(String::from_utf8(buf).unwrap())
    } else {
        None
    };
    es5citojs::generate(&mut stdout(), &ast, &es5citojs::Settings {
        block_name: &block_name[..],
        css_text: css_text.as_ref().map(|x| &x[..]),
        use_amd: use_amd,
        amd_name: amd_name.as_ref().map(|x| &x[..]).unwrap_or(
            source.with_extension("").to_str().unwrap()),
    }).unwrap();
}

<commit_msg>Add working `--js` option<commit_after>extern crate argparse;

extern crate marafet_parser as parser;
extern crate marafet_css as css;
extern crate marafet_es5citojs as es5citojs;

use std::fs::File;
use std::io::{Read, BufWriter};
use std::path::PathBuf;
use std::process::exit;

use argparse::{ArgumentParser, Parse, ParseOption, Collect, StoreTrue};

fn main() {
    let mut source = PathBuf::new();
    let mut use_amd = false;
    let mut amd_name = None::<String>;
    let mut output_js = None::<PathBuf>;
    let mut output_css = None::<PathBuf>;
    let mut block_name = None::<String>;
    let mut vars = Vec::<String>::new();
    let mut print_ast = false;
    let mut css_load = false;
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("Compiles .mft file to a CSS and/or JS file");
        ap.refer(&mut source)
            .required()
            .add_option(&["-f", "--file"], Parse, "Input file name");
        ap.refer(&mut output_js)
            .add_option(&["--js"], ParseOption, "Output JS file");
        ap.refer(&mut output_css)
            .add_option(&["--css"], ParseOption, "Output CSS file");
        ap.refer(&mut use_amd)
            .add_option(&["--amd"], StoreTrue, "Output AMD module");
        ap.refer(&mut amd_name)
            .add_option(&["--amd-name"], ParseOption,
                "Set AMD name for module");
        ap.refer(&mut block_name)
            .add_option(&["--block-name"], ParseOption,
                "Set block name (this is a name of CSS class that will be \
                 prepended to every classname in CSS and HTML to limit scope \
                 of style for this block only). By default derived from file \
                 name");
        ap.refer(&mut vars)
            .add_option(&["--css-var"], Collect, "Set CSS variable");
        ap.refer(&mut print_ast)
            .add_option(&["--print-ast"], StoreTrue, "Print AST to stdout");
        ap.refer(&mut css_load)
            .add_option(&["--auto-load-css"], StoreTrue,
                "Insert css load code to the Javascript code");
        ap.parse_args_or_exit();
    }

    let block_name = block_name.unwrap_or(
            String::from(source.file_stem().unwrap().to_str().unwrap()));

    let mut buf = Vec::new();
    File::open(&source).and_then(|mut f| f.read_to_end(&mut buf)).unwrap();
    let body = String::from_utf8(buf).unwrap();
    let ast = parser::parse_string(&body[..]).unwrap();

    if print_ast {
        println!("--- Ast ---");
        println!("{:?}", ast);
    }

    // println!("--- Css ---");
    // css::generate(&mut stdout(), &ast, &css::Settings {
    //     block_name: &block_name,
    //     vars: &Default::default(),
    //     }).unwrap();

    let css_text = if css_load {
        let mut buf = Vec::new();
        css::generate(&mut buf, &ast, &css::Settings {
            block_name: &block_name,
            vars: &Default::default(),
            }).unwrap();
        let string = String::from_utf8(buf).unwrap();
        if print_ast {
            println!("--- CSS ---");
            println!("{}", string);
        }
        Some(string)
    } else {
        None
    };
    if let Some(filename) = output_js {
        let mut file = match File::create(&filename).map(BufWriter::new) {
            Ok(f) => f,
            Err(e) => {
                println!("Error opening file {:?}: {}", filename, e);
                exit(2);
            }
        };
        let res = es5citojs::generate(&mut file, &ast, &es5citojs::Settings {
            block_name: &block_name[..],
            css_text: css_text.as_ref().map(|x| &x[..]),
            use_amd: use_amd,
            amd_name: amd_name.as_ref().map(|x| &x[..]).unwrap_or(
                source.with_extension("").to_str().unwrap()),
        });
        if let Err(err) = res {
            println!("{}", err);
            exit(1);
        }
    }
}

<|endoftext|>


<commit_before>#![feature(test)]

mod args;
mod lib;

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let program = &args[0];
    let opts = args::build_opts();
    let (filename, number, min_entropy, ngram_length, min_word_length) =
        match args::parse_args(&opts, &args) {
            Ok(parsed_args) => parsed_args,
            Err(_) => {
                args::print_usage(program, &opts);
                return;
            }
        };

    let passphrases =
        match lib::gen_passphrases(filename, number, min_entropy, ngram_length, min_word_length) {
            Ok(passphrases) => passphrases,
            Err(e) => {
                eprintln!("{}: {}", program, e.description());
                return;
            }
        };

    for (passphrase, entropy) in passphrases {
        println!("{} <{}>", passphrase, entropy);
    }
}
<commit_msg>Return Result from main.<commit_after>#![feature(test)]

mod args;
mod lib;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let args: Vec<String> = std::env::args().collect();
    let program = &args[0];
    let opts = args::build_opts();
    let (filename, number, min_entropy, ngram_length, min_word_length) =
        args::parse_args(&opts, &args).map_err(|error| {
            args::print_usage(program, &opts);

            error
        })?;

    let passphrases =
        lib::gen_passphrases(filename, number, min_entropy, ngram_length, min_word_length)
            .map_err(|error| {
                eprintln!("{}: {}", program, error.description());

                error
            })?;

    for (passphrase, entropy) in passphrases {
        println!("{} <{}>", passphrase, entropy);
    }

    Ok(())
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nickel;
extern crate rustc_serialize;

use std::collections::HashMap;
use nickel::*;

fn main() {

   let mut nickel = Nickel::new();

   /*fn handler<'a>(_: &mut Request, res: Response<'a>) -> MiddlewareResult<'a> {
     let mut data = HashMap::<&str, &str>::new();
     data.insert("title", "nickel-bootstrap");
     data.insert("message", "Welcome to");
     data.insert("message_line_two", "You can edit this to get started...");

     res.render("templates/all_for_one.mustache", &data);
   }*/

   fn handler<'a>(_: &mut Request, res: Response<'a>) -> MiddlewareResult<'a> {
     let mut data = HashMap::<&str, &str>::new();
     data.insert("title", "nickel-bootstrap");
     data.insert("message", "Welcome to");
     data.insert("message_line_two", "You can edit this to get started...");
     res.render("templates/all_for_one.mustache", &data)
   }

   nickel.get("**", handler);

   nickel.utilize(StaticFilesHandler::new("public/"));

   nickel.utilize(middleware! { |request|
     println!("Request: {:?}", request.origin.uri);
   });

   nickel.listen("127.0.0.1:6767");
}
<commit_msg>fixed /<commit_after>#[macro_use]
extern crate nickel;
extern crate rustc_serialize;

use std::collections::HashMap;
use nickel::*;

fn main() {

   let mut nickel = Nickel::new();

   /*fn handler<'a>(_: &mut Request, res: Response<'a>) -> MiddlewareResult<'a> {
     let mut data = HashMap::<&str, &str>::new();
     data.insert("title", "nickel-bootstrap");
     data.insert("message", "Welcome to");
     data.insert("message_line_two", "You can edit this to get started...");

     res.render("templates/all_for_one.mustache", &data);
   }*/

   fn handler<'a>(_: &mut Request, res: Response<'a>) -> MiddlewareResult<'a> {
     let mut data = HashMap::<&str, &str>::new();
     data.insert("title", "nickel-bootstrap");
     data.insert("message", "Welcome to");
     data.insert("message_line_two", "You can edit this to get started...");
     res.render("templates/all_for_one.mustache", &data)
   }

   nickel.get("/", handler);

   nickel.utilize(StaticFilesHandler::new("public/"));

   nickel.utilize(middleware! { |request|
     println!("Request: {:?}", request.origin.uri);
   });

   nickel.listen("127.0.0.1:6767");
}
<|endoftext|>


<commit_before>#![feature(phase)]
extern crate serialize;
#[phase(plugin)] extern crate docopt_macros;
extern crate docopt;
extern crate core;
extern crate collections;

use docopt::FlagParser;
use std::io::BufferedReader;
use std::io::File;
use std::io::Lines;
use std::io::IoResult;
use core::result::Result;
use collections::string::String;
use collections::vec::Vec;

docopt!(Args, "
interleaver

Usage: interleaver FILENAMES...
")

fn main() {
  let args: Args = FlagParser::parse().unwrap_or_else(|e| e.exit());

  // The Args struct satisfies `Show`:
  println!("{}", args);

  let paths_it = args.arg_FILENAMES.iter ().map (|n| Path::new(n.clone ()));
  let files_it = paths_it.map (|path| File::open(&path));
  let mut readers_it = files_it.map (|file| BufferedReader::new (file));
  let readers_vec : Vec<BufferedReader<core::result::Result<std::io::fs::File,std::io::IoError>>> = readers_it.collect ();
  // let line_iterators = readers.map (|mut reader| reader.lines ());

  let c = args.arg_FILENAMES.len();

  // let mut candidates : Vec<Option<IoResult<String>>> = Vec::new ();

  // for line_iterator in line_iterators.iter () {
  //   // let line = line_iterator.next ();
  //   // candidates.push (line);
  // }

  // let path = Path::new("p054_poker.txt");

  // let mut file = BufferedReader::new(File::open(&path));
  // for line in file.lines() {
  //   let l = line.unwrap ();
  // }
}
<commit_msg>Mixing all files<commit_after>#![feature(phase)]
extern crate serialize;
#[phase(plugin)] extern crate docopt_macros;
extern crate docopt;
extern crate core;
extern crate collections;

use docopt::FlagParser;
use std::io::BufferedReader;
use std::io::File;
use core::result::Result;
use collections::string::String;
use collections::vec::Vec;

docopt!(Args, "
interleaver

Usage: interleaver FILENAMES...
", )

type BrType = BufferedReader<core::result::Result<std::io::fs::File,std::io::IoError>>;

fn main() {
  let args: Args = FlagParser::parse().unwrap_or_else(|e| e.exit());

  // The Args struct satisfies `Show`:
  println!("{}", args);

  let paths_it = args.arg_FILENAMES.iter ().map (|n| Path::new(n.clone ()));
  let files_it = paths_it.map (|path| File::open(&path));
  let mut buffered_readers_it = files_it.map (|file| BufferedReader::new (file));
  let mut buffered_readers_vec : Vec<BrType> = buffered_readers_it.collect ();

  let mut done;

  loop {
    done = true;
    for buffered_reader in buffered_readers_vec.mut_iter () {
      let mut lines = buffered_reader.lines ();
      match lines.next () {
        None => (),
        Some (line) => {
          println! ("{}", line);
          done = false;
        }
      }
    }
    if done { break; }
  }

  // let line_readers_it = buffered_readers_vec.iter().map (|mut buffered_reader| { buffered_reader.read_to_string(); });

  // let line_iterators = readers.map (|mut reader| reader.lines ());

  // let c = args.arg_FILENAMES.len();

  // let mut candidates : Vec<Option<IoResult<String>>> = Vec::new ();

  // for line_iterator in line_iterators.iter () {
  //   // let line = line_iterator.next ();
  //   // candidates.push (line);
  // }

  // let path = Path::new("p054_poker.txt");

  // let mut file = BufferedReader::new(File::open(&path));
  // for line in file.lines() {
  //   let l = line.unwrap ();
  // }
}
<|endoftext|>