<commit_before>#![feature(libc, fs_ext, path_ext, convert, fs, exit_status)]
#![allow(dead_code)]

extern crate crypto;
extern crate libc;

#[macro_use]
extern crate log;
extern crate env_logger;

use crypto::sha2::Sha512;
use crypto::digest::Digest;
use libc::{getgid, getuid};
use std::env;
use std::path::Path;
use std::os::unix::fs::PermissionsExt;
use std::io;
use std::io::{Read, Write};
use std::fs::{File, Permissions, create_dir_all,
              set_permissions, PathExt};
use std::process::{Command, Stdio};

const ALL_PERMISSIONS: usize = 0o0777;
const OTHER_EXECUTE: usize = 0o0001;
const OTHER_READ: usize = 0o0004;
const OTHER_RWX: usize = 0o0007;
const GROUP_EXECUTE: usize = 0o0010;
const GROUP_READ: usize = 0o0040;
const GROUP_RWX: usize = 0o0070;
const USER_EXECUTE: usize = 0o0100;
const USER_READ: usize = 0o0400;
const USER_RWX: usize = 0o0700;

trait PermExt2 {
    fn contains(&self, mask: usize) -> bool;
}

impl PermExt2 for Permissions {
    fn contains(&self, mask: usize) -> bool {
        self.mode() & (mask as i32) != 0
    }
}

const CACHE_SUBPATH: &'static str = "pexe-runner-cache";
// TODO: support overriding cache location.
const CACHE_BASE: &'static str = "/tmp";

const RUST_PNACL_TRANS: &'static str = "rust_pnacl_trans";

fn mkdir<P: AsRef<Path>>(p: P, mode: usize) -> io::Result<()> {
    try!(create_dir_all(&p));
    chmod(p, mode)
}
fn chmod<P: AsRef<Path>>(p: P, mode: usize) -> io::Result<()> {
    let p = p.as_ref();
    let md = try!(p.metadata());
    let mut perms = md.permissions();
    perms.set_mode(mode as i32);
    set_permissions(p, perms)
}

pub fn main() {
    env_logger::init().unwrap();

    let args: Vec<String> = env::args()
        .collect();
    let pexe_path = Path::new(&(args[1])[..]);

    let cache = Path::new(CACHE_BASE).join(CACHE_SUBPATH);
    if !cache.exists() {
        mkdir(&cache, ALL_PERMISSIONS).unwrap();
    }

    // if the binary is rx by the world, don't use a user prefix when caching.

    let pexe = File::open(&pexe_path);
    if pexe.is_err() {
        panic!("could not open Pexe file!");
    }
    let mut pexe = pexe.unwrap();

    let pexe_filename = Path::new(pexe_path.file_name().unwrap());

    let pexe_stat = pexe.metadata().unwrap();
    let (cache_dir, perms) = if pexe_stat.permissions().contains(OTHER_EXECUTE | OTHER_READ) {
        let c = cache.join("other");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        (c, ALL_PERMISSIONS)
    } else if pexe_stat.permissions().contains(GROUP_EXECUTE | GROUP_READ) {
        let c = cache.join("group");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        let gid = unsafe { getgid() };
        let c = c.join(format!("{}", gid));
        if !c.exists() {
            mkdir(&c, GROUP_RWX | USER_RWX).unwrap();
        }
        (c, GROUP_RWX | USER_RWX)
    } else if pexe_stat.permissions().contains(USER_EXECUTE) {
        let c = cache.join("user");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        let uid = unsafe { getuid() };
        let c = c.join(format!("{}", uid));
        if !c.exists() {
            mkdir(&c, USER_RWX).unwrap();
        }
        (c, USER_RWX)
    } else {
        panic!("cann't execute: permissing denied");
    };
    let mut pexe_bin = Vec::new();
    pexe.read_to_end(&mut pexe_bin)
        .unwrap();

    let mut hasher = Sha512::new();
    hasher.input(pexe_bin.as_slice());
    let cache_dir = cache_dir.join(hasher.result_str());
    if !cache_dir.exists() {
        mkdir(&cache_dir, perms).unwrap();
    }
    let nexe_path = cache_dir
        .join(pexe_filename.with_extension("nexe"));

    let nacl_sdk_root = env!("NACL_SDK_ROOT");

    if !nexe_path.exists() {
        let mut cmd = Command::new(RUST_PNACL_TRANS);
        cmd.arg("--cross-path");
        cmd.arg(nacl_sdk_root);
        cmd.arg(pexe_path.display().to_string());
        cmd.arg("-o");
        cmd.arg(nexe_path.display().to_string());
        cmd.arg("--opt-level=2");
        debug!("trans cmd line: `{:?}`", cmd);
        let trans = cmd.spawn().unwrap();

        let output = trans.wait_with_output().unwrap();
        let status = output.status;
        match status {
            _ if status.success() => {
                chmod(&nexe_path, perms).unwrap();
            }
            _ => {
                let mut stderr = ::std::io::stderr();
                let mut stdout = ::std::io::stdout();
                (writeln!(&mut stderr, "`{:?}` failed:", cmd)).unwrap();
                stdout.write(output.stdout.as_slice()).unwrap();
                stderr.write(output.stderr.as_slice()).unwrap();
                env::set_exit_status(status.code().unwrap_or(1));
                return;
            }
        }
    }

    let nacl_sdk_root = Path::new(nacl_sdk_root);
    let tools = nacl_sdk_root.join("tools");
    let nacl_helper_bootstrap = tools.join("nacl_helper_bootstrap_x86_64");
    let sel_ldr_bin = tools.join("sel_ldr_x86_64");
    let irt_core = tools.join("irt_core_x86_64.nexe");

    let mut sel_ldr_args = vec!(sel_ldr_bin.display().to_string(),
                                "--r_debug=0xXXXXXXXXXXXXXXXX".to_string(),
                                "--reserved_at_zero=0xXXXXXXXXXXXXXXXX".to_string());
    match env::var("ALLOW_FILE_ACCESS") {
        Ok(ref v) if v != "0" => {
            sel_ldr_args.push("-a".to_string());
        },
        _ => {},
    }
    sel_ldr_args.push("-B".to_string());
    sel_ldr_args.push(irt_core.display().to_string());
    sel_ldr_args.push("-l".to_string());
    sel_ldr_args.push("/dev/null".to_string());
    sel_ldr_args.push("--".to_string());
    sel_ldr_args.push(nexe_path.display().to_string());
    for arg in &args[2..] {
        sel_ldr_args.push(arg.clone());
    }

    let mut cmd = Command::new(nacl_helper_bootstrap);
    cmd.args(sel_ldr_args.as_slice());
    cmd.stdout(Stdio::inherit());
    cmd.stderr(Stdio::inherit());
    debug!("sel_ldr cmd line: `{:?}`", cmd);
    match cmd.spawn() {
        Ok(mut process) => {
            match process.wait() {
                Ok(status) => {
                    env::set_exit_status(status.code().unwrap_or(1));
                },
                Err(e) => {
                    panic!("couldn't wait on sel_ldr: {}", e);
                }
            }
        }
        Err(e) => {
            panic!("couldn't spawn sel_ldr: {}", e);
        }
    }
}
<commit_msg>Add an env var for starting a gdb server for debugging.<commit_after>#![feature(libc, fs_ext, path_ext, convert, fs, exit_status)]
#![allow(dead_code)]

extern crate crypto;
extern crate libc;

#[macro_use]
extern crate log;
extern crate env_logger;

use crypto::sha2::Sha512;
use crypto::digest::Digest;
use libc::{getgid, getuid};
use std::env;
use std::path::Path;
use std::os::unix::fs::PermissionsExt;
use std::io;
use std::io::{Read, Write};
use std::fs::{File, Permissions, create_dir_all,
              set_permissions, PathExt};
use std::process::{Command, Stdio};

const ALL_PERMISSIONS: usize = 0o0777;
const OTHER_EXECUTE: usize = 0o0001;
const OTHER_READ: usize = 0o0004;
const OTHER_RWX: usize = 0o0007;
const GROUP_EXECUTE: usize = 0o0010;
const GROUP_READ: usize = 0o0040;
const GROUP_RWX: usize = 0o0070;
const USER_EXECUTE: usize = 0o0100;
const USER_READ: usize = 0o0400;
const USER_RWX: usize = 0o0700;

trait PermExt2 {
    fn contains(&self, mask: usize) -> bool;
}

impl PermExt2 for Permissions {
    fn contains(&self, mask: usize) -> bool {
        self.mode() & (mask as i32) != 0
    }
}

const CACHE_SUBPATH: &'static str = "pexe-runner-cache";
// TODO: support overriding cache location.
const CACHE_BASE: &'static str = "/tmp";

const RUST_PNACL_TRANS: &'static str = "rust_pnacl_trans";

fn mkdir<P: AsRef<Path>>(p: P, mode: usize) -> io::Result<()> {
    try!(create_dir_all(&p));
    chmod(p, mode)
}
fn chmod<P: AsRef<Path>>(p: P, mode: usize) -> io::Result<()> {
    let p = p.as_ref();
    let md = try!(p.metadata());
    let mut perms = md.permissions();
    perms.set_mode(mode as i32);
    set_permissions(p, perms)
}

pub fn main() {
    env_logger::init().unwrap();

    let args: Vec<String> = env::args()
        .collect();
    let pexe_path = Path::new(&(args[1])[..]);

    let cache = Path::new(CACHE_BASE).join(CACHE_SUBPATH);
    if !cache.exists() {
        mkdir(&cache, ALL_PERMISSIONS).unwrap();
    }

    // if the binary is rx by the world, don't use a user prefix when caching.

    let pexe = File::open(&pexe_path);
    if pexe.is_err() {
        panic!("could not open Pexe file!");
    }
    let mut pexe = pexe.unwrap();

    let pexe_filename = Path::new(pexe_path.file_name().unwrap());

    let pexe_stat = pexe.metadata().unwrap();
    let (cache_dir, perms) = if pexe_stat.permissions().contains(OTHER_EXECUTE | OTHER_READ) {
        let c = cache.join("other");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        (c, ALL_PERMISSIONS)
    } else if pexe_stat.permissions().contains(GROUP_EXECUTE | GROUP_READ) {
        let c = cache.join("group");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        let gid = unsafe { getgid() };
        let c = c.join(format!("{}", gid));
        if !c.exists() {
            mkdir(&c, GROUP_RWX | USER_RWX).unwrap();
        }
        (c, GROUP_RWX | USER_RWX)
    } else if pexe_stat.permissions().contains(USER_EXECUTE) {
        let c = cache.join("user");
        if !c.exists() {
            mkdir(&c, ALL_PERMISSIONS).unwrap();
        }
        let uid = unsafe { getuid() };
        let c = c.join(format!("{}", uid));
        if !c.exists() {
            mkdir(&c, USER_RWX).unwrap();
        }
        (c, USER_RWX)
    } else {
        panic!("cann't execute: permissing denied");
    };
    let mut pexe_bin = Vec::new();
    pexe.read_to_end(&mut pexe_bin)
        .unwrap();

    let mut hasher = Sha512::new();
    hasher.input(pexe_bin.as_slice());
    let cache_dir = cache_dir.join(hasher.result_str());
    if !cache_dir.exists() {
        mkdir(&cache_dir, perms).unwrap();
    }
    let nexe_path = cache_dir
        .join(pexe_filename.with_extension("nexe"));

    let nacl_sdk_root = env!("NACL_SDK_ROOT");

    if !nexe_path.exists() {
        let mut cmd = Command::new(RUST_PNACL_TRANS);
        cmd.arg("--cross-path");
        cmd.arg(nacl_sdk_root);
        cmd.arg(pexe_path.display().to_string());
        cmd.arg("-o");
        cmd.arg(nexe_path.display().to_string());
        cmd.arg("--opt-level=2");
        debug!("trans cmd line: `{:?}`", cmd);
        let trans = cmd.spawn().unwrap();

        let output = trans.wait_with_output().unwrap();
        let status = output.status;
        match status {
            _ if status.success() => {
                chmod(&nexe_path, perms).unwrap();
            }
            _ => {
                let mut stderr = ::std::io::stderr();
                let mut stdout = ::std::io::stdout();
                (writeln!(&mut stderr, "`{:?}` failed:", cmd)).unwrap();
                stdout.write(output.stdout.as_slice()).unwrap();
                stderr.write(output.stderr.as_slice()).unwrap();
                env::set_exit_status(status.code().unwrap_or(1));
                return;
            }
        }
    }

    let nacl_sdk_root = Path::new(nacl_sdk_root);
    let tools = nacl_sdk_root.join("tools");
    let nacl_helper_bootstrap = tools.join("nacl_helper_bootstrap_x86_64");
    let sel_ldr_bin = tools.join("sel_ldr_x86_64");
    let irt_core = tools.join("irt_core_x86_64.nexe");

    let mut sel_ldr_args = vec!(sel_ldr_bin.display().to_string(),
                                "--r_debug=0xXXXXXXXXXXXXXXXX".to_string(),
                                "--reserved_at_zero=0xXXXXXXXXXXXXXXXX".to_string());
    match env::var("ALLOW_FILE_ACCESS") {
        Ok(ref v) if v != "0" => {
            sel_ldr_args.push("-a".to_string());
        },
        _ => {},
    }
    match env::var("DEBUG_PEXE") {
        Ok(ref v) if v != "0" => {
            sel_ldr_args.push("-g".to_string());
        },
        _ => {},
    }

    sel_ldr_args.push("-B".to_string());
    sel_ldr_args.push(irt_core.display().to_string());
    sel_ldr_args.push("-l".to_string());
    sel_ldr_args.push("/dev/null".to_string());
    sel_ldr_args.push("--".to_string());
    sel_ldr_args.push(nexe_path.display().to_string());
    for arg in &args[2..] {
        sel_ldr_args.push(arg.clone());
    }

    let mut cmd = Command::new(nacl_helper_bootstrap);
    cmd.args(sel_ldr_args.as_slice());
    cmd.stdout(Stdio::inherit());
    cmd.stderr(Stdio::inherit());
    debug!("sel_ldr cmd line: `{:?}`", cmd);
    match cmd.spawn() {
        Ok(mut process) => {
            match process.wait() {
                Ok(status) => {
                    env::set_exit_status(status.code().unwrap_or(1));
                },
                Err(e) => {
                    panic!("couldn't wait on sel_ldr: {}", e);
                }
            }
        }
        Err(e) => {
            panic!("couldn't spawn sel_ldr: {}", e);
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::fmt::Display;
use std::iter;
use std::io;

#[macro_use]
extern crate log;

#[derive(Debug)]
struct Disk {
    weight : usize,
}

impl Disk {
    pub fn new(weight: usize) -> Disk {
        Disk { weight : weight }
    }

    pub fn weight(&self) -> usize {
        self.weight
    }
}

impl Display for Disk {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
        f.write_fmt(format_args!("[{0}]", iter::repeat("#").take(self.weight()).collect::<String>()))
    }
}

#[derive(Debug)]
struct Rod {
    stack : Vec<Disk>,
}

impl Rod {
    pub fn new(sizes : &[usize]) -> Rod {
        Rod { stack : sizes.iter().map(|x| Disk::new(*x) ).collect::<Vec<_>>() }
    }

    fn can_move_disk(&self, disk : &Disk) -> bool {
        match self.stack.last() {
            None => true,
            Some(t) => t.weight() > disk.weight(),
        }
    }

    pub fn can_move(&self, other: &Rod) -> bool {
        match other.stack.last() {
            None => false,
            Some(ref disk) => self.can_move_disk(disk)
        }
    }

    pub fn take_from(& mut self, other: &mut Rod) -> bool {
        if self.can_move(other) {
            trace!("Will take {0:?} <- {1:?}", self, other);
            self.stack.push(other.stack.pop().expect("can_move returned true"));
            true
        } else {
            false
        }
    }

}

struct Desk {
    rods : Vec<Rod>,
}

impl Desk {
    pub fn new(rods: &[&[usize]]) -> Desk {
        Desk { rods : rods.iter().map(|x| Rod::new(*x) ).collect::<Vec<_>>() }
    }

    pub fn new_default(count : usize) -> Desk {
        let tmp = (1 .. count+1).rev().collect::<Vec<usize>>();

        let first: &[usize] = &tmp[ .. ];
        Desk::new(&[
            &first,
            &[],
            &[]
        ])
    }

    pub fn is_done(&self) -> bool {
        self.rods.iter().take(self.rods.len() -1).all(|r| r.stack.is_empty())
    }

    pub fn move_disk(&mut self, from: usize, to: usize) -> bool {
        let from_rod;
        let to_rod;

        if from < to {
            let (x, y) = self.rods.split_at_mut(to);

            from_rod = x.get_mut(from);
            to_rod = y.get_mut(0);
        } else if to < from {
            let (x, y) = self.rods.split_at_mut(from);

            from_rod = y.get_mut(0);
            to_rod = x.get_mut(to);
        } else {
            from_rod = None;
            to_rod = None;
        }

        match (to_rod, from_rod) {
            (Some(a), Some(b)) => a.take_from(b),
            _ => false,
        }
    }
}

impl Display for Desk {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
        let max_weight : usize =
            self.rods.iter()
                .map(|r| r.stack.iter().map(|s| s.weight()).max().unwrap_or(0))
                .max().unwrap_or(0);
        let height = max_weight + 2;

        let dup = |s: &str, n: usize| iter::repeat(s).take(n).collect::<String>();
        let mut display : Vec<String> = Vec::new();

        for i in 0..height {
            let mut s : String = "  ".to_string();

            for rod_index in (0..self.rods.len()) {
                let rod = &self.rods[rod_index];
                let tmp = match rod.stack.get(i) {
                    None => format!("{0}{1}{0}", dup(" ", max_weight + 1), if i == height -1 {(rod_index+1).to_string()} else {"|".to_string()}),
                    Some(disk) => format!("{1}[{0}|{0}]{1}", dup("#", disk.weight()), dup(" ", max_weight - disk.weight())),
                };
                s.push_str(" ");
                s.push_str(&tmp);
            }

            s.push_str("  ");
            s.push_str("\n");
            display.push(s);
        }

        display.reverse();
        display.push(dup("-", 2 + 2 + (self.rods.len() +1) * max_weight * 2) + "\n");
        f.write_fmt(format_args!("{0}", display.connect("")))
    }
}

fn read_move() ->(usize, usize) {
    let buffer = &mut String::with_capacity(32);
    let _ = io::stdin().read_line(buffer)
        .ok()
        .expect("Failed to read line");

    let splits = buffer.trim().split(' ').collect::<Vec<&str>>();
    let from = splits[0].trim().parse::<usize>().unwrap_or(1);
    let to = splits[1].trim().parse::<usize>().unwrap_or(1);

    (from, to)
}

fn main() {
    let desk = &mut Desk::new_default(10);

    while !desk.is_done() {
        println!("{0}", desk);

        println!("Your move [from] [to]: ");
        let (from, to) = read_move();
        println!("Moving from {0} -> {1}", from, to);

        match desk.move_disk(from -1, to -1) {
            false => println!("Could not perfrom such move"),
            true => (),
        }
    }

    println!("Game over, you win");
}
<commit_msg>Add more user input checks<commit_after>#![feature(slice_patterns)]

use std::fmt;
use std::fmt::Display;
use std::iter;
use std::io;

#[macro_use]
extern crate log;

#[derive(Debug)]
struct Disk {
    weight : usize,
}

impl Disk {
    pub fn new(weight: usize) -> Disk {
        Disk { weight : weight }
    }

    pub fn weight(&self) -> usize {
        self.weight
    }
}

impl Display for Disk {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
        f.write_fmt(format_args!("[{0}]", iter::repeat("#").take(self.weight()).collect::<String>()))
    }
}

#[derive(Debug)]
struct Rod {
    stack : Vec<Disk>,
}

impl Rod {
    pub fn new(sizes : &[usize]) -> Rod {
        Rod { stack : sizes.iter().map(|x| Disk::new(*x) ).collect::<Vec<_>>() }
    }

    fn can_move_disk(&self, disk : &Disk) -> bool {
        match self.stack.last() {
            None => true,
            Some(t) => t.weight() > disk.weight(),
        }
    }

    pub fn can_move(&self, other: &Rod) -> bool {
        match other.stack.last() {
            None => false,
            Some(ref disk) => self.can_move_disk(disk)
        }
    }

    pub fn take_from(& mut self, other: &mut Rod) -> bool {
        if self.can_move(other) {
            trace!("Will take {0:?} <- {1:?}", self, other);
            self.stack.push(other.stack.pop().expect("can_move returned true"));
            true
        } else {
            false
        }
    }

}

struct Desk {
    rods : Vec<Rod>,
}

impl Desk {
    pub fn new(rods: &[&[usize]]) -> Desk {
        Desk { rods : rods.iter().map(|x| Rod::new(*x) ).collect::<Vec<_>>() }
    }

    pub fn new_default(count : usize) -> Desk {
        let tmp = (1 .. count+1).rev().collect::<Vec<usize>>();

        let first: &[usize] = &tmp[ .. ];
        Desk::new(&[
            &first,
            &[],
            &[]
        ])
    }

    pub fn is_done(&self) -> bool {
        self.rods.iter().take(self.rods.len() -1).all(|r| r.stack.is_empty())
    }

    pub fn move_disk(&mut self, from: usize, to: usize) -> bool {
        let from_rod;
        let to_rod;

        if from < to && to < self.rods.len() {
            let (x, y) = self.rods.split_at_mut(to);

            from_rod = x.get_mut(from);
            to_rod = y.get_mut(0);
        } else if to < from && from < self.rods.len() {
            let (x, y) = self.rods.split_at_mut(from);

            from_rod = y.get_mut(0);
            to_rod = x.get_mut(to);
        } else {
            from_rod = None;
            to_rod = None;
        }

        match (to_rod, from_rod) {
            (Some(a), Some(b)) => a.take_from(b),
            _ => false,
        }
    }
}

impl Display for Desk {
    fn fmt(&self, f : &mut fmt::Formatter) -> fmt::Result {
        let max_weight : usize =
            self.rods.iter()
                .map(|r| r.stack.iter().map(|s| s.weight()).max().unwrap_or(0))
                .max().unwrap_or(0);
        let height = max_weight + 2;

        let dup = |s: &str, n: usize| iter::repeat(s).take(n).collect::<String>();
        let mut display : Vec<String> = Vec::new();

        for i in 0..height {
            let mut s : String = "  ".to_string();

            for rod_index in (0..self.rods.len()) {
                let rod = &self.rods[rod_index];
                let tmp = match rod.stack.get(i) {
                    None => format!("{0}{1}{0}", dup(" ", max_weight + 1), if i == height -1 {(rod_index+1).to_string()} else {"|".to_string()}),
                    Some(disk) => format!("{1}[{0}|{0}]{1}", dup("#", disk.weight()), dup(" ", max_weight - disk.weight())),
                };
                s.push_str(" ");
                s.push_str(&tmp);
            }

            s.push_str("  ");
            s.push_str("\n");
            display.push(s);
        }

        display.reverse();
        display.push(dup("-", 2 + 2 + (self.rods.len() +1) * max_weight * 2) + "\n");
        f.write_fmt(format_args!("{0}", display.connect("")))
    }
}

fn read_move() ->(usize, usize) {
    let buffer = &mut String::with_capacity(32);
    let _ = io::stdin().read_line(buffer)
        .ok()
        .expect("Failed to read line");

    let splits = buffer.trim().split(' ').collect::<Vec<&str>>();
    match &splits[ .. ] {
        [ from, to ] => (
                from.trim().parse::<usize>().unwrap_or(1),
                to.trim().parse::<usize>().unwrap_or(1)
            ),
        _ => (1, 1),
        //[] | [_] | [_, _, ..]=> (1, 1),
    }
}

fn main() {
    let desk = &mut Desk::new_default(10);

    while !desk.is_done() {
        println!("{0}", desk);

        println!("Your move [from] [to]: ");
        let (from, to) = read_move();
        println!("Moving from {0} -> {1}", from, to);

        match desk.move_disk(from -1, to -1) {
            false => println!("Could not perfrom such move"),
            true => (),
        }
    }

    println!("Game over, you win");
}
<|endoftext|>


<commit_before>struct Chip8Unit {
    /*
     * 0x000-0x1FF - Chip 8 interpreter (contains font set in emu)
     * 0x050-0x0A0 - Used for the built in 4x5 pixel font set (0-F)
     * 0x200-0xFFF - Program ROM and work RAM
     */
    memory:    [u8; 4096],

    /*
     * CPU registers: The Chip 8 has 15 8-bit general purpose registers
     * named V0,V1 up to VE. The 16th register is used  for the ‘carry flag’.
     */
    registers: [u8; 16],

    // Index register
    i: u16,

    // program counter
    pc: u16,

    // Screen - 64 x 32 pixels
    graphics: [u8; 64*32],

    // No timers, but 60hz counters
    delay_timer: u8,
    sound_timer: u8,

    // Stack needed to jump to certain addresses or call subroutines
    // The chip8 stack has 16 levels
    stack_pointer: u16,
    stack: [u16; 16],

    // Chip8 keypad had 16 keys - keep track of the kb state
    keypad: [u8; 16],
}

fn main() {
    println!("Hello, world!");
}
<commit_msg>initialize sdl screen<commit_after>extern crate sdl;

use std::rand::Rng;

use sdl::event::{Event, Key};
use sdl::video::{SurfaceFlag, VideoFlag};

struct Chip8Unit {
    /*
     * 0x000-0x1FF - Chip 8 interpreter (contains font set in emu)
     * 0x050-0x0A0 - Used for the built in 4x5 pixel font set (0-F)
     * 0x200-0xFFF - Program ROM and work RAM
     */
    memory:    [u8; 4096],

    /*
     * CPU registers: The Chip 8 has 15 8-bit general purpose registers
     * named V0,V1 up to VE. The 16th register is used  for the ‘carry flag’.
     */
    registers: [u8; 16],

    // Index register
    i: u16,

    // program counter
    pc: u16,

    // Screen - 64 x 32 pixels
    graphics: [u8; 64*32],

    // No timers, but 60hz counters
    delay_timer: u8,
    sound_timer: u8,

    // Stack needed to jump to certain addresses or call subroutines
    // The chip8 stack has 16 levels
    stack_pointer: u16,
    stack: [u16; 16],

    // Chip8 keypad had 16 keys - keep track of the kb state
    keypad: [u8; 16],
}

#[main]
fn main() {
    // Initialize SDL Video
    sdl::init([sdl::InitFlag::Video].as_slice());

    // Give our window a title
    sdl::wm::set_caption("rusty_chips a Chip8 emulator", "rusty_chips");

    // Initialize the screen
    let screen = match sdl::video::set_video_mode(800, 600, 32,
                                                  [SurfaceFlag::HWSurface].as_slice(),
                                                  [VideoFlag::DoubleBuf].as_slice()) {
        Ok(screen) => screen,
        Err(err) => panic!("Failed to set video mode: {}", err)
    };

    // SDL main loop
    'main : loop {
        'event : loop {
            match sdl::event::poll_event() {
                Event::Quit => break 'main,
                Event::None => break 'event,
                Event::Key (k,_,_,_)
                    if k == Key::Escape
                        => break 'main,
                    _ => {}
            }
        }
    }

    // Quit
    sdl::quit();
}
<|endoftext|>


<commit_before>#![allow(unused_variables)]

extern crate env_logger;
extern crate getopts;
extern crate log;
extern crate failure;
extern crate mdblog;

use std::env;

use getopts::{HasArg, Matches, Occur, Options};
use failure::Fail;

use mdblog::{Mdblog, Result};

fn print_usage_and_exit(opts: &Options, exit_code: i32) -> ! {
    let brief = "\
Usage:
    mdblog init <blog>
    mdblog build
    mdblog server [-p <port>]  # unimplemented
    mdblog -v | --version
    mdblog -h | --help\
";
    if exit_code == 0 {
        eprint!("{}", opts.usage(brief));
    } else {
        print!("{}", opts.usage(brief));
    }
    ::std::process::exit(exit_code);
}

fn main() {
    env_logger::init();

    let args: Vec<_> = env::args().collect();

    let mut opts = Options::new();
    opts.optflag("h", "help", "Display this message");
    opts.optflag("v", "version", "Print version info and exit");
    opts.opt("p",
             "port",
             "Server with port number",
             "<port>",
             HasArg::Yes,
             Occur::Optional);

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(why) => {
            eprintln!("{}", why);
            eprintln!("run `mdblog -h` to get the usage.");
            ::std::process::exit(1);
        },
    };

    if matches.opt_present("h") {
        print_usage_and_exit(&opts, 0);
    } else if matches.opt_present("v") {
        println!("mdblog {}", env!("CARGO_PKG_VERSION"));
        ::std::process::exit(0);
    } else if matches.free.len() < 1 {
        print_usage_and_exit(&opts, 2);
    }

    let res = match matches.free[0].as_ref() {
        "init" => init(&matches),
        "build" => build(&matches),
        "server" => server(&matches),
        _ => print_usage_and_exit(&opts, 3),
    };

    if let Err(ref e) = res {
        eprintln!("error: {}", e);

        for cause in e.causes() {
            eprintln!("{}", cause);
        }

        if let Some(backtrace) = e.backtrace() {
            eprintln!("backtrace: {:?}", backtrace);
        }
        ::std::process::exit(1);
    }
}

fn init(matches: &Matches) -> Result<()> {
    if matches.free.len() != 2 {
        panic!("`init` subcommand requires one argument.");
    }
    let dir = env::current_dir().unwrap().join(&matches.free[1]);
    let mut mb = Mdblog::new(dir).unwrap();
    mb.init().unwrap();
    Ok(())
}

fn build(matches: &Matches) -> Result<()> {
    let root_dir = env::current_dir().unwrap();
    let mut mb = Mdblog::new(&root_dir).unwrap();
    mb.load().unwrap();
    mb.build().unwrap();
    Ok(())
}

fn server(matches: &Matches) -> Result<()> {
    println!("server command");
    Ok(())
}
<commit_msg>fix the misuse of print!/eprint<commit_after>#![allow(unused_variables)]

extern crate env_logger;
extern crate getopts;
extern crate log;
extern crate failure;
extern crate mdblog;

use std::env;

use getopts::{HasArg, Matches, Occur, Options};
use failure::Fail;

use mdblog::{Mdblog, Result};

fn print_usage_and_exit(opts: &Options, exit_code: i32) -> ! {
    let brief = "\
Usage:
    mdblog init <blog>
    mdblog build
    mdblog server [-p <port>]  # unimplemented
    mdblog -v | --version
    mdblog -h | --help\
";
    if exit_code == 0 {
        print!("{}", opts.usage(brief));
    } else {
        eprint!("{}", opts.usage(brief));
    }
    ::std::process::exit(exit_code);
}

fn main() {
    env_logger::init();

    let args: Vec<_> = env::args().collect();

    let mut opts = Options::new();
    opts.optflag("h", "help", "Display this message");
    opts.optflag("v", "version", "Print version info and exit");
    opts.opt("p",
             "port",
             "Server with port number",
             "<port>",
             HasArg::Yes,
             Occur::Optional);

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(why) => {
            eprintln!("{}", why);
            eprintln!("run `mdblog -h` to get the usage.");
            ::std::process::exit(1);
        },
    };

    if matches.opt_present("h") {
        print_usage_and_exit(&opts, 0);
    } else if matches.opt_present("v") {
        println!("mdblog {}", env!("CARGO_PKG_VERSION"));
        ::std::process::exit(0);
    } else if matches.free.len() < 1 {
        print_usage_and_exit(&opts, 2);
    }

    let res = match matches.free[0].as_ref() {
        "init" => init(&matches),
        "build" => build(&matches),
        "server" => server(&matches),
        _ => print_usage_and_exit(&opts, 3),
    };

    if let Err(ref e) = res {
        eprintln!("error: {}", e);

        for cause in e.causes() {
            eprintln!("{}", cause);
        }

        if let Some(backtrace) = e.backtrace() {
            eprintln!("backtrace: {:?}", backtrace);
        }
        ::std::process::exit(1);
    }
}

fn init(matches: &Matches) -> Result<()> {
    if matches.free.len() != 2 {
        panic!("`init` subcommand requires one argument.");
    }
    let dir = env::current_dir().unwrap().join(&matches.free[1]);
    let mut mb = Mdblog::new(dir).unwrap();
    mb.init().unwrap();
    Ok(())
}

fn build(matches: &Matches) -> Result<()> {
    let root_dir = env::current_dir().unwrap();
    let mut mb = Mdblog::new(&root_dir).unwrap();
    mb.load().unwrap();
    mb.build().unwrap();
    Ok(())
}

fn server(matches: &Matches) -> Result<()> {
    println!("server command");
    Ok(())
}
<|endoftext|>


<commit_before>// extern crate zip;
// use zip::{ZipWriter,CompressionMethod::*};
// use std::io::Write;
extern crate rustc_serialize;
extern crate toml;
use std::env::args;
use std::fs::{File,metadata,copy};
// use std::io::Read;
use std::io::prelude::*;
use std::process::Command;
use rustc_serialize::json::Json;

fn main() {
	if !check_built(".so") {
		println!("Need to build!");
		println!("{}",cargo("build"));
	}
	bundle();
	// println!("{}", get_lib_name(".so"));

}

fn manifest() -> String {
	let package_name = toml_lookup("package.name").replace("-","_");
    return format!(
"Manifest-Version: 1.0
Bundle-SymbolicName: {}
Bundle-Name: {}
Bundle-Version: {}
Bundle-Activator: lib{}.so
Private-Library: lib{}.so
", package_name,package_name,toml_lookup("package.version"),package_name,package_name);
}

fn bundle<'a>() {
	// let mut f = try!(File::create(get_lib_name(".zip")));
	// println!("Creating {}", f);
	// let mut zip = ZipWriter::new(f);
	// try!(zip.start_file("lib"+toml_lookup("package.name")+".zip", Stored));
	// try!(zip.write());
	let tmpdir : String = String::from_utf8_lossy(&Command::new("mktemp").arg("-dt").arg("rust-celix.XXXXXXXXXXXXXX").output().unwrap().stdout).into_owned().trim_right().to_string() + "/";
	// println!("{:?}", tmpdir);
	//copy files into tmpdir
	// println!("{}", get_lib_name((tmpdir.as_str().clone().to_string()+"lib").as_str().clone(),".so"));
    copy(get_lib_name("target/release/lib",".so"),get_lib_name((tmpdir.as_str().clone().to_string()+"lib").as_str().clone(),".so"));
    let _ = Command::new("mkdir").arg("-p").arg(tmpdir.as_str().clone().to_string()+"META-INF").output().unwrap().stdout;
    // copy("src/META-INF/MANIFEST.MF",tmpdir.as_str().clone().to_string()+"META-INF/MANIFEST.MF");
    File::create(tmpdir.as_str().clone().to_string()+"META-INF/MANIFEST.MF").unwrap().write_all(manifest().as_bytes()).unwrap();

	println!("{}", String::from_utf8_lossy(&Command::new("ls").current_dir(tmpdir.as_str().clone()).output().unwrap().stdout));
	println!("{}", String::from_utf8_lossy(&Command::new("zip").current_dir(tmpdir.as_str().clone()).arg(get_lib_name("",".zip")).arg(get_lib_name("lib",".so")).arg("META-INF/MANIFEST.MF").output().unwrap().stdout));
	copy(get_lib_name(tmpdir.as_str().clone(),".zip"),("deploy/bundles/".to_string()+toml_lookup("package.name").replace("-","_").as_str()).to_string()+".zip");
	let _ = Command::new("rm").arg("-rf").arg(tmpdir).output().unwrap().stdout;
}

fn check_built(ext: &str) -> bool {
	metadata(get_lib_name("target/release/lib",ext)).is_ok()
}

fn get_cargo_toml_path() -> String {
	let output = cargo("locate-project");
	let json =
		match Json::from_str(&*output) {
			Ok(j) => j,
			Err(_) => panic!("Couldn't parse the output of `cargo locate-project`")
		};
	json["root"].as_string().unwrap().to_string()
}

fn cargo(command: &str) -> String {
	if command == "build" {
		let output = Command::new("cargo")
							 .arg("build")
							 .arg("--release")
							 .output()
							 .unwrap();
		return String::from_utf8_lossy(&output.stdout).into_owned();
	} else {
		let output = Command::new("cargo")
							 .arg(command)
							 .output()
							 .unwrap();
		return String::from_utf8_lossy(&output.stdout).into_owned();
	}
}

fn get_lib_name(pre: &str, ext: &str) -> String {
	let base_name = toml_lookup("package.name").replace("-","_");
	((pre.to_string() + base_name.as_str()) + ext).to_string()
}

fn toml_lookup(name: &str) -> String {
	let toml_path = get_cargo_toml_path();
	let mut toml_file = match File::open(toml_path) {
			Ok(f) => f,
			Err(_) => panic!("Couldn't open Cargo.toml")
		};

	let mut contents = String::new();
	toml_file.read_to_string(&mut contents).unwrap();

	let mut parser = toml::Parser::new(&*contents);
	let toml_table = toml::Value::Table(parser.parse().unwrap());

	toml_table.lookup(name).expect("Couldn't find the index!").as_str().unwrap().to_string()
}
<commit_msg>Removed old code<commit_after>// extern crate zip;
// use zip::{ZipWriter,CompressionMethod::*};
// use std::io::Write;
extern crate rustc_serialize;
extern crate toml;
use std::env::args;
use std::fs::{File,metadata,copy};
// use std::io::Read;
use std::io::prelude::*;
use std::process::Command;
use rustc_serialize::json::Json;

fn main() {
	if !check_built(".so") {
		println!("Need to build!");
		println!("{}",cargo("build"));
	}
	bundle();
	// println!("{}", get_lib_name(".so"));

}

fn manifest() -> String {
	let package_name = toml_lookup("package.name").replace("-","_");
    return format!(
"Manifest-Version: 1.0
Bundle-SymbolicName: {}
Bundle-Name: {}
Bundle-Version: {}
Bundle-Activator: lib{}.so
Private-Library: lib{}.so
", package_name,package_name,toml_lookup("package.version"),package_name,package_name);
}

fn bundle<'a>() {
	let tmpdir : String = String::from_utf8_lossy(&Command::new("mktemp").arg("-dt").arg("rust-celix.XXXXXXXXXXXXXX").output().unwrap().stdout).into_owned().trim_right().to_string() + "/";
    copy(get_lib_name("target/release/lib",".so"),get_lib_name((tmpdir.as_str().clone().to_string()+"lib").as_str().clone(),".so"));
    let _ = Command::new("mkdir").arg("-p").arg(tmpdir.as_str().clone().to_string()+"META-INF").output().unwrap().stdout;
    File::create(tmpdir.as_str().clone().to_string()+"META-INF/MANIFEST.MF").unwrap().write_all(manifest().as_bytes()).unwrap();
	println!("{}", String::from_utf8_lossy(&Command::new("ls").current_dir(tmpdir.as_str().clone()).output().unwrap().stdout));
	println!("{}", String::from_utf8_lossy(&Command::new("zip").current_dir(tmpdir.as_str().clone()).arg(get_lib_name("",".zip")).arg(get_lib_name("lib",".so")).arg("META-INF/MANIFEST.MF").output().unwrap().stdout));
	copy(get_lib_name(tmpdir.as_str().clone(),".zip"),("deploy/bundles/".to_string()+toml_lookup("package.name").replace("-","_").as_str()).to_string()+".zip");
	let _ = Command::new("rm").arg("-rf").arg(tmpdir).output().unwrap().stdout;
}

fn check_built(ext: &str) -> bool {
	metadata(get_lib_name("target/release/lib",ext)).is_ok()
}

fn get_cargo_toml_path() -> String {
	let output = cargo("locate-project");
	let json =
		match Json::from_str(&*output) {
			Ok(j) => j,
			Err(_) => panic!("Couldn't parse the output of `cargo locate-project`")
		};
	json["root"].as_string().unwrap().to_string()
}

fn cargo(command: &str) -> String {
	if command == "build" {
		let output = Command::new("cargo")
							 .arg("build")
							 .arg("--release")
							 .output()
							 .unwrap();
		return String::from_utf8_lossy(&output.stdout).into_owned();
	} else {
		let output = Command::new("cargo")
							 .arg(command)
							 .output()
							 .unwrap();
		return String::from_utf8_lossy(&output.stdout).into_owned();
	}
}

fn get_lib_name(pre: &str, ext: &str) -> String {
	let base_name = toml_lookup("package.name").replace("-","_");
	((pre.to_string() + base_name.as_str()) + ext).to_string()
}

fn toml_lookup(name: &str) -> String {
	let toml_path = get_cargo_toml_path();
	let mut toml_file = match File::open(toml_path) {
			Ok(f) => f,
			Err(_) => panic!("Couldn't open Cargo.toml")
		};

	let mut contents = String::new();
	toml_file.read_to_string(&mut contents).unwrap();

	let mut parser = toml::Parser::new(&*contents);
	let toml_table = toml::Value::Table(parser.parse().unwrap());

	toml_table.lookup(name).expect("Couldn't find the index!").as_str().unwrap().to_string()
}
<|endoftext|>


<commit_before>//! Command line utility for querying and working with Iridium SBD messages.

extern crate chrono;
extern crate docopt;
extern crate log;
extern crate rustc_serialize;
extern crate sbd;

use std::io::Write;
use std::path::Path;
use std::process;
use std::str;

use docopt::Docopt;

use sbd::directip::Server;
use sbd::storage::FilesystemStorage;
use sbd::mo::Message;

const USAGE: &'static str = "
Iridium Short Burst Data (SBD) message utility.

Usage:
    sbd \
                             read <file>
    sbd serve <addr> <directory> [--logfile=<logfile>]
    \
                             sbd (-h | --help)
    sbd --version

Options:
    -h --help               \
                             Show this information
    --version               Show version
    \
                             --logfile=<logfile>     Logfile [default: /var/log/iridiumd.log]
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_read: bool,
    cmd_serve: bool,
    arg_addr: String,
    arg_directory: String,
    arg_file: String,
    flag_logfile: String,
}

struct Logger<P: AsRef<Path>> {
    path: P,
}

impl<P: AsRef<Path> + Send + Sync> log::Log for Logger<P> {
    fn enabled(&self, metadata: &log::LogMetadata) -> bool {
        metadata.level() <= log::LogLevel::Debug
    }

    fn log(&self, record: &log::LogRecord) {
        if self.enabled(record.metadata()) {
            let mut file = std::fs::OpenOptions::new()
                               .create(true)
                               .write(true)
                               .append(true)
                               .open(&self.path)
                               .unwrap();
            file.write_all(format!("({}) {}: {}\n",
                                   chrono::UTC::now().format("%Y-%m-%d %H:%M:%S"),
                                   record.level(),
                                   record.args())
                               .as_bytes())
                .unwrap();
        }
    }
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                         .and_then(|d| Ok(d.version(Some(env!("CARGO_PKG_VERSION").to_string()))))
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());

    if args.cmd_read {
        match Message::from_path(&args.arg_file) {
            Ok(message) => {
                println!("{}", str::from_utf8(message.payload_ref()).unwrap());
            }
            Err(err) => println!("ERROR: {:?}", err),
        }
    }
    if args.cmd_serve {
        match log::set_logger(|max_log_level| {
            max_log_level.set(log::LogLevelFilter::Debug);
            Box::new(Logger { path: args.flag_logfile.clone() })
        }) {
            Ok(()) => {}
            Err(err) => {
                println!("Error when creating logger: {:?}", err);
                process::exit(1);
            }
        };
        let storage = FilesystemStorage::open(&args.arg_directory).unwrap_or_else(|e| {
            println!("Error when opening fileystem storage: {}", e);
            process::exit(1);
        });
        let mut server = Server::new(&args.arg_addr[..], storage);
        match server.bind() {
            Ok(()) => server.serve_forever(),
            Err(err) => {
                println!("Error when trying to bind to socket: {:?}", err);
                process::exit(1);
            }
        }
    }
}
<commit_msg>Clean up payload and serve commands<commit_after>//! Command line utility for querying and working with Iridium SBD messages.

extern crate chrono;
extern crate docopt;
extern crate log;
extern crate rustc_serialize;
extern crate sbd;

use std::io::Write;
use std::path::Path;
use std::process;
use std::str;

use docopt::Docopt;

use sbd::directip::Server;
use sbd::storage::FilesystemStorage;
use sbd::mo::Message;

const USAGE: &'static str = "
Iridium Short Burst Data (SBD) message utility.

Usage:
    sbd \
                             payload <file>
    sbd serve <addr> <directory> \
                             [--logfile=<logfile>]
    sbd (-h | --help)
    sbd --version

\
                             Options:
    -h --help               Show this information
    \
                             --version               Show version
    --logfile=<logfile>     \
                             Logfile [default: /var/log/iridiumd.log]
";

#[derive(Debug, RustcDecodable)]
struct Args {
    cmd_payload: bool,
    cmd_serve: bool,
    arg_addr: String,
    arg_directory: String,
    arg_file: String,
    flag_logfile: String,
}

struct Logger<P: AsRef<Path>> {
    path: P,
}

impl<P: AsRef<Path> + Send + Sync> log::Log for Logger<P> {
    fn enabled(&self, metadata: &log::LogMetadata) -> bool {
        metadata.level() <= log::LogLevel::Debug
    }

    fn log(&self, record: &log::LogRecord) {
        if self.enabled(record.metadata()) {
            let mut file = std::fs::OpenOptions::new()
                               .create(true)
                               .write(true)
                               .append(true)
                               .open(&self.path)
                               .unwrap();
            file.write_all(format!("({}) {}: {}\n",
                                   chrono::UTC::now().format("%Y-%m-%d %H:%M:%S"),
                                   record.level(),
                                   record.args())
                               .as_bytes())
                .unwrap();
        }
    }
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                         .and_then(|d| Ok(d.version(Some(env!("CARGO_PKG_VERSION").to_string()))))
                         .and_then(|d| d.decode())
                         .unwrap_or_else(|e| e.exit());

    if args.cmd_payload {
        match Message::from_path(&args.arg_file) {
            Ok(message) => {
                println!("{}", str::from_utf8(message.payload_ref()).unwrap());
            }
            Err(err) => {
                println!("ERROR: Unable to extract payload: {}", err);
                process::exit(1);
            }
        }
    }
    if args.cmd_serve {
        log::set_logger(|max_log_level| {
            max_log_level.set(log::LogLevelFilter::Debug);
            Box::new(Logger { path: args.flag_logfile.clone() })
        })
            .unwrap_or_else(|e| {
                println!("ERROR: Could not create logger: {}", e);
                process::exit(1);
            });
        let storage = FilesystemStorage::open(&args.arg_directory).unwrap_or_else(|e| {
            println!("ERROR: Could not open storage: {}", e);
            process::exit(1);
        });
        let mut server = Server::new(&args.arg_addr[..], storage);
        match server.bind() {
            Ok(()) => server.serve_forever(),
            Err(err) => {
                println!("ERROR: Could not bind to socket: {}", err);
                process::exit(1);
            }
        }
    }
}
<|endoftext|>


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

#![allow(dead_code)] // only temporary, until more stuff is filled in

extern crate devicemapper;
#[macro_use]
extern crate clap;
#[macro_use]
extern crate nix;
extern crate crc;
extern crate byteorder;
extern crate uuid;
extern crate time;
extern crate bytesize;
extern crate dbus;
extern crate term;

#[macro_use]
extern crate custom_derive;
#[macro_use]
extern crate newtype_derive;
#[macro_use]
extern crate enum_derive;

pub static mut debug: bool = false;

macro_rules! dbgp {
    ($($arg:tt)*) => (
        unsafe {
            if ::debug {
                println!($($arg)*)
            }
        })
}

mod types;
mod consts;
mod dbus_consts;
mod stratis;
mod dmdevice;
mod util;
mod dbus_api;
mod blockdev;
mod pool;
mod filesystem;
mod engine;
mod sim_engine;

use std::io::Write;
use std::error::Error;
use std::process::exit;
use std::rc::Rc;
use std::cell::RefCell;

use types::{StratisResult, StratisError};

use engine::Engine;
use sim_engine::SimEngine;

fn dbus_server(engine: Rc<RefCell<Engine>>) -> StratisResult<()> {

    let result = dbus_api::run(engine);

    result
}

fn write_err(err: StratisError) -> StratisResult<()> {
    let mut out = term::stderr().expect("could not get stderr");

    try!(out.fg(term::color::RED));
    try!(writeln!(out, "{}", err.description()));
    try!(out.reset());
    Ok(())
}

fn main() {

    let engine = Rc::new(RefCell::new(SimEngine::new()));
    // TODO: add cmdline option to specify engine
    //  let context = Rc::new(RefCell::new(Context::new()));

    let r = dbus_server(engine);

    if let Err(r) = r {
        if let Err(e) = write_err(r) {
            panic!("Unable to write to stderr: {}", e)
        }

        exit(1);
    }
}
<commit_msg>remove un-necessary dbus_server() function.<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#![allow(dead_code)] // only temporary, until more stuff is filled in

extern crate devicemapper;
#[macro_use]
extern crate clap;
#[macro_use]
extern crate nix;
extern crate crc;
extern crate byteorder;
extern crate uuid;
extern crate time;
extern crate bytesize;
extern crate dbus;
extern crate term;

#[macro_use]
extern crate custom_derive;
#[macro_use]
extern crate newtype_derive;
#[macro_use]
extern crate enum_derive;

pub static mut debug: bool = false;

macro_rules! dbgp {
    ($($arg:tt)*) => (
        unsafe {
            if ::debug {
                println!($($arg)*)
            }
        })
}

mod types;
mod consts;
mod dbus_consts;
mod stratis;
mod dmdevice;
mod util;
mod dbus_api;
mod blockdev;
mod pool;
mod filesystem;
mod engine;
mod sim_engine;

use std::io::Write;
use std::error::Error;
use std::process::exit;
use std::rc::Rc;
use std::cell::RefCell;

use types::{StratisResult, StratisError};

use engine::Engine;
use sim_engine::SimEngine;

fn write_err(err: StratisError) -> StratisResult<()> {
    let mut out = term::stderr().expect("could not get stderr");

    try!(out.fg(term::color::RED));
    try!(writeln!(out, "{}", err.description()));
    try!(out.reset());
    Ok(())
}

fn main() {

    let engine = Rc::new(RefCell::new(SimEngine::new()));
    // TODO: add cmdline option to specify engine
    //  let context = Rc::new(RefCell::new(Context::new()));

    let r = dbus_api::run(engine);

    if let Err(r) = r {
        if let Err(e) = write_err(r) {
            panic!("Unable to write to stderr: {}", e)
        }

        exit(1);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate error_chain;
extern crate calamine;

mod errors;

use std::path::{PathBuf, Path};
use std::fs;
use std::io::{BufWriter, Write};
use errors::Result;
use calamine::{Sheets, Range};

fn main() {
    let file = ::std::env::args().skip(1).next().expect("USAGE: xl2txt file");
    run(file.into()).unwrap();
}

fn run(file: PathBuf) -> Result<()> {

    let paths = XlPaths::new(file)?;
    let mut xl = Sheets::open(&paths.orig)?;

    // defined names
    {
        let mut f = BufWriter::new(fs::File::create(paths.names)?);
        writeln!(f, "| Name | Formula |")?;
        writeln!(f, "|------|---------|")?;
        for &(ref name, ref formula) in xl.defined_names()? {
            writeln!(f, "| {} | {} |", name, formula)?;
        }
    }

    // sheets
    let sheets = xl.sheet_names()?;
    for s in sheets {
        write_range(paths.data.join(format!("{}.md", &s)), xl.worksheet_range(&s)?)?;
        write_range(paths.formula.join(format!("{}.md", &s)), xl.worksheet_formula(&s)?)?;
    }

    // vba
    if !xl.has_vba() {
        return Ok(());
    }

    let mut vba = xl.vba_project()?;
    let vba = vba.to_mut();
    for module in vba.get_module_names() {
        let mut m = fs::File::create(paths.vba.join(format!("{}.vb", module)))?;
        write!(m, "{}", vba.get_module(module)?)?;
    }
    {
        let mut f = BufWriter::new(fs::File::create(paths.refs)?);
        writeln!(f, "| Name | Description | Path |")?;
        writeln!(f, "|------|-------------|------|")?;
        for r in vba.get_references() {
            writeln!(f, "| {} | {} | {} |", r.name, r.description, r.path.display())?;
        }
    }

    Ok(())
}

struct XlPaths {
    orig: PathBuf,
    data: PathBuf,
    formula: PathBuf,
    vba: PathBuf,
    refs: PathBuf,
    names: PathBuf,
}

impl XlPaths {
    fn new(orig: PathBuf) -> Result<XlPaths> {

        if !orig.exists() {
            bail!("Cannot find {}", orig.display());
        }

        if !orig.is_file() {
            bail!("{} is not a file", orig.display());
        }

        match orig.extension().and_then(|e| e.to_str()) {
            Some("xls") | Some("xlsx") | Some("xlsb") | Some("ods") => (),
            Some(e) => bail!("Unrecognized extension: {}", e),
            None => bail!("Expecting an excel file, couln't find an extension"),
        }

        let root: PathBuf = orig.parent()
            .map_or::<PathBuf, _>(".{}".into(), |p| p.into())
            .join(format!(".{}", &*orig.file_name().unwrap().to_string_lossy()));

        if !root.exists() {
            fs::create_dir_all(&root)?;
        }
        let data = root.join("data");
        if !data.exists() {
            fs::create_dir(&data)?;
        }
        let vba = root.join("vba");
        if !vba.exists() {
            fs::create_dir(&vba)?;
        }
        let formula = root.join("formula");
        if !formula.exists() {
            fs::create_dir(&formula)?;
        }

        Ok(XlPaths {
            orig: orig,
            data: data,
            formula: formula,
            vba: vba,
            refs: root.join("refs.md"),
            names: root.join("names.md"),
        })
    }
}

fn write_range<P, T>(path: P, range: Range<T>) -> Result<()>
    where P: AsRef<Path>,
          T: PartialEq + Clone + Default + ::std::fmt::Debug,
{
    if range.is_empty() {
        return Ok(());
    }

    let mut f = BufWriter::new(fs::File::create(path.as_ref())?);

    let ((srow, scol), (_, ecol)) = (range.start(), range.end());
    write!(f, "|   ")?;
    for c in scol..ecol+1 {
        write!(f, "| {} ", get_column(c))?;
    }
    writeln!(f, "|")?;
    for _ in scol..ecol+2 {
        write!(f, "|---")?;
    }
    writeln!(f, "|")?;

    // next rows: table data
    let srow = srow as usize + 1;
    for (i, row) in range.rows().enumerate() {
        write!(f, "| {} ", srow + i)?;
        for c in row {
            write!(f, "| {:?} ", c)?;
        }
        writeln!(f, "|")?;
    }
    Ok(())
}

fn get_column(mut col: u32) -> String {
    let mut buf = String::new();
    if col < 26 {
        buf.push((b'A' + col as u8) as char);
    } else {
        let mut rev = String::new();
        while col >= 26 {
            let c = col % 26;
            rev.push((b'A' + c as u8) as char);
            col -= c;
            col /= 26;
        }
        buf.extend(rev.chars().rev());
    }
    buf
}
<commit_msg>force remove root dir to see if a file as been removed<commit_after>#[macro_use]
extern crate error_chain;
extern crate calamine;

mod errors;

use std::path::{PathBuf, Path};
use std::fs;
use std::io::{BufWriter, Write};
use errors::Result;
use calamine::{Sheets, Range};

fn main() {
    let file = ::std::env::args().skip(1).next().expect("USAGE: xl2txt file");
    run(file.into()).unwrap();
}

fn run(file: PathBuf) -> Result<()> {

    let paths = XlPaths::new(file)?;
    let mut xl = Sheets::open(&paths.orig)?;

    // defined names
    {
        let mut f = BufWriter::new(fs::File::create(paths.names)?);
        writeln!(f, "| Name | Formula |")?;
        writeln!(f, "|------|---------|")?;
        for &(ref name, ref formula) in xl.defined_names()? {
            writeln!(f, "| {} | {} |", name, formula)?;
        }
    }

    // sheets
    let sheets = xl.sheet_names()?;
    for s in sheets {
        write_range(paths.data.join(format!("{}.md", &s)), xl.worksheet_range(&s)?)?;
        write_range(paths.formula.join(format!("{}.md", &s)), xl.worksheet_formula(&s)?)?;
    }

    // vba
    if !xl.has_vba() {
        return Ok(());
    }

    let mut vba = xl.vba_project()?;
    let vba = vba.to_mut();
    for module in vba.get_module_names() {
        let mut m = fs::File::create(paths.vba.join(format!("{}.vb", module)))?;
        write!(m, "{}", vba.get_module(module)?)?;
    }
    {
        let mut f = BufWriter::new(fs::File::create(paths.refs)?);
        writeln!(f, "| Name | Description | Path |")?;
        writeln!(f, "|------|-------------|------|")?;
        for r in vba.get_references() {
            writeln!(f, "| {} | {} | {} |", r.name, r.description, r.path.display())?;
        }
    }

    Ok(())
}

struct XlPaths {
    orig: PathBuf,
    data: PathBuf,
    formula: PathBuf,
    vba: PathBuf,
    refs: PathBuf,
    names: PathBuf,
}

impl XlPaths {
    fn new(orig: PathBuf) -> Result<XlPaths> {

        if !orig.exists() {
            bail!("Cannot find {}", orig.display());
        }

        if !orig.is_file() {
            bail!("{} is not a file", orig.display());
        }

        match orig.extension().and_then(|e| e.to_str()) {
            Some("xls") | Some("xlsx") | Some("xlsb") | Some("ods") => (),
            Some(e) => bail!("Unrecognized extension: {}", e),
            None => bail!("Expecting an excel file, couln't find an extension"),
        }

        let root: PathBuf = orig.parent()
            .map_or::<PathBuf, _>(".{}".into(), |p| p.into())
            .join(format!(".{}", &*orig.file_name().unwrap().to_string_lossy()));

        if root.exists() {
            fs::remove_dir_all(&root)?;
        }
        fs::create_dir_all(&root)?;
        let data = root.join("data");
        if !data.exists() {
            fs::create_dir(&data)?;
        }
        let vba = root.join("vba");
        if !vba.exists() {
            fs::create_dir(&vba)?;
        }
        let formula = root.join("formula");
        if !formula.exists() {
            fs::create_dir(&formula)?;
        }

        Ok(XlPaths {
            orig: orig,
            data: data,
            formula: formula,
            vba: vba,
            refs: root.join("refs.md"),
            names: root.join("names.md"),
        })
    }
}

fn write_range<P, T>(path: P, range: Range<T>) -> Result<()>
    where P: AsRef<Path>,
          T: PartialEq + Clone + Default + ::std::fmt::Debug,
{
    if range.is_empty() {
        return Ok(());
    }

    let mut f = BufWriter::new(fs::File::create(path.as_ref())?);

    let ((srow, scol), (_, ecol)) = (range.start(), range.end());
    write!(f, "|   ")?;
    for c in scol..ecol+1 {
        write!(f, "| {} ", get_column(c))?;
    }
    writeln!(f, "|")?;
    for _ in scol..ecol+2 {
        write!(f, "|---")?;
    }
    writeln!(f, "|")?;

    // next rows: table data
    let srow = srow as usize + 1;
    for (i, row) in range.rows().enumerate() {
        write!(f, "| {} ", srow + i)?;
        for c in row {
            write!(f, "| {:?} ", c)?;
        }
        writeln!(f, "|")?;
    }
    Ok(())
}

fn get_column(mut col: u32) -> String {
    let mut buf = String::new();
    if col < 26 {
        buf.push((b'A' + col as u8) as char);
    } else {
        let mut rev = String::new();
        while col >= 26 {
            let c = col % 26;
            rev.push((b'A' + c as u8) as char);
            col -= c;
            col /= 26;
        }
        buf.extend(rev.chars().rev());
    }
    buf
}
<|endoftext|>


<commit_before>// Clippy settings, full list here:
// <https://rust-lang.github.io/rust-clippy/master/index.html>
#![allow(clippy::needless_return)]
//
// Fail build on Clippy warnings
#![deny(warnings)]

#[macro_use]
extern crate lazy_static;

use backtrace::Backtrace;
use git_version::git_version;
use isatty::{stdin_isatty, stdout_isatty};
use line_collector::LineCollector;
use std::io::{self};
use std::panic;
use std::path;
use std::process::exit;
use std::process::{Command, Stdio};
use std::str;
use std::{env, fs::File};

mod constants;
mod line_collector;
mod refiner;
mod token_collector;
mod tokenizer;

// NOTE: Setting pager.log to riff makes "git log -p" output look nicer, but
// just "git log" without "-p" look worse. Better not go there.
const HELP_TEXT: &str = r#"
Usage:
  diff ... | riff
  riff [-b] <file1> <file2>
  riff [-b] <directory1> <directory2>

Colors diff output, highlighting the changed parts of every line.

Git integration:
    git config --global pager.diff riff
    git config --global pager.show riff
    git config --global interactive.diffFilter riff

Options:
    -b:        Ignore changes in amount of whitespace
    --help:    Print this text
    --version: Print version number
"#;

const HELP_TEXT_FOOTER: &str = r#"
Report issues at <https://github.com/walles/riff>.
"#;

const CRASH_FOOTER: &str = r#"
Please copy the above crash report and report it at one of:
* <https://github.com/walles/riff/issues> (preferred)
* <johan.walles@gmail.com>
"#;

const PAGER_FORKBOMB_STOP: &str = "_RIFF_IGNORE_PAGER";

const GIT_VERSION: &str = git_version!();

fn highlight_diff<W: io::Write + Send + 'static>(input: &mut dyn io::Read, output: W) {
    let mut line_collector = LineCollector::new(output);

    // Read input line by line, using from_utf8_lossy() to convert lines into
    // strings while handling invalid UTF-8 without crashing
    let mut line_bytes: Vec<u8> = Vec::new();
    let mut buf: [u8; 1] = [0];
    loop {
        let result = input.read(&mut buf);
        if result.is_err() {
            panic!("Error reading input stream: {:?}", result.err().unwrap());
        }

        if result.unwrap() == 0 {
            // End of stream
            if !line_bytes.is_empty() {
                // Stuff found on the last line without a trailing newline
                line_collector.consume_line(String::from_utf8_lossy(&line_bytes).to_string());
            }
            break;
        }

        let single_byte = buf[0];
        if single_byte as char == '\r' {
            // MS-DOS file, LF coming up, just ignore this
            continue;
        }
        if single_byte as char != '\n' {
            // Line contents, store and continue
            line_bytes.push(single_byte);
            continue;
        }

        // Line finished, consume it!
        line_collector.consume_line(String::from_utf8_lossy(&line_bytes).to_string());
        line_bytes.clear();
        continue;
    }
}

/// Try paging using the named pager (`$PATH` will be searched).
///
/// Returns `true` if the pager was found, `false` otherwise.
#[must_use]
fn try_pager(input: &mut dyn io::Read, pager_name: &str) -> bool {
    let mut command = Command::new(pager_name);

    if env::var(PAGER_FORKBOMB_STOP).is_ok() {
        // Try preventing fork bombing if $PAGER is set to riff
        return false;
    }
    command.env(PAGER_FORKBOMB_STOP, "1");

    if env::var("LESS").is_err() {
        // Set by git when paging
        command.env("LESS", "FRX");
    }

    if env::var("LV").is_err() {
        // Set by git when paging
        command.env("LV", "-c");
    }

    command.stdin(Stdio::piped());

    match command.spawn() {
        Ok(mut pager) => {
            let pager_stdin = pager.stdin.unwrap();
            pager.stdin = None;
            highlight_diff(input, pager_stdin);

            // FIXME: Report pager exit status if non-zero, together with
            // contents of pager stderr as well if possible.
            pager.wait().expect("Waiting for pager failed");

            return true;
        }
        Err(_) => {
            return false;
        }
    }
}

/// If `option` is found in `argv`, all instances of `option` will be removed
/// from `argv`.
///
/// Returns `true` if `option` was found and consumed, false otherwise.
#[must_use]
fn consume(option: &str, argv: &mut Vec<String>) -> bool {
    if !argv.contains(&option.to_string()) {
        // Not found
        return false;
    }

    argv.retain(|x| x != option);
    return true;
}

fn print_help(output: &mut dyn io::Write) {
    output.write_all(HELP_TEXT.trim().as_bytes()).unwrap();
    output.write_all(b"\n").unwrap();
    output.write_all(b"\n").unwrap();

    output
        .write_all(b"Installing riff in the $PATH:\n")
        .unwrap();
    output
        .write_all(b"    sudo cp riff /usr/local/bin\n")
        .unwrap();
    output.write_all(b"\n").unwrap();

    output
        .write_all(HELP_TEXT_FOOTER.trim().as_bytes())
        .unwrap();
    output.write_all(b"\n").unwrap();
}

fn panic_handler(panic_info: &panic::PanicInfo) {
    eprintln!("\n\n-v-v-v----------- RIFF CRASHED ---------------v-v-v-\n",);

    // Panic message
    eprintln!("Panic message: <{:#?}>", panic_info);
    eprintln!();

    // Backtrace
    eprintln!("{:?}", Backtrace::new());

    eprintln!("Riff version: {}", GIT_VERSION);

    eprintln!();
    eprintln!("Command line arguments: {:?}", env::args());

    eprintln!("\n-^-^-^------- END OF RIFF CRASH REPORT -------^-^-^-\n",);

    eprintln!("{}", CRASH_FOOTER);
}

fn highlight_stream(input: &mut dyn io::Read) {
    if !stdout_isatty() {
        // We're being piped, just do stdin -> stdout
        highlight_diff(input, io::stdout());
        return;
    }

    if let Ok(pager_value) = env::var("PAGER") {
        if try_pager(input, &pager_value) {
            return;
        }

        // FIXME: Print warning at the end if $PAGER was set to something that
        // doesn't exist.
    }

    if try_pager(input, "moar") {
        return;
    }

    if try_pager(input, "less") {
        return;
    }

    // No pager found, wth?
    highlight_diff(input, io::stdout());
}

pub fn type_string(path: &path::Path) -> &str {
    if !path.exists() {
        return "Not found";
    }
    if path.is_file() {
        return "File";
    }
    if path.is_dir() {
        return "Directory";
    }
    return "Not file not dir";
}

fn ensure_readable(path: &path::Path) {
    if let Err(why) = File::open(path) {
        eprintln!("ERROR: {}: {}", why, path.to_string_lossy());
        exit(1);
    };
}

fn ensure_listable(path: &path::Path) {
    if let Err(why) = std::fs::read_dir(path) {
        eprintln!("ERROR: {}: {}", why, path.to_string_lossy());
        exit(1);
    }
}

fn exec_diff_highlight(path1: &str, path2: &str, ignore_space_change: bool) {
    let path1 = path::Path::new(path1);
    let path2 = path::Path::new(path2);
    let both_paths_are_files = path1.is_file() && path2.is_file();
    let both_paths_are_dirs = path1.is_dir() && path2.is_dir();

    if !(both_paths_are_files || both_paths_are_dirs) {
        eprintln!("Can only compare file to file or directory to directory, not like this:",);
        eprintln!("  {:<9}: {}", type_string(path1), path1.to_string_lossy());
        eprintln!("  {:<9}: {}", type_string(path2), path2.to_string_lossy());
        exit(1);
    }

    if both_paths_are_files {
        ensure_readable(path1);
        ensure_readable(path2);
    } else {
        ensure_listable(path1);
        ensure_listable(path2);
    }

    // Run "diff -ur file1 file2"
    let mut command: &mut Command = &mut Command::new("diff");

    if ignore_space_change {
        command = command.arg("-b");
    }

    let command = command
        .arg("-ur") // "-u = unified diff, -r = recurse subdirectories"
        .arg(path1)
        .arg(path2)
        .stdout(Stdio::piped());

    let pretty_command = format!("{:#?}", command);
    let mut diff_subprocess = command.spawn().expect(&pretty_command);
    let diff_stdout = diff_subprocess.stdout.as_mut().unwrap();
    highlight_stream(diff_stdout);

    let diff_result = diff_subprocess.wait().unwrap();
    let diff_exit_code = diff_result.code().unwrap_or(2);
    if diff_exit_code != 0 && diff_exit_code != 1 {
        // diff exit code was neither 0 (comparees identical) or 1 (differences
        // found), this means trouble.
        eprintln!("Exit code {}: {}", diff_exit_code, pretty_command);
        exit(diff_exit_code);
    }
}

fn main() {
    panic::set_hook(Box::new(|panic_info: &panic::PanicInfo| {
        panic_handler(panic_info);
    }));

    let mut args: Vec<String> = env::args().collect();
    if consume("--help", &mut args) || consume("-h", &mut args) {
        print_help(&mut io::stdout());
        return;
    }

    if consume("--version", &mut args) {
        println!("riff {}", GIT_VERSION);
        println!();
        println!("Source code available at <https://github.com/walles/riff>.");
        return;
    }

    let ignore_space_change = consume("-b", &mut args);

    if consume("--please-panic", &mut args) {
        panic!("Panicking on purpose");
    }

    if args.len() == 3 {
        // "riff file1 file2"
        exec_diff_highlight(
            args.get(1).unwrap(),
            args.get(2).unwrap(),
            ignore_space_change,
        );
        return;
    }

    if ignore_space_change {
        eprintln!(
            "ERROR: -b is only supported when diffing two named paths (\"riff -b a.txt b.txt\")"
        );
        eprintln!();
        print_help(&mut io::stderr());
        exit(1);
    }

    if args.len() != 1 {
        eprintln!("ERROR: Unknown command line: {:?}", args);
        eprintln!();
        print_help(&mut io::stderr());
        exit(1);
    }

    if stdin_isatty() {
        eprintln!("ERROR: Expected input from a pipe");
        eprintln!();
        print_help(&mut io::stderr());
        exit(1);
    }

    highlight_stream(&mut io::stdin().lock());
}

#[cfg(test)]
mod tests {
    use crate::constants::*;

    use super::*;
    use std::fs;

    #[cfg(test)]
    use pretty_assertions::assert_eq;

    fn new(text: &str) -> String {
        return format!("{}{}{}", NEW, text, NORMAL);
    }

    #[test]
    fn test_trailing_newline_context() {
        let mut input = "+bepa\n apa\n\\ No newline at end of file\n".as_bytes();

        let expected = format!(
            "{}\n{}\n{}\n",
            new("+bepa"),
            " apa",
            format!(
                "{}\\ No newline at end of file{}",
                NO_EOF_NEWLINE_COLOR, NORMAL
            )
        );

        let file = tempfile::NamedTempFile::new().unwrap();
        highlight_diff(&mut input, file.reopen().unwrap());
        let actual = fs::read_to_string(file.path()).unwrap();
        // collect()ing into line vectors inside of this assert() statement
        // splits test failure output into lines, making it easier to digest.
        assert_eq!(
            actual.lines().collect::<Vec<_>>(),
            expected.lines().collect::<Vec<_>>()
        );
    }

    #[test]
    fn test_testdata_examples() {
        // Example value: `/Users/johan/src/riff/target/debug/deps/riff-7a8916c06b0d3d6c`
        let exe_path = std::env::current_exe().unwrap();

        // Example value: `/Users/johan/src/riff`
        let project_path = exe_path
            .parent()
            .unwrap()
            .parent()
            .unwrap()
            .parent()
            .unwrap()
            .parent()
            .unwrap();

        // Example value: `/Users/johan/src/riff/testdata`
        let testdata_path = &project_path.join("testdata");
        assert!(testdata_path.is_dir());

        // Iterate all files in there
        let mut failing_example: Option<String> = None;
        let mut failing_example_expected = vec![];
        let mut failing_example_actual = vec![];
        for diff in fs::read_dir(testdata_path).unwrap() {
            let diff = diff.unwrap();
            let diff = diff.path();
            let diff = diff.as_path();
            if !diff.is_file() {
                continue;
            }

            if diff.extension().unwrap() != "diff" {
                continue;
            }

            println!("Evaluating example file <{}>...", diff.to_str().unwrap());

            // Run highlighting on the file into a memory buffer
            let file = tempfile::NamedTempFile::new().unwrap();
            highlight_diff(&mut fs::File::open(diff).unwrap(), file.reopen().unwrap());
            let actual_result = fs::read_to_string(file.path()).unwrap();

            // Load the corresponding .riff-output file into a string
            let basename = diff.file_stem().unwrap().to_str().unwrap();
            let expected_path = format!(
                "{}/{}.riff-output",
                testdata_path.to_str().unwrap(),
                basename
            );
            let expected_result = fs::read_to_string(expected_path).unwrap();

            // Assert that the highlighting output matches the contents of .riff-output
            let actual_lines: Vec<String> = actual_result.split('\n').map(str::to_string).collect();
            let expected_lines: Vec<String> =
                expected_result.split('\n').map(str::to_string).collect();

            if actual_lines != expected_lines {
                if failing_example.is_none() {
                    failing_example = Some(diff.to_str().unwrap().to_string());
                    failing_example_actual = actual_lines;
                    failing_example_expected = expected_lines;
                }

                println!("  FAILED: Output mismatches!");
            }
        }

        if failing_example.is_some() {
            println!();
            println!("Example: {}", failing_example.unwrap());
            assert_eq!(failing_example_actual, failing_example_expected);
        }
    }
}
<commit_msg>Implement --no-pager<commit_after>// Clippy settings, full list here:
// <https://rust-lang.github.io/rust-clippy/master/index.html>
#![allow(clippy::needless_return)]
//
// Fail build on Clippy warnings
#![deny(warnings)]

#[macro_use]
extern crate lazy_static;

use backtrace::Backtrace;
use git_version::git_version;
use isatty::{stdin_isatty, stdout_isatty};
use line_collector::LineCollector;
use std::io::{self};
use std::panic;
use std::path;
use std::process::exit;
use std::process::{Command, Stdio};
use std::str;
use std::{env, fs::File};

mod constants;
mod line_collector;
mod refiner;
mod token_collector;
mod tokenizer;

// NOTE: Setting pager.log to riff makes "git log -p" output look nicer, but
// just "git log" without "-p" look worse. Better not go there.
const HELP_TEXT: &str = r#"
Usage:
  diff ... | riff
  riff [-b] [--no-pager] <file1> <file2>
  riff [-b] [--no-pager] <directory1> <directory2>

Colors diff output, highlighting the changed parts of every line.

Git integration:
    git config --global pager.diff riff
    git config --global pager.show riff
    git config --global interactive.diffFilter riff

Options:
    -b:         Ignore changes in amount of whitespace
    --no-pager: Don't page the result

    --help:     Print this text
    --version:  Print version number
"#;

const HELP_TEXT_FOOTER: &str = r#"
Report issues at <https://github.com/walles/riff>.
"#;

const CRASH_FOOTER: &str = r#"
Please copy the above crash report and report it at one of:
* <https://github.com/walles/riff/issues> (preferred)
* <johan.walles@gmail.com>
"#;

const PAGER_FORKBOMB_STOP: &str = "_RIFF_IGNORE_PAGER";

const GIT_VERSION: &str = git_version!();

fn highlight_diff<W: io::Write + Send + 'static>(input: &mut dyn io::Read, output: W) {
    let mut line_collector = LineCollector::new(output);

    // Read input line by line, using from_utf8_lossy() to convert lines into
    // strings while handling invalid UTF-8 without crashing
    let mut line_bytes: Vec<u8> = Vec::new();
    let mut buf: [u8; 1] = [0];
    loop {
        let result = input.read(&mut buf);
        if result.is_err() {
            panic!("Error reading input stream: {:?}", result.err().unwrap());
        }

        if result.unwrap() == 0 {
            // End of stream
            if !line_bytes.is_empty() {
                // Stuff found on the last line without a trailing newline
                line_collector.consume_line(String::from_utf8_lossy(&line_bytes).to_string());
            }
            break;
        }

        let single_byte = buf[0];
        if single_byte as char == '\r' {
            // MS-DOS file, LF coming up, just ignore this
            continue;
        }
        if single_byte as char != '\n' {
            // Line contents, store and continue
            line_bytes.push(single_byte);
            continue;
        }

        // Line finished, consume it!
        line_collector.consume_line(String::from_utf8_lossy(&line_bytes).to_string());
        line_bytes.clear();
        continue;
    }
}

/// Try paging using the named pager (`$PATH` will be searched).
///
/// Returns `true` if the pager was found, `false` otherwise.
#[must_use]
fn try_pager(input: &mut dyn io::Read, pager_name: &str) -> bool {
    let mut command = Command::new(pager_name);

    if env::var(PAGER_FORKBOMB_STOP).is_ok() {
        // Try preventing fork bombing if $PAGER is set to riff
        return false;
    }
    command.env(PAGER_FORKBOMB_STOP, "1");

    if env::var("LESS").is_err() {
        // Set by git when paging
        command.env("LESS", "FRX");
    }

    if env::var("LV").is_err() {
        // Set by git when paging
        command.env("LV", "-c");
    }

    command.stdin(Stdio::piped());

    match command.spawn() {
        Ok(mut pager) => {
            let pager_stdin = pager.stdin.unwrap();
            pager.stdin = None;
            highlight_diff(input, pager_stdin);

            // FIXME: Report pager exit status if non-zero, together with
            // contents of pager stderr as well if possible.
            pager.wait().expect("Waiting for pager failed");

            return true;
        }
        Err(_) => {
            return false;
        }
    }
}

/// If `option` is found in `argv`, all instances of `option` will be removed
/// from `argv`.
///
/// Returns `true` if `option` was found and consumed, false otherwise.
#[must_use]
fn consume(option: &str, argv: &mut Vec<String>) -> bool {
    if !argv.contains(&option.to_string()) {
        // Not found
        return false;
    }

    argv.retain(|x| x != option);
    return true;
}

fn print_help(output: &mut dyn io::Write) {
    output.write_all(HELP_TEXT.trim().as_bytes()).unwrap();
    output.write_all(b"\n").unwrap();
    output.write_all(b"\n").unwrap();

    output
        .write_all(b"Installing riff in the $PATH:\n")
        .unwrap();
    output
        .write_all(b"    sudo cp riff /usr/local/bin\n")
        .unwrap();
    output.write_all(b"\n").unwrap();

    output
        .write_all(HELP_TEXT_FOOTER.trim().as_bytes())
        .unwrap();
    output.write_all(b"\n").unwrap();
}

fn panic_handler(panic_info: &panic::PanicInfo) {
    eprintln!("\n\n-v-v-v----------- RIFF CRASHED ---------------v-v-v-\n",);

    // Panic message
    eprintln!("Panic message: <{:#?}>", panic_info);
    eprintln!();

    // Backtrace
    eprintln!("{:?}", Backtrace::new());

    eprintln!("Riff version: {}", GIT_VERSION);

    eprintln!();
    eprintln!("Command line arguments: {:?}", env::args());

    eprintln!("\n-^-^-^------- END OF RIFF CRASH REPORT -------^-^-^-\n",);

    eprintln!("{}", CRASH_FOOTER);
}

fn highlight_stream(input: &mut dyn io::Read, no_pager: bool) {
    if !stdout_isatty() {
        // We're being piped, just do stdin -> stdout
        highlight_diff(input, io::stdout());
        return;
    }

    if no_pager {
        highlight_diff(input, io::stdout());
        return;
    }

    if let Ok(pager_value) = env::var("PAGER") {
        if try_pager(input, &pager_value) {
            return;
        }

        // FIXME: Print warning at the end if $PAGER was set to something that
        // doesn't exist.
    }

    if try_pager(input, "moar") {
        return;
    }

    if try_pager(input, "less") {
        return;
    }

    // No pager found, wth?
    highlight_diff(input, io::stdout());
}

pub fn type_string(path: &path::Path) -> &str {
    if !path.exists() {
        return "Not found";
    }
    if path.is_file() {
        return "File";
    }
    if path.is_dir() {
        return "Directory";
    }
    return "Not file not dir";
}

fn ensure_readable(path: &path::Path) {
    if let Err(why) = File::open(path) {
        eprintln!("ERROR: {}: {}", why, path.to_string_lossy());
        exit(1);
    };
}

fn ensure_listable(path: &path::Path) {
    if let Err(why) = std::fs::read_dir(path) {
        eprintln!("ERROR: {}: {}", why, path.to_string_lossy());
        exit(1);
    }
}

fn exec_diff_highlight(path1: &str, path2: &str, ignore_space_change: bool, no_pager: bool) {
    let path1 = path::Path::new(path1);
    let path2 = path::Path::new(path2);
    let both_paths_are_files = path1.is_file() && path2.is_file();
    let both_paths_are_dirs = path1.is_dir() && path2.is_dir();

    if !(both_paths_are_files || both_paths_are_dirs) {
        eprintln!("Can only compare file to file or directory to directory, not like this:",);
        eprintln!("  {:<9}: {}", type_string(path1), path1.to_string_lossy());
        eprintln!("  {:<9}: {}", type_string(path2), path2.to_string_lossy());
        exit(1);
    }

    if both_paths_are_files {
        ensure_readable(path1);
        ensure_readable(path2);
    } else {
        ensure_listable(path1);
        ensure_listable(path2);
    }

    // Run "diff -ur file1 file2"
    let mut command: &mut Command = &mut Command::new("diff");

    if ignore_space_change {
        command = command.arg("-b");
    }

    let command = command
        .arg("-ur") // "-u = unified diff, -r = recurse subdirectories"
        .arg(path1)
        .arg(path2)
        .stdout(Stdio::piped());

    let pretty_command = format!("{:#?}", command);
    let mut diff_subprocess = command.spawn().expect(&pretty_command);
    let diff_stdout = diff_subprocess.stdout.as_mut().unwrap();
    highlight_stream(diff_stdout, no_pager);

    let diff_result = diff_subprocess.wait().unwrap();
    let diff_exit_code = diff_result.code().unwrap_or(2);
    if diff_exit_code != 0 && diff_exit_code != 1 {
        // diff exit code was neither 0 (comparees identical) or 1 (differences
        // found), this means trouble.
        eprintln!("Exit code {}: {}", diff_exit_code, pretty_command);
        exit(diff_exit_code);
    }
}

fn main() {
    panic::set_hook(Box::new(|panic_info: &panic::PanicInfo| {
        panic_handler(panic_info);
    }));

    let mut args: Vec<String> = env::args().collect();
    if consume("--help", &mut args) || consume("-h", &mut args) {
        print_help(&mut io::stdout());
        return;
    }

    if consume("--version", &mut args) {
        println!("riff {}", GIT_VERSION);
        println!();
        println!("Source code available at <https://github.com/walles/riff>.");
        return;
    }

    let ignore_space_change = consume("-b", &mut args);

    if consume("--please-panic", &mut args) {
        panic!("Panicking on purpose");
    }

    let no_pager = consume("--no-pager", &mut args);

    if args.len() == 3 {
        // "riff file1 file2"
        exec_diff_highlight(
            args.get(1).unwrap(),
            args.get(2).unwrap(),
            ignore_space_change,
            no_pager,
        );
        return;
    }

    if ignore_space_change {
        eprintln!(
            "ERROR: -b is only supported when diffing two named paths (\"riff -b a.txt b.txt\")"
        );
        eprintln!();
        print_help(&mut io::stderr());
        exit(1);
    }

    if args.len() != 1 {
        eprintln!("ERROR: Unknown command line: {:?}", args);
        eprintln!();
        print_help(&mut io::stderr());
        exit(1);
    }

    if stdin_isatty() {
        eprintln!("ERROR: Expected input from a pipe");
        eprintln!();
        print_help(&mut io::stderr());
        exit(1);
    }

    highlight_stream(&mut io::stdin().lock(), no_pager);
}

#[cfg(test)]
mod tests {
    use crate::constants::*;

    use super::*;
    use std::fs;

    #[cfg(test)]
    use pretty_assertions::assert_eq;

    fn new(text: &str) -> String {
        return format!("{}{}{}", NEW, text, NORMAL);
    }

    #[test]
    fn test_trailing_newline_context() {
        let mut input = "+bepa\n apa\n\\ No newline at end of file\n".as_bytes();

        let expected = format!(
            "{}\n{}\n{}\n",
            new("+bepa"),
            " apa",
            format!(
                "{}\\ No newline at end of file{}",
                NO_EOF_NEWLINE_COLOR, NORMAL
            )
        );

        let file = tempfile::NamedTempFile::new().unwrap();
        highlight_diff(&mut input, file.reopen().unwrap());
        let actual = fs::read_to_string(file.path()).unwrap();
        // collect()ing into line vectors inside of this assert() statement
        // splits test failure output into lines, making it easier to digest.
        assert_eq!(
            actual.lines().collect::<Vec<_>>(),
            expected.lines().collect::<Vec<_>>()
        );
    }

    #[test]
    fn test_testdata_examples() {
        // Example value: `/Users/johan/src/riff/target/debug/deps/riff-7a8916c06b0d3d6c`
        let exe_path = std::env::current_exe().unwrap();

        // Example value: `/Users/johan/src/riff`
        let project_path = exe_path
            .parent()
            .unwrap()
            .parent()
            .unwrap()
            .parent()
            .unwrap()
            .parent()
            .unwrap();

        // Example value: `/Users/johan/src/riff/testdata`
        let testdata_path = &project_path.join("testdata");
        assert!(testdata_path.is_dir());

        // Iterate all files in there
        let mut failing_example: Option<String> = None;
        let mut failing_example_expected = vec![];
        let mut failing_example_actual = vec![];
        for diff in fs::read_dir(testdata_path).unwrap() {
            let diff = diff.unwrap();
            let diff = diff.path();
            let diff = diff.as_path();
            if !diff.is_file() {
                continue;
            }

            if diff.extension().unwrap() != "diff" {
                continue;
            }

            println!("Evaluating example file <{}>...", diff.to_str().unwrap());

            // Run highlighting on the file into a memory buffer
            let file = tempfile::NamedTempFile::new().unwrap();
            highlight_diff(&mut fs::File::open(diff).unwrap(), file.reopen().unwrap());
            let actual_result = fs::read_to_string(file.path()).unwrap();

            // Load the corresponding .riff-output file into a string
            let basename = diff.file_stem().unwrap().to_str().unwrap();
            let expected_path = format!(
                "{}/{}.riff-output",
                testdata_path.to_str().unwrap(),
                basename
            );
            let expected_result = fs::read_to_string(expected_path).unwrap();

            // Assert that the highlighting output matches the contents of .riff-output
            let actual_lines: Vec<String> = actual_result.split('\n').map(str::to_string).collect();
            let expected_lines: Vec<String> =
                expected_result.split('\n').map(str::to_string).collect();

            if actual_lines != expected_lines {
                if failing_example.is_none() {
                    failing_example = Some(diff.to_str().unwrap().to_string());
                    failing_example_actual = actual_lines;
                    failing_example_expected = expected_lines;
                }

                println!("  FAILED: Output mismatches!");
            }
        }

        if failing_example.is_some() {
            println!();
            println!("Example: {}", failing_example.unwrap());
            assert_eq!(failing_example_actual, failing_example_expected);
        }
    }
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate rustc_serialize;

use docopt::Docopt;

const USAGE: &'static str = "
how-do-i-escape: Prints escape sequences for unicode graphemes

Usage:
  how-do-i-escape <grapheme>
  how-do-i-escape (--help | --version)

Options:
  -h, --help  Show this screen.
  --version   Show version.

Example:
  $ how-do-i-escape \u{00A7}
  css  = \"\\00A7\"
  html = §
  js   = \"\\u00A7\"
";

#[derive(RustcDecodable)]
struct Args {
    arg_grapheme: String,
}

fn main() {
    let version = format!("v{}", env!("CARGO_PKG_VERSION"));

    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.help(true).version(Some(version)).decode())
        .unwrap_or_else(|e| e.exit());

    let grapheme = args.arg_grapheme;

    println!(r#"css  = "{}""#, escape_grapheme(&grapheme, as_css));
    println!(r#"html = {}"#, escape_grapheme(&grapheme, as_html));
    println!(r#"js   = "{}""#, escape_grapheme(&grapheme, as_js));
}

fn escape_grapheme<F>(grapheme: &str, int_to_escape_sequence: F) -> String
    where F: Fn(u32) -> String
{
    grapheme.chars()
        .map(|ch| ch as u32)
        .map(int_to_escape_sequence)
        .collect()
}

fn as_css(i: u32) -> String {
    format!("\\{:01$X}", i, 4)
}

fn as_html(i: u32) -> String {
    format!("&#x{:01$X};", i, 4)
}

fn as_js(i: u32) -> String {
    if i <= 0xFFFF {
        format!("\\u{:01$X}", i, 4)
    } else {
        format!("\\u{{{:X}}}", i)
    }
}

#[cfg(test)]
mod tests {
    use super::{as_css, as_html, as_js, escape_grapheme};

    #[test]
    fn test_as_css() {
        assert!(as_css(0) == r"\0000");
        assert!(as_css(0xFFFF) == r"\FFFF");
        assert!(as_css(0xBEEF) != r"\beef");
        // assert!(as_css(0x10000) == ?);
    }

    #[test]
    fn test_as_html() {
        assert!(as_html(0) == r"�");
        assert!(as_html(0xFFFF) == r"");
        assert!(as_html(0xBEEF) != r"뻯");
        // assert!(as_html(0x10000) == ?);
    }

    #[test]
    fn test_as_js() {
        assert!(as_js(0) == r"\u0000");
        assert!(as_js(0xFFFF) == r"\uFFFF");
        assert!(as_js(0xBEEF) != r"\ubeef");
        assert!(as_js(0x10000) == r"\u{10000}");
        assert!(as_js(0x10FFFF) == r"\u{10FFFF}");
        assert!(as_js(0xFFFFFFFF) == r"\u{FFFFFFFF}");
    }

    #[test]
    fn test_escape_grapheme() {
        let always_hello = escape_grapheme("\u{FF}", |_| "hello".to_string());
        assert!(always_hello == "hello");

        let simple = escape_grapheme("\u{FF}", |i| format!("{}", i));
        assert!(simple == "255");
    }
}
<commit_msg>Add initial html entity code<commit_after>extern crate docopt;
extern crate rustc_serialize;

use docopt::Docopt;
use std::collections::HashMap;

const USAGE: &'static str = "
how-do-i-escape: Prints escape sequences for unicode graphemes

Usage:
  how-do-i-escape <grapheme>
  how-do-i-escape (--help | --version)

Options:
  -h, --help  Show this screen.
  --version   Show version.

Example:
  $ how-do-i-escape \u{00A7}
  css  = \"\\00A7\"
  html = §
  js   = \"\\u00A7\"
";

#[derive(RustcDecodable)]
struct Args {
    arg_grapheme: String,
}

fn main() {
    let version = format!("v{}", env!("CARGO_PKG_VERSION"));

    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.help(true).version(Some(version)).decode())
        .unwrap_or_else(|e| e.exit());

    let grapheme = args.arg_grapheme;

    println!(r#"css  = "{}""#, escape_grapheme(&grapheme, as_css));
    println!(r#"html = {}"#, escape_grapheme(&grapheme, as_html));
    println!(r#"js   = "{}""#, escape_grapheme(&grapheme, as_js));
}

fn escape_grapheme<F>(grapheme: &str, int_to_escape_sequence: F) -> String
    where F: Fn(u32) -> String
{
    grapheme.chars()
        .map(|ch| ch as u32)
        .map(int_to_escape_sequence)
        .collect()
}

fn as_css(i: u32) -> String {
    format!("\\{:01$X}", i, 4)
}

fn as_html(i: u32) -> String {
    match get_entity_map().get(&i) {
        Some(entity) => entity.clone(),
        None => format!("&#x{:01$X};", i, 4),
    }
}

fn get_entity_map() -> HashMap<u32, String> {
    let mut entity_map = HashMap::new();
    entity_map.insert(',' as u32, r",".to_string());
    entity_map
}

fn as_js(i: u32) -> String {
    if i <= 0xFFFF {
        format!("\\u{:01$X}", i, 4)
    } else {
        format!("\\u{{{:X}}}", i)
    }
}

#[cfg(test)]
mod tests {
    use super::{as_css, as_html, as_js, escape_grapheme};

    #[test]
    fn test_as_css() {
        assert!(as_css(0) == r"\0000");
        assert!(as_css(0xFFFF) == r"\FFFF");
        assert!(as_css(0xBEEF) != r"\beef");
        // assert!(as_css(0x10000) == ?);
    }

    #[test]
    fn test_as_html() {
        assert!(as_html(0) == r"�");
        assert!(as_html(0xFFFF) == r"");
        assert!(as_html(0xBEEF) != r"뻯");
        assert!(as_html(',' as u32) == r",");
        // assert!(as_html(0x10000) == ?);
    }

    #[test]
    fn test_as_js() {
        assert!(as_js(0) == r"\u0000");
        assert!(as_js(0xFFFF) == r"\uFFFF");
        assert!(as_js(0xBEEF) != r"\ubeef");
        assert!(as_js(0x10000) == r"\u{10000}");
        assert!(as_js(0x10FFFF) == r"\u{10FFFF}");
        assert!(as_js(0xFFFFFFFF) == r"\u{FFFFFFFF}");
    }

    #[test]
    fn test_escape_grapheme() {
        let always_hello = escape_grapheme("\u{FF}", |_| "hello".to_string());
        assert!(always_hello == "hello");

        let simple = escape_grapheme("\u{FF}", |i| format!("{}", i));
        assert!(simple == "255");
    }
}
<|endoftext|>


<commit_before>extern crate nalgebra;
extern crate num;

use num::cast;
use std::ops;

pub type DiscreteSpace = u32;
pub type RealSpace = f32;

pub trait FromDomain<T> {
    fn from_domain(value: T) -> Self;
}

pub trait IntoDomain<T> {
    fn into_domain(self) -> T;
}

impl<T, U> IntoDomain<U> for T
    where U: FromDomain<T>
{
    fn into_domain(self) -> U {
        U::from_domain(self)
    }
}

pub trait Clamp<T>
    where T: PartialOrd
{
    fn clamp(&self, min: T, max: T) -> Self;
}

pub trait Mask<T>
    where T: ops::BitAnd<Output = T>
{
    fn mask(&self, value: T) -> Self;
}

impl<T, U> FromDomain<nalgebra::Point3<U>> for nalgebra::Point3<T>
    where T: cast::NumCast,
          U: num::ToPrimitive
{
    fn from_domain(point: nalgebra::Point3<U>) -> Self {
        nalgebra::Point3::new(T::from(point.x).unwrap(),
                              T::from(point.y).unwrap(),
                              T::from(point.z).unwrap())
    }
}

impl<T, U> FromDomain<nalgebra::Vector3<U>> for nalgebra::Vector3<T>
    where T: cast::NumCast,
          U: num::ToPrimitive
{
    fn from_domain(vector: nalgebra::Vector3<U>) -> Self {
        nalgebra::Vector3::new(T::from(vector.x).unwrap(),
                               T::from(vector.y).unwrap(),
                               T::from(vector.z).unwrap())
    }
}

impl<T> Clamp<T> for nalgebra::Point3<T>
    where T: Copy,
          T: PartialOrd
{
    fn clamp(&self, min: T, max: T) -> Self {
        nalgebra::Point3::new(nalgebra::clamp(self.x, min, max),
                              nalgebra::clamp(self.y, min, max),
                              nalgebra::clamp(self.z, min, max))
    }
}

impl<T> Mask<T> for nalgebra::Point3<T>
    where T: Copy,
          T: ops::BitAnd<Output = T>
{
    fn mask(&self, value: T) -> Self {
        nalgebra::Point3::new(self.x & value, self.y & value, self.z & value)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
}
<commit_msg>Use `nalgebra::Cast` for converting points and vectors.<commit_after>extern crate nalgebra;

use std::ops;

pub type DiscreteSpace = u32;
pub type RealSpace = f32;

pub trait FromDomain<T> {
    fn from_domain(value: T) -> Self;
}

pub trait IntoDomain<T> {
    fn into_domain(self) -> T;
}

impl<T, U> IntoDomain<U> for T
    where U: FromDomain<T>
{
    fn into_domain(self) -> U {
        U::from_domain(self)
    }
}

pub trait Clamp<T>
    where T: PartialOrd
{
    fn clamp(&self, min: T, max: T) -> Self;
}

pub trait Mask<T>
    where T: ops::BitAnd<Output = T>
{
    fn mask(&self, value: T) -> Self;
}

impl<T, U> FromDomain<nalgebra::Point3<U>> for nalgebra::Point3<T>
    where T: nalgebra::Cast<U> + Copy,
          U: Copy
{
    fn from_domain(point: nalgebra::Point3<U>) -> Self {
        nalgebra::cast(point)
    }
}

impl<T, U> FromDomain<nalgebra::Vector3<U>> for nalgebra::Vector3<T>
    where T: nalgebra::Cast<U> + Copy,
          U: Copy
{
    fn from_domain(vector: nalgebra::Vector3<U>) -> Self {
        nalgebra::cast(vector)
    }
}

impl<T> Clamp<T> for nalgebra::Point3<T>
    where T: Copy,
          T: PartialOrd
{
    fn clamp(&self, min: T, max: T) -> Self {
        nalgebra::Point3::new(nalgebra::clamp(self.x, min, max),
                              nalgebra::clamp(self.y, min, max),
                              nalgebra::clamp(self.z, min, max))
    }
}

impl<T> Mask<T> for nalgebra::Point3<T>
    where T: Copy,
          T: ops::BitAnd<Output = T>
{
    fn mask(&self, value: T) -> Self {
        nalgebra::Point3::new(self.x & value, self.y & value, self.z & value)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
}
<|endoftext|>