<commit_before>use std::collections::HashMap;
use std::io::{self, Write};
use std::iter::Peekable;
use std::process::{Command, ExitStatus};
use std::str::CharIndices;

// TODO(tsion): Use the readline library.
fn prompt(line: &mut String) -> io::Result<usize> {
    let current_dir = try!(std::env::current_dir());
    print!("{}> ", current_dir.display());
    try!(io::stdout().flush());
    io::stdin().read_line(line)
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Ast {
    Empty,
    Call { command: String, args: Vec<String> }
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Token {
    Newline,
    Whitespace,
    Text(String),
}

#[derive(Clone)]
struct Lexer<'a> {
    input: &'a str,
    iter: Peekable<CharIndices<'a>>,
}

impl<'a> Lexer<'a> {
    fn new(input: &str) -> Lexer {
        Lexer {
            input: input,
            iter: input.char_indices().peekable(),
        }
    }

    fn pos(&mut self) -> usize {
        self.iter.peek().map(|p| p.0).unwrap_or(self.input.len())
    }

    fn peek_char(&mut self) -> Option<char> {
        self.iter.peek().map(|p| p.1)
    }

    fn is_whitespace(c: char) -> bool {
        c == ' ' || c == '\t'
    }

    fn lex_whitespace(&mut self) -> Token {
        while let Some(c) = self.peek_char() {
            if !Lexer::is_whitespace(c) { break; }
            self.iter.next();
        }

        Token::Whitespace
    }

    fn lex_unquoted_text(&mut self) -> Token {
        let start = self.pos();

        while let Some(c) = self.peek_char() {
            if Lexer::is_whitespace(c) || c == '\r' || c == '\n' { break; }
            self.iter.next();
        }

        let end = self.pos();

        // TODO(tsion): Do this without allocation.
        Token::Text(String::from(&self.input[start..end]))
    }
}

impl<'a> Iterator for Lexer<'a> {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        self.peek_char().map(|peek_char| {
            match peek_char {
                '\r' | '\n'                  => { self.iter.next(); Token::Newline },
                c if Lexer::is_whitespace(c) => self.lex_whitespace(),
                _                            => self.lex_unquoted_text(),
            }
        })
    }
}

#[derive(Clone)]
struct Parser<'a> {
    lexer: Lexer<'a>,
}

impl<'a> Parser<'a> {
    fn new(input: &str) -> Parser {
        Parser { lexer: Lexer::new(input) }
    }

    fn parse(&mut self) -> Ast {
        match self.lexer.next() {
            Some(Token::Whitespace) | Some(Token::Newline) => self.parse(),
            Some(Token::Text(command)) => self.parse_call(command),
            None => Ast::Empty,
        }
    }

    fn parse_call(&mut self, command: String) -> Ast {
        let mut args = vec![];

        for token in &mut self.lexer {
            match token {
                Token::Newline    => break,
                Token::Whitespace => {},
                Token::Text(arg)  => { args.push(arg); },
            }
        }

        Ast::Call { command: command, args: args }
    }
}

struct Builtin {
    name: &'static str,
    min_args: usize,
    max_args: usize,
    func: fn(&[String]) -> i32,
}

fn result_to_exit_code(result: io::Result<()>) -> i32 {
    match result {
        Ok(()) => 0,
        Err(e) => {
            writeln!(&mut io::stderr(), "cd: {}", e).unwrap();
            1
        },
    }
}

fn builtin_cd(args: &[String]) -> i32 {
    if let Some(path) = args.get(0) {
        result_to_exit_code(std::env::set_current_dir(path))
    } else if let Some(home) = std::env::home_dir() {
        result_to_exit_code(std::env::set_current_dir(home))
    } else {
        writeln!(&mut io::stderr(), "cd: couldn't find home dir").unwrap();
        1
    }
}

fn builtin_exit(args: &[String]) -> i32 {
    if let Some(exit_code_str) = args.get(0) {
        match exit_code_str.parse() {
            Ok(exit_code) => std::process::exit(exit_code),
            Err(e) => {
                writeln!(&mut io::stderr(), "exit: can't parse exit code: {}", e).unwrap();
                1
            },
        }
    } else {
        std::process::exit(0);
    }
}

fn execute(ast: &Ast) -> i32 {
    let mut builtins = HashMap::new();

    builtins.insert("cd", Builtin {
        name: "cd",
        min_args: 0,
        max_args: 1,
        func: builtin_cd,
    });

    builtins.insert("exit", Builtin {
        name: "exit",
        min_args: 0,
        max_args: 1,
        func: builtin_exit,
    });

    match *ast {
        Ast::Empty => 0,

        Ast::Call { ref command, ref args } => {
            if let Some(builtin) = builtins.get(&command[..]) {
                if args.len() < builtin.min_args {
                    writeln!(&mut io::stderr(), "{}: not enough arguments", builtin.name).unwrap();
                    1
                } else if args.len() > builtin.max_args {
                    writeln!(&mut io::stderr(), "{}: too many arguments", builtin.name).unwrap();
                    1
                } else {
                    (builtin.func)(args)
                }
            } else {
                match Command::new(command).args(args).status() {
                    Ok(exit_status) => {
                        #[cfg(unix)]
                        fn exit_signal(exit_status: &ExitStatus) -> Option<i32> {
                            use std::os::unix::process::ExitStatusExt;
                            exit_status.signal()
                        }

                        #[cfg(not(unix))]
                        fn exit_signal(_exit_status: &ExitStatus) -> Option<i32> {
                            None
                        }

                        if let Some(code) = exit_status.code() {
                            code
                        } else if let Some(signal) = exit_signal(&exit_status) {
                            128 + signal
                        } else {
                            127
                        }
                    },

                    Err(e) => {
                        writeln!(&mut io::stderr(), "shroom: {}", e).unwrap();
                        127
                    },
                }
            }
        },
    }
}

fn main() {
    let mut line = String::new();
    loop {
        prompt(&mut line).unwrap();
        let ast = Parser::new(&line).parse();
        let exit_code = execute(&ast);
        if exit_code != 0 {
            println!("shroom: exit code: {}", exit_code);
        }
        line.clear();
    }
}
<commit_msg>Change error message format.<commit_after>use std::collections::HashMap;
use std::io::{self, Write};
use std::iter::Peekable;
use std::process::{Command, ExitStatus};
use std::str::CharIndices;

// TODO(tsion): Use the readline library.
fn prompt(line: &mut String) -> io::Result<usize> {
    let current_dir = try!(std::env::current_dir());
    print!("{}> ", current_dir.display());
    try!(io::stdout().flush());
    io::stdin().read_line(line)
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Ast {
    Empty,
    Call { command: String, args: Vec<String> }
}

#[derive(Clone, Debug, Eq, PartialEq)]
enum Token {
    Newline,
    Whitespace,
    Text(String),
}

#[derive(Clone)]
struct Lexer<'a> {
    input: &'a str,
    iter: Peekable<CharIndices<'a>>,
}

impl<'a> Lexer<'a> {
    fn new(input: &str) -> Lexer {
        Lexer {
            input: input,
            iter: input.char_indices().peekable(),
        }
    }

    fn pos(&mut self) -> usize {
        self.iter.peek().map(|p| p.0).unwrap_or(self.input.len())
    }

    fn peek_char(&mut self) -> Option<char> {
        self.iter.peek().map(|p| p.1)
    }

    fn is_whitespace(c: char) -> bool {
        c == ' ' || c == '\t'
    }

    fn lex_whitespace(&mut self) -> Token {
        while let Some(c) = self.peek_char() {
            if !Lexer::is_whitespace(c) { break; }
            self.iter.next();
        }

        Token::Whitespace
    }

    fn lex_unquoted_text(&mut self) -> Token {
        let start = self.pos();

        while let Some(c) = self.peek_char() {
            if Lexer::is_whitespace(c) || c == '\r' || c == '\n' { break; }
            self.iter.next();
        }

        let end = self.pos();

        // TODO(tsion): Do this without allocation.
        Token::Text(String::from(&self.input[start..end]))
    }
}

impl<'a> Iterator for Lexer<'a> {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        self.peek_char().map(|peek_char| {
            match peek_char {
                '\r' | '\n'                  => { self.iter.next(); Token::Newline },
                c if Lexer::is_whitespace(c) => self.lex_whitespace(),
                _                            => self.lex_unquoted_text(),
            }
        })
    }
}

#[derive(Clone)]
struct Parser<'a> {
    lexer: Lexer<'a>,
}

impl<'a> Parser<'a> {
    fn new(input: &str) -> Parser {
        Parser { lexer: Lexer::new(input) }
    }

    fn parse(&mut self) -> Ast {
        match self.lexer.next() {
            Some(Token::Whitespace) | Some(Token::Newline) => self.parse(),
            Some(Token::Text(command)) => self.parse_call(command),
            None => Ast::Empty,
        }
    }

    fn parse_call(&mut self, command: String) -> Ast {
        let mut args = vec![];

        for token in &mut self.lexer {
            match token {
                Token::Newline    => break,
                Token::Whitespace => {},
                Token::Text(arg)  => { args.push(arg); },
            }
        }

        Ast::Call { command: command, args: args }
    }
}

struct Builtin {
    name: &'static str,
    min_args: usize,
    max_args: usize,
    func: fn(&[String]) -> i32,
}

fn result_to_exit_code(cmd: &'static str, result: io::Result<()>) -> i32 {
    match result {
        Ok(()) => 0,
        Err(e) => {
            writeln!(&mut io::stderr(), "shroom: {}: {}", cmd, e).unwrap();
            1
        },
    }
}

fn builtin_cd(args: &[String]) -> i32 {
    if let Some(path) = args.get(0) {
        result_to_exit_code("cd", std::env::set_current_dir(path))
    } else if let Some(home) = std::env::home_dir() {
        result_to_exit_code("cd", std::env::set_current_dir(home))
    } else {
        writeln!(&mut io::stderr(), "shroom: cd: couldn't find home dir").unwrap();
        1
    }
}

fn builtin_exit(args: &[String]) -> i32 {
    if let Some(exit_code_str) = args.get(0) {
        match exit_code_str.parse() {
            Ok(exit_code) => std::process::exit(exit_code),
            Err(e) => {
                writeln!(&mut io::stderr(), "shroom: exit: can't parse exit code: {}", e).unwrap();
                1
            },
        }
    } else {
        std::process::exit(0);
    }
}

fn execute(ast: &Ast) -> i32 {
    let mut builtins = HashMap::new();

    builtins.insert("cd", Builtin {
        name: "cd",
        min_args: 0,
        max_args: 1,
        func: builtin_cd,
    });

    builtins.insert("exit", Builtin {
        name: "exit",
        min_args: 0,
        max_args: 1,
        func: builtin_exit,
    });

    match *ast {
        Ast::Empty => 0,

        Ast::Call { ref command, ref args } => {
            if let Some(builtin) = builtins.get(&command[..]) {
                if args.len() < builtin.min_args {
                    writeln!(&mut io::stderr(), "shroom: {}: not enough arguments",
                             builtin.name).unwrap();
                    1
                } else if args.len() > builtin.max_args {
                    writeln!(&mut io::stderr(), "shroom: {}: too many arguments",
                             builtin.name).unwrap();
                    1
                } else {
                    (builtin.func)(args)
                }
            } else {
                match Command::new(command).args(args).status() {
                    Ok(exit_status) => {
                        #[cfg(unix)]
                        fn exit_signal(exit_status: &ExitStatus) -> Option<i32> {
                            use std::os::unix::process::ExitStatusExt;
                            exit_status.signal()
                        }

                        #[cfg(not(unix))]
                        fn exit_signal(_exit_status: &ExitStatus) -> Option<i32> {
                            None
                        }

                        if let Some(code) = exit_status.code() {
                            code
                        } else if let Some(signal) = exit_signal(&exit_status) {
                            128 + signal
                        } else {
                            127
                        }
                    },

                    Err(e) => {
                        writeln!(&mut io::stderr(), "shroom: {}: {}", command, e).unwrap();
                        127
                    },
                }
            }
        },
    }
}

fn main() {
    let mut line = String::new();
    loop {
        prompt(&mut line).unwrap();
        let ast = Parser::new(&line).parse();
        let exit_code = execute(&ast);
        if exit_code != 0 {
            println!("shroom: exit code: {}", exit_code);
        }
        line.clear();
    }
}
<|endoftext|>


<commit_before>extern crate regex;

use std::env;
use std::fs;
use std::io;
use std::io::Write;
use std::path::Path;
use regex::Regex;

fn main() {
    let pattern = env::args().nth(1).unwrap();

    let pattern = match Regex::new(&pattern) {
        Ok(regex) => regex,
        Err(error) => {
            writeln!(io::stderr(), "Invalid pattern: {}", error).unwrap();
            return;
        }
    };

    let replacement = env::args().nth(2).unwrap();

    for arg in env::args().skip(3) {
        if !pattern.is_match(&arg) {
            println!("Skipping `{}`", arg);
            continue;
        }

        if !Path::new(&arg).exists() {
            writeln!(io::stderr(), "Source path `{}` doesn't exist", arg).unwrap();
            return;
        }

        let new_name = pattern.replace(&arg, &*replacement);

        if Path::new(&new_name).exists() {
            writeln!(io::stderr(), "Failed to rename `{}`: destination path `{}` already exists", arg, new_name).unwrap();
            return;
        }

        match fs::rename(&arg, &new_name) {
            Ok(_) => println!("Renamed `{}` -> `{}`", arg, new_name),
            Err(error) => {
                writeln!(io::stderr(), "Failed to rename `{}` -> `{}`: {}", arg, new_name, error).unwrap();
                return;
            }
        };
    }
}
<commit_msg>Extract path processing into a separate function<commit_after>extern crate regex;

use std::env;
use std::fs;
use std::io;
use std::io::Write;
use std::path::Path;
use regex::Regex;

fn rename_path(path: &str, pattern: &Regex, replacement: &str) {
    if !pattern.is_match(path) {
        println!("Skipping `{}`", path);
        return;
    }

    if !Path::new(path).exists() {
        writeln!(io::stderr(), "Source path `{}` doesn't exist", path).unwrap();
        return;
    }

    let new_path = pattern.replace(path, replacement);

    if Path::new(&new_path).exists() {
        writeln!(io::stderr(), "Failed to rename `{}`: destination path `{}` already exists", path, new_path).unwrap();
        return;
    }

    match fs::rename(path, &new_path) {
        Ok(_) => println!("Renamed `{}` -> `{}`", path, new_path),
        Err(error) => {
            writeln!(io::stderr(), "Failed to rename `{}` -> `{}`: {}", path, new_path, error).unwrap();
            return;
        }
    };
}

fn main() {
    let pattern = env::args().nth(1).unwrap();

    let pattern = match Regex::new(&pattern) {
        Ok(regex) => regex,
        Err(error) => {
            writeln!(io::stderr(), "Invalid pattern: {}", error).unwrap();
            return;
        }
    };

    let replacement = env::args().nth(2).unwrap();

    for path in env::args().skip(3) {
        rename_path(&path, &pattern, &replacement);
    }
}
<|endoftext|>


<commit_before>//! Utility for controlling RGB header on MSI boards
//!
//! The RGB header is controlled by the NCT6795D Super I/O chip. It seems like the "bank" is
//! enabled by writing `87 07` to the PORT port (0x4e) and then `12` to the DATA port (0x4f).
//!
//! This bank then looks like this:
//!
//! 00 |  ...
//! 10 |  ...
//! .  |
//! .  |
//! .  |
//! E0 | XX XX XX XX  PX XX XX XX  XX XX XX XX  XX XX XX XX
//! F0 | RR RR RR RR  GG GG GG GG  BB BB BB BB  XX XX TT TX
//!     --------------------------------------------------
//!      00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F
//!
//! Here:
//!
//! `R` - intensity of the red colour
//! `G` - intensity of the green colour
//! `B` - intensity of the blue colour
//!
//! There’s 8 distinct steps that can be specified, hence the four instances of `RR`, `GG` and
//! `BB`. These colours change every given interval specified in the `TTT` bytes. TTT has the bit
//! format like this: `bgrdt tttt tttt`
//!
//! Here `t` bits are a duration between changes from one colour to another (takes the next column
//! of RR GG BB);
//!
//! `d` bit specifies whether the RGB header is turned on (distinct from the motherboard lights).;
//!
//! `bgr` invert the intensity (`F` is 0%, `0` is 100%) for blue, green and red channels
//! respectively.
//!
//! `P` here is another bitmask of the form `pbbb`, where `p` specifies whether smooth pulsing
//! behaviour is enabled. `bbb` specifies duration between blinks. If `bbb` is `001`,
//! all lightning is turned off, including the one on the motherboard itself. `000` is always on.

extern crate clap;
#[macro_use]
extern crate error_chain;

use std::io::{self, Seek, Write};
use std::fs;
use clap::{Arg, App, ArgMatches};

error_chain! {
    foreign_links {
        Io(::std::io::Error);
        Parse(::std::num::ParseIntError);
    }
}

const PORT1: u8 = 0x4e;
const PORT2: u8 = 0x4f;

const REDCELL: u8 = 0xf0;
const GREENCELL: u8 = 0xf4;
const BLUECELL: u8 = 0xf8;

fn outb(f: &mut fs::File, cell: u8, data: u8) -> io::Result<()> {
    f.seek(io::SeekFrom::Start(cell as _))?;
    f.write(&[data])?;
    Ok(())
}

fn write_byte_to_cell(f: &mut fs::File, cell: u8, data: u8) -> io::Result<()> {
    outb(f, PORT1, 0x87)?;
    outb(f, PORT1, 0x87)?;
    outb(f, PORT1, 0x07)?;
    outb(f, PORT2, 0x12)?;
    outb(f, PORT1, cell)?;
    outb(f, PORT2, data)
}

fn write_colour(f: &mut fs::File, cell_offset: u8, data: u32) -> io::Result<()> {
    write_byte_to_cell(f, cell_offset, (data >> 24) as u8)?;
    write_byte_to_cell(f, cell_offset + 1, (data >> 16) as u8)?;
    write_byte_to_cell(f, cell_offset + 2, (data >> 8) as u8)?;
    write_byte_to_cell(f, cell_offset + 3, data as u8)
}

fn run<'a>(matches: ArgMatches<'a>) -> Result<()> {
    let mut f = fs::OpenOptions::new().read(true).write(true).open("/dev/port")
        .chain_err(|| { "could not open /dev/port; try sudo?" })?;
    let disable = matches.is_present("DISABLE");
    let pulse = matches.is_present("PULSE");
    let flash = matches.value_of("BLINK").expect("bug: BLINK argument").parse::<u8>()?;
    let red = u32::from_str_radix(matches.value_of("RED").expect("bug: RED argument"), 16)?;
    let green = u32::from_str_radix(matches.value_of("GREEN").expect("bug: GREEN argument"), 16)?;
    let blue = u32::from_str_radix(matches.value_of("BLUE").expect("bug: BLUE argument"), 16)?;
    let step_duration = matches.value_of("STEPDURATION").expect("bug: STEPDURATION argument")
                               .parse::<u16>()?;
    let invs = matches.values_of("INVHALF").map(|i| i.collect()).unwrap_or(Vec::new());

    let e4_val = if disable { 1 } else { 0 } |
                 if pulse { 0b1000 } else { 0 } |
                 if flash == 0 { 0 } else { (flash + 1) & 0b111 };
    write_byte_to_cell(&mut f, 0xe4, e4_val)?;
    write_colour(&mut f, REDCELL, red)?;
    write_colour(&mut f, GREENCELL, green)?;
    write_colour(&mut f, BLUECELL, blue)?;

    write_byte_to_cell(&mut f, 0xfe, step_duration as u8)?;
    let ff_val = (step_duration >> 8) as u8 & 1 |
                 0b10 | // if 0 disable lights on rgb header only, not on board
                 if invs.contains(&"b") { 0b10000 } else { 0 } |
                 if invs.contains(&"g") { 0b01000 } else { 0 } |
                 if invs.contains(&"r") { 0b00100 } else { 0 };
    write_byte_to_cell(&mut f, 0xff, ff_val)?;
    Ok(())
}

fn main() {
    let matches = App::new("msi-rgb")
        .version(option_env!("CARGO_PKG_VERSION").unwrap_or("0.0.0"))
        .about(option_env!("CARGO_PKG_DESCRIPTION").unwrap_or(""))
        .setting(clap::AppSettings::ArgRequiredElseHelp)
        .arg(Arg::with_name("RED").required(true)
             .help("values of red colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("GREEN").required(true)
             .help("values of green colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("BLUE").required(true)
             .help("values of blue colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("INVHALF").long("invert").short("i").multiple(true)
             .takes_value(true).possible_values(&["r","g","b"])
             .help("invert the specified channel(s) and halve their bit depth (=8 distinct steps)"))
        .arg(Arg::with_name("PULSE").long("pulse").short("p")
             .help("smooth pulsing"))
        .arg(Arg::with_name("STEPDURATION").long("duration").short("d").takes_value(true)
             .default_value("25").validator(|s| { match s.parse::<u16>() {
                 Err(e) => Err(format!("{}", e)),
                 Ok(s) => if s > 511 { Err("duration must not exceed 511".into()) } else { Ok(()) }
             }})
             .help("duration between distinct steps of colours (0 - fastest, 511 - slowest"))
        .arg(Arg::with_name("BLINK").long("blink").short("b").takes_value(true).default_value("0")
             .possible_values(&["0", "1", "2", "3", "4", "5", "6"])
             .help("duration between blinks (from 0 to 6, 0 is always on, 6 is slowest)"))
        .arg(Arg::with_name("DISABLE").long("disable").short("x")
             .help("disable the RGB subsystem altogether"))
        .get_matches();

    ::std::process::exit(if let Err(e) = run(matches) {
        let _ = writeln!(::std::io::stderr(), " {}", e);
        for e in e.iter().skip(1) {
            let _ = writeln!(::std::io::stderr(), "    caused by: {}", e);
        }
        1
    } else {
        0
    });
}
<commit_msg>Update the description of the invert flag<commit_after>//! Utility for controlling RGB header on MSI boards
//!
//! The RGB header is controlled by the NCT6795D Super I/O chip. It seems like the "bank" is
//! enabled by writing `87 07` to the PORT port (0x4e) and then `12` to the DATA port (0x4f).
//!
//! This bank then looks like this:
//!
//! 00 |  ...
//! 10 |  ...
//! .  |
//! .  |
//! .  |
//! E0 | XX XX XX XX  PX XX XX XX  XX XX XX XX  XX XX XX XX
//! F0 | RR RR RR RR  GG GG GG GG  BB BB BB BB  XX XX TT TX
//!     --------------------------------------------------
//!      00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F
//!
//! Here:
//!
//! `R` - intensity of the red colour
//! `G` - intensity of the green colour
//! `B` - intensity of the blue colour
//!
//! There’s 8 distinct steps that can be specified, hence the four instances of `RR`, `GG` and
//! `BB`. These colours change every given interval specified in the `TTT` bytes. TTT has the bit
//! format like this: `bgrdt tttt tttt`
//!
//! Here `t` bits are a duration between changes from one colour to another (takes the next column
//! of RR GG BB);
//!
//! `d` bit specifies whether the RGB header is turned on (distinct from the motherboard lights).;
//!
//! `bgr` invert the intensity (`F` is 0%, `0` is 100%) for blue, green and red channels
//! respectively.
//!
//! `P` here is another bitmask of the form `pbbb`, where `p` specifies whether smooth pulsing
//! behaviour is enabled. `bbb` specifies duration between blinks. If `bbb` is `001`,
//! all lightning is turned off, including the one on the motherboard itself. `000` is always on.

extern crate clap;
#[macro_use]
extern crate error_chain;

use std::io::{self, Seek, Write};
use std::fs;
use clap::{Arg, App, ArgMatches};

error_chain! {
    foreign_links {
        Io(::std::io::Error);
        Parse(::std::num::ParseIntError);
    }
}

const PORT1: u8 = 0x4e;
const PORT2: u8 = 0x4f;

const REDCELL: u8 = 0xf0;
const GREENCELL: u8 = 0xf4;
const BLUECELL: u8 = 0xf8;

fn outb(f: &mut fs::File, cell: u8, data: u8) -> io::Result<()> {
    f.seek(io::SeekFrom::Start(cell as _))?;
    f.write(&[data])?;
    Ok(())
}

fn write_byte_to_cell(f: &mut fs::File, cell: u8, data: u8) -> io::Result<()> {
    outb(f, PORT1, 0x87)?;
    outb(f, PORT1, 0x87)?;
    outb(f, PORT1, 0x07)?;
    outb(f, PORT2, 0x12)?;
    outb(f, PORT1, cell)?;
    outb(f, PORT2, data)
}

fn write_colour(f: &mut fs::File, cell_offset: u8, data: u32) -> io::Result<()> {
    write_byte_to_cell(f, cell_offset, (data >> 24) as u8)?;
    write_byte_to_cell(f, cell_offset + 1, (data >> 16) as u8)?;
    write_byte_to_cell(f, cell_offset + 2, (data >> 8) as u8)?;
    write_byte_to_cell(f, cell_offset + 3, data as u8)
}

fn run<'a>(matches: ArgMatches<'a>) -> Result<()> {
    let mut f = fs::OpenOptions::new().read(true).write(true).open("/dev/port")
        .chain_err(|| { "could not open /dev/port; try sudo?" })?;
    let disable = matches.is_present("DISABLE");
    let pulse = matches.is_present("PULSE");
    let flash = matches.value_of("BLINK").expect("bug: BLINK argument").parse::<u8>()?;
    let red = u32::from_str_radix(matches.value_of("RED").expect("bug: RED argument"), 16)?;
    let green = u32::from_str_radix(matches.value_of("GREEN").expect("bug: GREEN argument"), 16)?;
    let blue = u32::from_str_radix(matches.value_of("BLUE").expect("bug: BLUE argument"), 16)?;
    let step_duration = matches.value_of("STEPDURATION").expect("bug: STEPDURATION argument")
                               .parse::<u16>()?;
    let invs = matches.values_of("INVHALF").map(|i| i.collect()).unwrap_or(Vec::new());

    let e4_val = if disable { 1 } else { 0 } |
                 if pulse { 0b1000 } else { 0 } |
                 if flash == 0 { 0 } else { (flash + 1) & 0b111 };
    write_byte_to_cell(&mut f, 0xe4, e4_val)?;
    write_colour(&mut f, REDCELL, red)?;
    write_colour(&mut f, GREENCELL, green)?;
    write_colour(&mut f, BLUECELL, blue)?;

    write_byte_to_cell(&mut f, 0xfe, step_duration as u8)?;
    let ff_val = (step_duration >> 8) as u8 & 1 |
                 0b10 | // if 0 disable lights on rgb header only, not on board
                 if invs.contains(&"b") { 0b10000 } else { 0 } |
                 if invs.contains(&"g") { 0b01000 } else { 0 } |
                 if invs.contains(&"r") { 0b00100 } else { 0 };
    write_byte_to_cell(&mut f, 0xff, ff_val)?;
    Ok(())
}

fn main() {
    let matches = App::new("msi-rgb")
        .version(option_env!("CARGO_PKG_VERSION").unwrap_or("0.0.0"))
        .about(option_env!("CARGO_PKG_DESCRIPTION").unwrap_or(""))
        .setting(clap::AppSettings::ArgRequiredElseHelp)
        .arg(Arg::with_name("RED").required(true)
             .help("values of red colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("GREEN").required(true)
             .help("values of green colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("BLUE").required(true)
             .help("values of blue colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("INVHALF").long("invert").short("i").multiple(true)
             .takes_value(true).possible_values(&["r","g","b"])
             .help("invert the specified channel(s)"))
        .arg(Arg::with_name("PULSE").long("pulse").short("p")
             .help("smooth pulsing"))
        .arg(Arg::with_name("STEPDURATION").long("duration").short("d").takes_value(true)
             .default_value("25").validator(|s| { match s.parse::<u16>() {
                 Err(e) => Err(format!("{}", e)),
                 Ok(s) => if s > 511 { Err("duration must not exceed 511".into()) } else { Ok(()) }
             }})
             .help("duration between distinct steps of colours (0 - fastest, 511 - slowest"))
        .arg(Arg::with_name("BLINK").long("blink").short("b").takes_value(true).default_value("0")
             .possible_values(&["0", "1", "2", "3", "4", "5", "6"])
             .help("duration between blinks (from 0 to 6, 0 is always on, 6 is slowest)"))
        .arg(Arg::with_name("DISABLE").long("disable").short("x")
             .help("disable the RGB subsystem altogether"))
        .get_matches();

    ::std::process::exit(if let Err(e) = run(matches) {
        let _ = writeln!(::std::io::stderr(), " {}", e);
        for e in e.iter().skip(1) {
            let _ = writeln!(::std::io::stderr(), "    caused by: {}", e);
        }
        1
    } else {
        0
    });
}
<|endoftext|>


<commit_before>use std::env;
use std::fs;
use std::io::Read;
use std::path::Path;

fn main() {
    let pif_file_name = env::args().nth(1).unwrap();
    let rom_file_name = env::args().nth(2).unwrap();

    let pif = read_bin(pif_file_name);
    let rom = read_bin(rom_file_name);
}

fn read_bin<P: AsRef<Path>>(path: P) -> Vec<u8> {
    let mut file = fs::File::open(path).unwrap();
    let mut file_buf = Vec::new();
    file.read_to_end(&mut file_buf).unwrap();
    file_buf
}
<commit_msg>Started modelling the CPU<commit_after>use std::env;
use std::fs;
use std::io::Read;
use std::path::Path;

const NUM_GPR: usize = 32;

struct Cpu {
    reg_gpr: [u64; NUM_GPR],
    reg_fpr: [f64; NUM_GPR],

    reg_pc: u64,

    reg_hi: u64,
    reg_lo: u64,

    reg_llbit: bool, // TODO: Enum type

    reg_fcr0: u32,
    reg_fcr31: u32,

    cp0: Cp0
}

impl Cpu {
    fn new() -> Cpu {
        Cpu {
            reg_gpr: [0; NUM_GPR],
            reg_fpr: [0; NUM_GPR],

            reg_pc: 0,

            reg_hi: 0,
            reg_lo: 0,

            reg_llbit: false,

            reg_fcr0: 0,
            reg_fcr31: 0,

            cp0: Cp0::new()
        }
    }

    fn power_on_reset(&mut self) {
        self.cp0.power_on_reset();
    }
}

struct Cp0 {
    reg_index: u64,
    reg_random: u64,
    reg_entry_lo0: u64,
    reg_entry_lo1: u64,
    reg_context: u64,
    reg_page_mask: u64,
    reg_wired: u64,
    reg_bad_v_addr: u64,
    reg_count: u64,
    reg_entry_hi: u64,
    reg_compare: u64,
    reg_status: u64,
    reg_cause: u64,
    reg_epc: u64,
    reg_pr_id: u64,
    reg_config: u64,
    reg_ll_addr: u64,
    reg_watch_lo: u64,
    reg_watch_hi: u64,
    reg_x_context: u64,
    reg_tag_lo: u64,
    reg_tag_hi: u64,
    reg_error_epc: u64
}

impl Cp0 {
    fn new() -> Cp0 {
        Cp0 {
            reg_index: 0,
            reg_random: 0,
            reg_entry_lo0: 0,
            reg_entry_lo1: 0,
            reg_context: 0,
            reg_page_mask: 0,
            reg_wired: 0,
            reg_bad_v_addr: 0,
            reg_count: 0,
            reg_entry_hi: 0,
            reg_compare: 0,
            reg_status: 0,
            reg_cause: 0,
            reg_epc: 0,
            reg_pr_id: 0,
            reg_config: 0,
            reg_ll_addr: 0,
            reg_watch_lo: 0,
            reg_watch_hi: 0,
            reg_x_context: 0,
            reg_tag_lo: 0,
            reg_tag_hi: 0,
            reg_error_epc: 0
        }
    }

    fn power_on_reset(&mut self) {

    }
}

fn main() {
    let pif_file_name = env::args().nth(1).unwrap();
    let rom_file_name = env::args().nth(2).unwrap();

    let pif = read_bin(pif_file_name);
    let rom = read_bin(rom_file_name);

    let mut cpu = Cpu::new();
}

fn read_bin<P: AsRef<Path>>(path: P) -> Vec<u8> {
    let mut file = fs::File::open(path).unwrap();
    let mut file_buf = Vec::new();
    file.read_to_end(&mut file_buf).unwrap();
    file_buf
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Read;

mod constants;
mod memory;
mod cpu;
mod ppu;

use cpu::Cpu6502;
use memory::*;

const PC_START: u16 = 0x400;
const DUMP_FILE: &'static str = "/Users/brian/Desktop/6502dump.bin";

fn main() {
    let mut f = File::open("test_roms/6502_functional_test.bin").unwrap();

    let mut rom = Vec::<u8>::new();
    let bytes_read = f.read_to_end(&mut rom).unwrap();
    if bytes_read != 65536 {
        panic!("expected 16kb of data");
    }

    let mut mem = SimpleMemory::new();
    mem.store_many(0, &rom);
    let mut memory: Box<Memory> = Box::new(mem);
    {
        let mut cpu = Cpu6502::new(&mut *memory);
        cpu.registers.pc = PC_START;
        let mut last_pc: u16 = PC_START;

        loop {
            match cpu.step() {
                Ok(instr) => {
                    if cpu.registers.pc == 0x3399 {
                        println!("******* SUCCESS ********");
                        return;
                    }

                    if last_pc == cpu.registers.pc {
                        println!("{} {} cyc: {}",
                                 instr.to_string(),
                                 cpu.registers.to_string(),
                                 cpu.cycles);
                        println!("Detected Trap");
                        break;
                    }

                    last_pc = cpu.registers.pc;

                    if cpu.cycles % 1000000 == 0 {
                        println!("{} cycles", cpu.cycles);
                    }
                }
                Err(msg) => {
                    println!("{}", msg);
                    break;
                }
            }
        }
    }

    // If we get here, we detected a trap.
    memory.dump(DUMP_FILE);
}
<commit_msg>Get rid of dead code warnings (for now)<commit_after>#![allow(dead_code)]

use std::fs::File;
use std::io::Read;

mod constants;
mod memory;
mod cpu;
mod ppu;

use cpu::Cpu6502;
use memory::*;

const PC_START: u16 = 0x400;
const DUMP_FILE: &'static str = "/Users/brian/Desktop/6502dump.bin";

fn main() {
    let mut f = File::open("test_roms/6502_functional_test.bin").unwrap();

    let mut rom = Vec::<u8>::new();
    let bytes_read = f.read_to_end(&mut rom).unwrap();
    if bytes_read != 65536 {
        panic!("expected 16kb of data");
    }

    let mut mem = SimpleMemory::new();
    mem.store_many(0, &rom);
    let mut memory: Box<Memory> = Box::new(mem);
    {
        let mut cpu = Cpu6502::new(&mut *memory);
        cpu.registers.pc = PC_START;
        let mut last_pc: u16 = PC_START;

        loop {
            match cpu.step() {
                Ok(instr) => {
                    if cpu.registers.pc == 0x3399 {
                        println!("******* SUCCESS ********");
                        return;
                    }

                    if last_pc == cpu.registers.pc {
                        println!("{} {} cyc: {}",
                                 instr.to_string(),
                                 cpu.registers.to_string(),
                                 cpu.cycles);
                        println!("Detected Trap");
                        break;
                    }

                    last_pc = cpu.registers.pc;

                    if cpu.cycles % 1000000 == 0 {
                        println!("{} cycles", cpu.cycles);
                    }
                }
                Err(msg) => {
                    println!("{}", msg);
                    break;
                }
            }
        }
    }

    // If we get here, we detected a trap.
    memory.dump(DUMP_FILE);
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Nikita Pekin and the smexybot contributors
// See the README.md file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(missing_docs)]
#![deny(non_camel_case_types)]
#![cfg_attr(feature = "nightly", feature(proc_macro))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![warn(missing_copy_implementations,
        missing_debug_implementations,
        missing_docs,
        trivial_numeric_casts,
        unsafe_code,
        unused_extern_crates,
        unused_import_braces,
        unused_qualifications)]
#![cfg_attr(feature="clippy", warn(cast_possible_truncation))]
#![cfg_attr(feature="clippy", warn(cast_possible_wrap))]
#![cfg_attr(feature="clippy", warn(cast_precision_loss))]
#![cfg_attr(feature="clippy", warn(cast_sign_loss))]
#![cfg_attr(feature="clippy", warn(mut_mut))]
// This allows us to use `unwrap` on `Option` values when compiling in test mode
// (because using it in tests is idiomatic).
#![cfg_attr(all(not(test), feature="clippy"), warn(result_unwrap_used))]
#![cfg_attr(feature="clippy", warn(wrong_pub_self_convention))]

//! Smexybot is a general-purpose [Discord](https://discordapp.com/) bot written
//! in [Rust](https://www.rust-lang.org/). It is built upon the
//! [serenity.rs](https://github.com/zeyla/serenity.rs) Discord API.

extern crate chrono;
extern crate env_logger;
extern crate hyper;
#[cfg(any(feature = "roll", feature = "wolfram", feature = "xkcd"))]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate rand;
extern crate serde;
#[cfg(feature = "nightly")]
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serenity;
extern crate url;

mod command;
mod config;
mod counter;
mod error;
mod util;

use chrono::{DateTime, UTC};

use config::Config;
use counter::CommandCounter;
use serenity::Client;
use serenity::client::LoginType;
use serenity::ext::framework::Framework;
use std::collections::HashMap;
use std::env;
use util::{check_msg, timestamp_to_string};

const RATE_LIMIT_MESSAGE: &'static str = "Try this again in %time% seconds.";

lazy_static! {
    static ref CONFIG: Config = Config::new(Some("config.json"));
    static ref UPTIME: DateTime<UTC> = UTC::now();
}

fn main() {
    // Initialize the `env_logger` to provide logging output.
    env_logger::init().expect("Failed to initialize env_logger");

    // Initialize the `UPTIME` variable.
    debug!("Initialized at: {}", timestamp_to_string(&*UPTIME));

    // Create a client for a user.
    let (_, mut client) = login();

    {
        let mut data = client.data.lock().expect("Failed to lock client data");
        data.insert::<CommandCounter>(HashMap::default());
    }

    client.on_ready(|_context, ready| {
        let shard_info = if let Some(s) = ready.shard {
            Some(format!("shard {}/{} ", s[0] + 1, s[1]))
        } else {
            None
        };
        println!(
            "Started {}as {}#{}, serving {} guilds",
            shard_info.unwrap_or_else(|| "".to_owned()),
            ready.user.name,
            ready.user.discriminator,
            ready.guilds.len(),
        );
    });

    client.with_framework(build_framework);

    if let Err(err) = client.start_autosharded() {
        error!("Client error: {:?}", err);
    }
}

// Configures the `Framework` used by serenity, and registers the handlers for
// any enabled commands.
fn build_framework(framework: Framework) -> Framework {
    let mut framework = framework.configure(|c| {
            c.rate_limit_message(RATE_LIMIT_MESSAGE)
                .prefix(&CONFIG.command_prefix)
        })
        .before(|context, message, command_name| {
            info!(
            "Got command '{}' from user '{}'",
            command_name,
            message.author.name,
        );

            // Increment the number of times this command has been run. If the
            // command's name does not exist in the counter, add a default value of
            // 0.
            let mut data = context.data.lock().expect("Failed to lock context data");
            let counter = data.get_mut::<CommandCounter>().unwrap();
            let entry = counter.entry(command_name.clone()).or_insert(0);
            *entry += 1;

            true
        })
        .after(|context, _message, command_name, error| {
            if let Err(err) = error {
                check_msg(context.say(&err));
            } else {
                debug!("Processed command '{}'", command_name);
            }
        });

    #[cfg(feature = "fuyu")]
    {
        framework = framework.on("fuyu", command::fuyu::handler);
    }
    #[cfg(feature = "help")]
    {
        use serenity::ext::framework::help_commands;
        framework = framework.command("help", |c| c.exec_help(help_commands::plain));
    }
    #[cfg(feature = "ping")]
    {
        framework = framework.on("ping", command::ping::handler);
    }
    #[cfg(feature = "roll")]
    {
        framework = framework.on("roll", command::roll::handler);
    }
    #[cfg(feature = "stats")]
    {
        framework = framework.on("stats", command::stats::handler);
    }
    #[cfg(feature = "tag")]
    {
        framework = framework.on("tag", command::tag::handler);
    }
    #[cfg(feature = "wolfram")]
    {
        framework = framework.on("wolfram", command::wolfram_alpha::handler);
    }
    #[cfg(feature = "xkcd")]
    {
        framework = framework.on("xkcd", command::xkcd::handler);
    }

    framework
}

// Creates a `Client`.
fn login() -> (LoginType, Client) {
    debug!("Attempting to login");

    if let Ok(bot_token) = env::var("DISCORD_BOT_TOKEN") {
        debug!("Performing bot token login");
        return (LoginType::Bot, Client::login_bot(&bot_token));
    }
    debug!("Skipping bot token login");

    if let Ok(user_token) = env::var("DISCORD_USER_TOKEN") {
        debug!("Performing user token login");
        return (LoginType::User, Client::login_user(&user_token));
    }
    debug!("Skipping user token login");

    panic!("No suitable authentication method found");
}
<commit_msg>chore: update denied and warned lints<commit_after>// Copyright (c) 2016 Nikita Pekin and the smexybot contributors
// See the README.md file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(non_camel_case_types)]
#![cfg_attr(feature = "nightly", feature(proc_macro))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![warn(missing_copy_implementations,
        missing_debug_implementations,
        missing_docs,
        trivial_casts,
        trivial_numeric_casts,
        unused_extern_crates,
        unused_import_braces,
        unused_qualifications)]
#![deny(missing_docs, non_camel_case_types, unsafe_code)]
#![cfg_attr(feature="clippy", warn(cast_possible_truncation))]
#![cfg_attr(feature="clippy", warn(cast_possible_wrap))]
#![cfg_attr(feature="clippy", warn(cast_precision_loss))]
#![cfg_attr(feature="clippy", warn(cast_sign_loss))]
#![cfg_attr(feature="clippy", warn(mut_mut))]
// This allows us to use `unwrap` on `Option` values when compiling in test mode
// (because using it in tests is idiomatic).
#![cfg_attr(all(not(test), feature="clippy"), warn(result_unwrap_used))]
#![cfg_attr(feature="clippy", warn(wrong_pub_self_convention))]

//! Smexybot is a general-purpose [Discord](https://discordapp.com/) bot written
//! in [Rust](https://www.rust-lang.org/). It is built upon the
//! [serenity.rs](https://github.com/zeyla/serenity.rs) Discord API.

extern crate chrono;
extern crate env_logger;
extern crate hyper;
#[cfg(any(feature = "roll", feature = "wolfram", feature = "xkcd"))]
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate rand;
extern crate serde;
#[cfg(feature = "nightly")]
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate serenity;
extern crate url;

mod command;
mod config;
mod counter;
mod error;
mod util;

use chrono::{DateTime, UTC};

use config::Config;
use counter::CommandCounter;
use serenity::Client;
use serenity::client::LoginType;
use serenity::ext::framework::Framework;
use std::collections::HashMap;
use std::env;
use util::{check_msg, timestamp_to_string};

const RATE_LIMIT_MESSAGE: &'static str = "Try this again in %time% seconds.";

lazy_static! {
    static ref CONFIG: Config = Config::new(Some("config.json"));
    static ref UPTIME: DateTime<UTC> = UTC::now();
}

fn main() {
    // Initialize the `env_logger` to provide logging output.
    env_logger::init().expect("Failed to initialize env_logger");

    // Initialize the `UPTIME` variable.
    debug!("Initialized at: {}", timestamp_to_string(&*UPTIME));

    // Create a client for a user.
    let (_, mut client) = login();

    {
        let mut data = client.data.lock().expect("Failed to lock client data");
        data.insert::<CommandCounter>(HashMap::default());
    }

    client.on_ready(|_context, ready| {
        let shard_info = if let Some(s) = ready.shard {
            Some(format!("shard {}/{} ", s[0] + 1, s[1]))
        } else {
            None
        };
        println!(
            "Started {}as {}#{}, serving {} guilds",
            shard_info.unwrap_or_else(|| "".to_owned()),
            ready.user.name,
            ready.user.discriminator,
            ready.guilds.len(),
        );
    });

    client.with_framework(build_framework);

    if let Err(err) = client.start_autosharded() {
        error!("Client error: {:?}", err);
    }
}

// Configures the `Framework` used by serenity, and registers the handlers for
// any enabled commands.
fn build_framework(framework: Framework) -> Framework {
    let mut framework = framework.configure(|c| {
            c.rate_limit_message(RATE_LIMIT_MESSAGE)
                .prefix(&CONFIG.command_prefix)
        })
        .before(|context, message, command_name| {
            info!(
            "Got command '{}' from user '{}'",
            command_name,
            message.author.name,
        );

            // Increment the number of times this command has been run. If the
            // command's name does not exist in the counter, add a default value of
            // 0.
            let mut data = context.data.lock().expect("Failed to lock context data");
            let counter = data.get_mut::<CommandCounter>().unwrap();
            let entry = counter.entry(command_name.clone()).or_insert(0);
            *entry += 1;

            true
        })
        .after(|context, _message, command_name, error| {
            if let Err(err) = error {
                check_msg(context.say(&err));
            } else {
                debug!("Processed command '{}'", command_name);
            }
        });

    #[cfg(feature = "fuyu")]
    {
        framework = framework.on("fuyu", command::fuyu::handler);
    }
    #[cfg(feature = "help")]
    {
        use serenity::ext::framework::help_commands;
        framework = framework.command("help", |c| c.exec_help(help_commands::plain));
    }
    #[cfg(feature = "ping")]
    {
        framework = framework.on("ping", command::ping::handler);
    }
    #[cfg(feature = "roll")]
    {
        framework = framework.on("roll", command::roll::handler);
    }
    #[cfg(feature = "stats")]
    {
        framework = framework.on("stats", command::stats::handler);
    }
    #[cfg(feature = "tag")]
    {
        framework = framework.on("tag", command::tag::handler);
    }
    #[cfg(feature = "wolfram")]
    {
        framework = framework.on("wolfram", command::wolfram_alpha::handler);
    }
    #[cfg(feature = "xkcd")]
    {
        framework = framework.on("xkcd", command::xkcd::handler);
    }

    framework
}

// Creates a `Client`.
fn login() -> (LoginType, Client) {
    debug!("Attempting to login");

    if let Ok(bot_token) = env::var("DISCORD_BOT_TOKEN") {
        debug!("Performing bot token login");
        return (LoginType::Bot, Client::login_bot(&bot_token));
    }
    debug!("Skipping bot token login");

    if let Ok(user_token) = env::var("DISCORD_USER_TOKEN") {
        debug!("Performing user token login");
        return (LoginType::User, Client::login_user(&user_token));
    }
    debug!("Skipping user token login");

    panic!("No suitable authentication method found");
}
<|endoftext|>


<commit_before>#![feature(path_ext)]
#![feature(convert)]
extern crate mysql;
extern crate toml;
#[macro_use]
extern crate lazy_static;

use mysql::conn::MyOpts;
use std::default::Default;
use mysql::conn::pool;
use mysql::value::from_value;

use toml::Table;
use toml::Value;

use std::collections::HashMap;

mod lib {
	pub mod config;
}

static VERSION : &'static str = "0.1"; // String not valid

lazy_static! {
	static ref CONFIG: Table = {
		println!("Starting yayd-backend v{}",&VERSION);
		lib::config::init_config() //return
	};

}

fn main() {
	let opts = mysql_options();
}

//Set options for the connection
fn mysql_options() -> MyOpts {
	let dbconfig = CONFIG.get("db").unwrap().clone();
	let dbconfig = dbconfig.as_table().unwrap(); // shadow binding to workaround borrow / lifetime problems

    MyOpts {
    	//tcp_addr: Some(dbconfig.get("ip").unwrap().as_str().clone()),
    	tcp_addr: get_option_string(dbconfig,"ip"),
    	tcp_port: 3306,
    	//tcp_port: "3306"
    	user: get_option_string(dbconfig,"user"),
    	pass: get_option_string(dbconfig, "password"),
    	db_name: get_option_string(dbconfig, "db"),
    	..Default::default() // set other to default
    }
}

fn get_option_string(table: & Table,key: & str) -> Option<String> {
	let val: Value = table.get(key).unwrap().clone();
	if let toml::Value::String(s) = val {
		println!("Value: {:?}", s);
		Some(s)
	} else { unreachable!() }
	//Some(table.get(key).unwrap().as_str().unwrap())
}<commit_msg>*port now included in the config loading<commit_after>#![feature(path_ext)]
#![feature(convert)]
extern crate mysql;
extern crate toml;
#[macro_use]
extern crate lazy_static;

use mysql::conn::MyOpts;
use std::default::Default;
use mysql::conn::pool;
use mysql::value::from_value;

use toml::Table;
use toml::Value;

use std::collections::HashMap;

mod lib {
	pub mod config;
}

static VERSION : &'static str = "0.1"; // String not valid

lazy_static! {
	static ref CONFIG: Table = {
		println!("Starting yayd-backend v{}",&VERSION);
		lib::config::init_config() //return
	};

}

fn main() {
	let opts = mysql_options();

}

//Set options for the connection
fn mysql_options() -> MyOpts {
	let dbconfig = CONFIG.get("db").unwrap().clone();
	let dbconfig = dbconfig.as_table().unwrap(); // shadow binding to workaround borrow / lifetime problems

    MyOpts {
    	//tcp_addr: Some(dbconfig.get("ip").unwrap().as_str().clone()),
    	tcp_addr: get_option_string(dbconfig,"ip"),
    	tcp_port: dbconfig.get("port").unwrap().as_integer().unwrap() as u16,
    	//TODO: value does support Encodable -> set as encodable..
    	user: get_option_string(dbconfig,"user"),
    	pass: get_option_string(dbconfig, "password"),
    	db_name: get_option_string(dbconfig, "db"),
    	..Default::default() // set other to default
    }
}

///Converts a toml::Value to a Option<String> for mysql::MyOpts
fn get_option_string(table: & Table,key: & str) -> Option<String> {
	let val: Value = table.get(key).unwrap().clone();
	if let toml::Value::String(s) = val {
		Some(s)
	} else { unreachable!() }
}

// fn get_option_int(table: & Table, key: & str) -> Option<int> {
// 	let val: Value = table.get(key).unwrap().clone();
// 	if let toml::Value::
// }<|endoftext|>


<commit_before>// Copyright 2016 rust-fuzz developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

extern crate toml;
extern crate clap;
extern crate term;
#[macro_use]
extern crate error_chain;

use clap::{App, Arg, SubCommand, ArgMatches, AppSettings};
use std::{env, fs, path, ffi, process};
use std::io::Write;
use std::io::Read;

use std::os::unix::ffi::OsStrExt;

#[macro_use]
mod templates;
mod utils;

error_chain! {
    foreign_links {
        Toml(toml::de::Error);
        Io(::std::io::Error);
    }
}

fn main() {
    let app = App::new("cargo-fuzz")
        .version(option_env!("CARGO_PKG_VERSION").unwrap_or("0.0.0"))
        .about(option_env!("CARGO_PKG_DESCRIPTION").unwrap_or(""))
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .setting(AppSettings::GlobalVersion)
        // cargo passes in the subcommand name to the invoked executable. Use a hidden, optional
        // positional argument to deal with it?
        .arg(Arg::with_name("dummy").possible_value("fuzz").required(false).hidden(true))
        .subcommand(SubCommand::with_name("init").about("Initialize the fuzz folder"))
        .subcommand(SubCommand::with_name("run").about("Run the fuzz target in fuzz/fuzzers")
            .setting(AppSettings::TrailingVarArg)
            .arg(Arg::with_name("TARGET").required(true)
                 .help("name of the fuzz target"))
            .arg(Arg::with_name("ARGS").multiple(true)
                 .help("additional libFuzzer arguments passed to the binary \
                       (including a path to corpus or artefact which must be last argument)"))
        )
        .subcommand(SubCommand::with_name("add").about("Add a new fuzz target")
                    .arg(Arg::with_name("TARGET").required(true)
                         .help("name of the fuzz target"))
        )
        .subcommand(SubCommand::with_name("list").about("List all fuzz targets"));
    let args = app.get_matches();

    ::std::process::exit(match args.subcommand() {
        ("init", _) => FuzzProject::init().map(|_| ()),
        ("add", matches) =>
            FuzzProject::new().and_then(|p| p.add_target(matches.expect("arguments present"))),
        ("list", _) => FuzzProject::new().and_then(|p| p.list_targets()),
        ("run", matches) =>
            FuzzProject::new().and_then(|p| p.exec_target(matches.expect("arguments present"))),
        (s, _) => panic!("unimplemented subcommand {}!", s),
    }.map(|_| 0).unwrap_or_else(|err| {
        utils::report_error(err);
        1
    }));
}

struct FuzzProject {
    /// Path to the root cargo project
    ///
    /// Not the project with fuzz targets, but the project being fuzzed
    root_project: path::PathBuf,
    targets: Vec<String>,
}

impl FuzzProject {
    fn new() -> Result<Self> {
        let mut project = FuzzProject {
            root_project: find_package()?,
            targets: Vec::new()
        };
        let manifest = project.manifest()?;
        if !is_fuzz_manifest(&manifest) {
            return Err(format!("manifest `{:?}` does not look a cargo-fuzz manifest. \
                                Add following lines to override:\n\
                                [package.metadata]\ncargo-fuzz = true",
                                project.manifest_path()).into());
        }
        project.targets = collect_targets(&manifest);
        Ok(project)
    }

    /// Create the fuzz project structure
    ///
    /// This will not clone libfuzzer-sys
    fn init() -> Result<Self> {
        let project = FuzzProject {
            root_project: find_package()?,
            targets: Vec::new(),
        };
        let fuzz_project = project.path();
        // TODO: check if the project is already initialized
        fs::create_dir(&fuzz_project)?;
        fs::create_dir(fuzz_project.join("fuzzers"))?;

        let mut cargo = fs::File::create(fuzz_project.join("Cargo.toml"))?;
        cargo.write_fmt(toml_template!(project.root_project_name()?))?;

        let mut ignore = fs::File::create(fuzz_project.join(".gitignore"))?;
        ignore.write_fmt(gitignore_template!())?;

        const TARGET: &'static str = "fuzzer_script_1";
        project.create_target_template(TARGET)
               .chain_err(|| format!("could not create template file for target {:?}", TARGET))?;
        Ok(project)
    }

    fn list_targets(&self) -> Result<()> {
        for bin in &self.targets {
            utils::print_message(bin, term::color::GREEN);
        }
        Ok(())
    }

    fn add_target<'a>(&self, args: &ArgMatches<'a>) -> Result<()> {
        let target: String = args.value_of_os("TARGET").expect("TARGET is required").to_os_string()
            .into_string().map_err(|_| "TARGET must be valid unicode")?;
        self.create_target_template(&target)
            .chain_err(|| format!("could not create template file for target {:?}", target))
    }

    /// Add a new fuzz target script with a given name
    fn create_target_template<'a>(&self, target: &str) -> Result<()> {
        let target_path = self.target_path(target);
        let mut script = fs::OpenOptions::new().write(true).create_new(true).open(&target_path)?;
        script.write_fmt(target_template!(self.root_project_name()?.replace("-", "_")))?;

        let mut cargo = fs::OpenOptions::new().append(true)
            .open(self.manifest_path())?;
        Ok(cargo.write_fmt(toml_bin_template!(target))?)
    }

    /// Fuzz a given fuzz target
    fn exec_target<'a>(&self, args: &ArgMatches<'a>) -> Result<()> {
        let target: String = args.value_of_os("TARGET").expect("TARGET is required").to_os_string()
            .into_string().map_err(|_| "TARGET must be valid unicode")?;
        let exec_args = args.values_of_os("ARGS")
                            .map(|v| v.collect::<Vec<_>>());
        let target_triple = "x86_64-unknown-linux-gnu";

        let mut flags = env::var("RUSTFLAGS").unwrap_or("".into());
        if !flags.is_empty() {
            flags.push(' ');
        }
        flags.push_str("-Cpasses=sancov -Cllvm-args=-sanitizer-coverage-level=3 -Zsanitizer=address -Cpanic=abort");
        let mut cmd = process::Command::new("cargo");

        let mut artefact_arg = ffi::OsString::from("-artifact_prefix=");
        artefact_arg.push(self.artifacts_for(&target)?);

        // Merge the asan options, so users can still provide their own options
        // to e.g. disable the leak sanitizer. Options are colon-separated.
        let mut asan_opts = env::var("ASAN_OPTIONS").unwrap_or("".into());
        if !asan_opts.is_empty() {
            asan_opts.push(':');
        }
        asan_opts.push_str("detect_odr_violation=0");

        cmd.env("RUSTFLAGS", flags)
           .arg("run")
           .arg("--manifest-path")
           .arg(self.manifest_path())
           .arg("--verbose")
           .arg("--bin")
           .arg(&target)
           .arg("--target")
           // won't pass rustflags to build scripts
           .arg(target_triple)
           .arg("--")
           .arg(artefact_arg)
           .env("ASAN_OPTIONS", &asan_opts);

        // Corpus or artefact file must be last argument passed. Check if the last argument being
        // passed through to libfuzzer looks anything like a not-argument (missing `-`). If so,
        // do not append our pregenerated corpus directory.
        if let Some((last, rest)) = exec_args.as_ref().and_then(|args| args.split_last()) {
            for arg in rest {
                cmd.arg(arg);
            }
            if last.as_bytes().starts_with(b"-") {
                cmd.arg(last);
                cmd.arg(self.corpus_for(&target)?);
            } else {
                cmd.arg(last);
            }
        } else {
            cmd.arg(self.corpus_for(&target)?);
        }

        exec_cmd(&mut cmd).chain_err(|| format!("could not execute command: {:?}", cmd))?;
        Ok(())
    }

    fn path(&self) -> path::PathBuf {
        self.root_project.join("fuzz")
    }

    fn manifest_path(&self) -> path::PathBuf {
        self.path().join("Cargo.toml")
    }

    fn corpus_for(&self, target: &str) -> Result<path::PathBuf> {
        let mut p = self.path();
        p.push("corpus");
        p.push(target);
        fs::create_dir_all(&p)
            .chain_err(|| format!("could not make a corpus directory at {:?}", p))?;
        Ok(p)
    }

    fn artifacts_for(&self, target: &str) -> Result<path::PathBuf> {
        let mut p = self.path();
        p.push("artifacts");
        p.push(target);
        p.push(""); // trailing slash, necessary for libfuzzer, because it does simple concat
        fs::create_dir_all(&p)
            .chain_err(|| format!("could not make a artifact directory at {:?}", p))?;
        Ok(p)
    }

    fn target_path(&self, target: &str) -> path::PathBuf {
        let mut root = self.path();
        root.push("fuzzers");
        root.push(target);
        root.set_extension("rs");
        root
    }

    fn manifest(&self) -> Result<toml::Value> {
        let filename = self.manifest_path();
        let mut file = fs::File::open(&filename).chain_err(||
            format!("could not read the manifest file: {:?}", filename)
        )?;
        let mut data = Vec::new();
        file.read_to_end(&mut data)?;
        toml::from_slice(&data).chain_err(||
            format!("could not decode the manifest file at {:?}", filename)
        )
    }

    fn root_project_name(&self) -> Result<String> {
        let filename = self.root_project.join("Cargo.toml");
        let mut file = fs::File::open(&filename)?;
        let mut data = Vec::new();
        file.read_to_end(&mut data)?;
        let value: toml::Value = toml::from_slice(&data)?;
        let name = value.as_table().and_then(|v| v.get("package"))
                                   .and_then(toml::Value::as_table)
                                   .and_then(|v| v.get("name"))
                                   .and_then(toml::Value::as_str);
        if let Some(name) = name {
            Ok(String::from(name))
        } else {
            Err(format!("{:?} (package.name) is malformed", filename).into())
        }
    }
}

fn collect_targets(value: &toml::Value) -> Vec<String> {
    let bins = value.as_table().and_then(|v| v.get("bin"))
                               .and_then(toml::Value::as_array);
    if let Some(bins) = bins {
        bins.iter().map(|bin|
            bin.as_table().and_then(|v| v.get("name")).and_then(toml::Value::as_str)
        ).filter_map(|name| name.map(|v| String::from(v))).collect()
    } else {
        Vec::new()
    }
}

fn is_fuzz_manifest(value: &toml::Value) -> bool {
    let is_fuzz = value.as_table().and_then(|v| v.get("package"))
                                  .and_then(toml::Value::as_table)
                                  .and_then(|v| v.get("metadata"))
                                  .and_then(toml::Value::as_table)
                                  .and_then(|v| v.get("cargo-fuzz"))
                                  .and_then(toml::Value::as_bool);
    is_fuzz == Some(true)
}

/// Returns the path for the first found non-fuzz Cargo package
fn find_package() -> Result<path::PathBuf> {
    let mut dir = env::current_dir()?;
    let mut data = Vec::new();
    loop {
        let manifest_path = dir.join("Cargo.toml");
        match fs::File::open(&manifest_path) {
            Err(_) => {},
            Ok(mut f) => {
                f.read_to_end(&mut data)?;
                let value: toml::Value = toml::from_slice(&data)
                    .chain_err(||
                        format!("could not decode the manifest file at {:?}", manifest_path)
                    )?;
                if !is_fuzz_manifest(&value) {
                    // Not a cargo-fuzz project => must be a proper cargo project :)
                    return Ok(dir);
                }
            }
        }
        if !dir.pop() { break; }
    }
    Err("could not find a cargo project".into())
}

#[cfg(unix)]
fn exec_cmd(cmd: &mut process::Command) -> Result<process::ExitStatus> {
    use std::os::unix::process::CommandExt;
    Err(cmd.exec().into())
}

#[cfg(not(unix))]
fn exec_cmd(cmd: &mut process::Command) -> Result<process::ExitStatus> {
    cmd.status().map_err(|e| e.into())
}
<commit_msg>Create corpus and artefact dirs on target add<commit_after>// Copyright 2016 rust-fuzz developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

extern crate toml;
extern crate clap;
extern crate term;
#[macro_use]
extern crate error_chain;

use clap::{App, Arg, SubCommand, ArgMatches, AppSettings};
use std::{env, fs, path, ffi, process};
use std::io::Write;
use std::io::Read;

use std::os::unix::ffi::OsStrExt;

#[macro_use]
mod templates;
mod utils;

error_chain! {
    foreign_links {
        Toml(toml::de::Error);
        Io(::std::io::Error);
    }
}

fn main() {
    let app = App::new("cargo-fuzz")
        .version(option_env!("CARGO_PKG_VERSION").unwrap_or("0.0.0"))
        .about(option_env!("CARGO_PKG_DESCRIPTION").unwrap_or(""))
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .setting(AppSettings::GlobalVersion)
        // cargo passes in the subcommand name to the invoked executable. Use a hidden, optional
        // positional argument to deal with it?
        .arg(Arg::with_name("dummy").possible_value("fuzz").required(false).hidden(true))
        .subcommand(SubCommand::with_name("init").about("Initialize the fuzz folder"))
        .subcommand(SubCommand::with_name("run").about("Run the fuzz target in fuzz/fuzzers")
            .setting(AppSettings::TrailingVarArg)
            .arg(Arg::with_name("TARGET").required(true)
                 .help("name of the fuzz target"))
            .arg(Arg::with_name("ARGS").multiple(true)
                 .help("additional libFuzzer arguments passed to the binary \
                       (including a path to corpus or artefact which must be last argument)"))
        )
        .subcommand(SubCommand::with_name("add").about("Add a new fuzz target")
                    .arg(Arg::with_name("TARGET").required(true)
                         .help("name of the fuzz target"))
        )
        .subcommand(SubCommand::with_name("list").about("List all fuzz targets"));
    let args = app.get_matches();

    ::std::process::exit(match args.subcommand() {
        ("init", _) => FuzzProject::init().map(|_| ()),
        ("add", matches) =>
            FuzzProject::new().and_then(|p| p.add_target(matches.expect("arguments present"))),
        ("list", _) => FuzzProject::new().and_then(|p| p.list_targets()),
        ("run", matches) =>
            FuzzProject::new().and_then(|p| p.exec_target(matches.expect("arguments present"))),
        (s, _) => panic!("unimplemented subcommand {}!", s),
    }.map(|_| 0).unwrap_or_else(|err| {
        utils::report_error(err);
        1
    }));
}

struct FuzzProject {
    /// Path to the root cargo project
    ///
    /// Not the project with fuzz targets, but the project being fuzzed
    root_project: path::PathBuf,
    targets: Vec<String>,
}

impl FuzzProject {
    fn new() -> Result<Self> {
        let mut project = FuzzProject {
            root_project: find_package()?,
            targets: Vec::new()
        };
        let manifest = project.manifest()?;
        if !is_fuzz_manifest(&manifest) {
            return Err(format!("manifest `{:?}` does not look a cargo-fuzz manifest. \
                                Add following lines to override:\n\
                                [package.metadata]\ncargo-fuzz = true",
                                project.manifest_path()).into());
        }
        project.targets = collect_targets(&manifest);
        Ok(project)
    }

    /// Create the fuzz project structure
    ///
    /// This will not clone libfuzzer-sys
    fn init() -> Result<Self> {
        let project = FuzzProject {
            root_project: find_package()?,
            targets: Vec::new(),
        };
        let fuzz_project = project.path();
        // TODO: check if the project is already initialized
        fs::create_dir(&fuzz_project)?;
        fs::create_dir(fuzz_project.join("fuzzers"))?;

        let mut cargo = fs::File::create(fuzz_project.join("Cargo.toml"))?;
        cargo.write_fmt(toml_template!(project.root_project_name()?))?;

        let mut ignore = fs::File::create(fuzz_project.join(".gitignore"))?;
        ignore.write_fmt(gitignore_template!())?;

        const TARGET: &'static str = "fuzzer_script_1";
        project.create_target_template(TARGET)
               .chain_err(|| format!("could not create template file for target {:?}", TARGET))?;
        Ok(project)
    }

    fn list_targets(&self) -> Result<()> {
        for bin in &self.targets {
            utils::print_message(bin, term::color::GREEN);
        }
        Ok(())
    }

    fn add_target<'a>(&self, args: &ArgMatches<'a>) -> Result<()> {
        let target: String = args.value_of_os("TARGET").expect("TARGET is required").to_os_string()
            .into_string().map_err(|_| "TARGET must be valid unicode")?;
        // Create corpus and artifact directories for the newly added target
        self.corpus_for(&target)?;
        self.artifacts_for(&target)?;
        self.create_target_template(&target)
            .chain_err(|| format!("could not add target {:?}", target))
    }

    /// Add a new fuzz target script with a given name
    fn create_target_template<'a>(&self, target: &str) -> Result<()> {
        let target_path = self.target_path(target);
        let mut script = fs::OpenOptions::new().write(true).create_new(true).open(&target_path)
            .chain_err(|| format!("could not create target script file at {:?}", target_path))?;
        script.write_fmt(target_template!(self.root_project_name()?.replace("-", "_")))?;

        let mut cargo = fs::OpenOptions::new().append(true)
            .open(self.manifest_path())?;
        Ok(cargo.write_fmt(toml_bin_template!(target))?)
    }

    /// Fuzz a given fuzz target
    fn exec_target<'a>(&self, args: &ArgMatches<'a>) -> Result<()> {
        let target: String = args.value_of_os("TARGET").expect("TARGET is required").to_os_string()
            .into_string().map_err(|_| "TARGET must be valid unicode")?;
        let exec_args = args.values_of_os("ARGS")
                            .map(|v| v.collect::<Vec<_>>());
        let target_triple = "x86_64-unknown-linux-gnu";

        let mut flags = env::var("RUSTFLAGS").unwrap_or("".into());
        if !flags.is_empty() {
            flags.push(' ');
        }
        flags.push_str("-Cpasses=sancov -Cllvm-args=-sanitizer-coverage-level=3 -Zsanitizer=address -Cpanic=abort");
        let mut cmd = process::Command::new("cargo");

        let mut artefact_arg = ffi::OsString::from("-artifact_prefix=");
        artefact_arg.push(self.artifacts_for(&target)?);

        // Merge the asan options, so users can still provide their own options
        // to e.g. disable the leak sanitizer. Options are colon-separated.
        let mut asan_opts = env::var("ASAN_OPTIONS").unwrap_or("".into());
        if !asan_opts.is_empty() {
            asan_opts.push(':');
        }
        asan_opts.push_str("detect_odr_violation=0");

        cmd.env("RUSTFLAGS", flags)
           .arg("run")
           .arg("--manifest-path")
           .arg(self.manifest_path())
           .arg("--verbose")
           .arg("--bin")
           .arg(&target)
           .arg("--target")
           // won't pass rustflags to build scripts
           .arg(target_triple)
           .arg("--")
           .arg(artefact_arg)
           .env("ASAN_OPTIONS", &asan_opts);

        // Corpus or artefact file must be last argument passed. Check if the last argument being
        // passed through to libfuzzer looks anything like a not-argument (missing `-`). If so,
        // do not append our pregenerated corpus directory.
        if let Some((last, rest)) = exec_args.as_ref().and_then(|args| args.split_last()) {
            for arg in rest {
                cmd.arg(arg);
            }
            if last.as_bytes().starts_with(b"-") {
                cmd.arg(last);
                cmd.arg(self.corpus_for(&target)?);
            } else {
                cmd.arg(last);
            }
        } else {
            cmd.arg(self.corpus_for(&target)?);
        }

        exec_cmd(&mut cmd).chain_err(|| format!("could not execute command: {:?}", cmd))?;
        Ok(())
    }

    fn path(&self) -> path::PathBuf {
        self.root_project.join("fuzz")
    }

    fn manifest_path(&self) -> path::PathBuf {
        self.path().join("Cargo.toml")
    }

    fn corpus_for(&self, target: &str) -> Result<path::PathBuf> {
        let mut p = self.path();
        p.push("corpus");
        p.push(target);
        fs::create_dir_all(&p)
            .chain_err(|| format!("could not make a corpus directory at {:?}", p))?;
        Ok(p)
    }

    fn artifacts_for(&self, target: &str) -> Result<path::PathBuf> {
        let mut p = self.path();
        p.push("artifacts");
        p.push(target);
        p.push(""); // trailing slash, necessary for libfuzzer, because it does simple concat
        fs::create_dir_all(&p)
            .chain_err(|| format!("could not make a artifact directory at {:?}", p))?;
        Ok(p)
    }

    fn target_path(&self, target: &str) -> path::PathBuf {
        let mut root = self.path();
        root.push("fuzzers");
        root.push(target);
        root.set_extension("rs");
        root
    }

    fn manifest(&self) -> Result<toml::Value> {
        let filename = self.manifest_path();
        let mut file = fs::File::open(&filename).chain_err(||
            format!("could not read the manifest file: {:?}", filename)
        )?;
        let mut data = Vec::new();
        file.read_to_end(&mut data)?;
        toml::from_slice(&data).chain_err(||
            format!("could not decode the manifest file at {:?}", filename)
        )
    }

    fn root_project_name(&self) -> Result<String> {
        let filename = self.root_project.join("Cargo.toml");
        let mut file = fs::File::open(&filename)?;
        let mut data = Vec::new();
        file.read_to_end(&mut data)?;
        let value: toml::Value = toml::from_slice(&data)?;
        let name = value.as_table().and_then(|v| v.get("package"))
                                   .and_then(toml::Value::as_table)
                                   .and_then(|v| v.get("name"))
                                   .and_then(toml::Value::as_str);
        if let Some(name) = name {
            Ok(String::from(name))
        } else {
            Err(format!("{:?} (package.name) is malformed", filename).into())
        }
    }
}

fn collect_targets(value: &toml::Value) -> Vec<String> {
    let bins = value.as_table().and_then(|v| v.get("bin"))
                               .and_then(toml::Value::as_array);
    if let Some(bins) = bins {
        bins.iter().map(|bin|
            bin.as_table().and_then(|v| v.get("name")).and_then(toml::Value::as_str)
        ).filter_map(|name| name.map(|v| String::from(v))).collect()
    } else {
        Vec::new()
    }
}

fn is_fuzz_manifest(value: &toml::Value) -> bool {
    let is_fuzz = value.as_table().and_then(|v| v.get("package"))
                                  .and_then(toml::Value::as_table)
                                  .and_then(|v| v.get("metadata"))
                                  .and_then(toml::Value::as_table)
                                  .and_then(|v| v.get("cargo-fuzz"))
                                  .and_then(toml::Value::as_bool);
    is_fuzz == Some(true)
}

/// Returns the path for the first found non-fuzz Cargo package
fn find_package() -> Result<path::PathBuf> {
    let mut dir = env::current_dir()?;
    let mut data = Vec::new();
    loop {
        let manifest_path = dir.join("Cargo.toml");
        match fs::File::open(&manifest_path) {
            Err(_) => {},
            Ok(mut f) => {
                f.read_to_end(&mut data)?;
                let value: toml::Value = toml::from_slice(&data)
                    .chain_err(||
                        format!("could not decode the manifest file at {:?}", manifest_path)
                    )?;
                if !is_fuzz_manifest(&value) {
                    // Not a cargo-fuzz project => must be a proper cargo project :)
                    return Ok(dir);
                }
            }
        }
        if !dir.pop() { break; }
    }
    Err("could not find a cargo project".into())
}

#[cfg(unix)]
fn exec_cmd(cmd: &mut process::Command) -> Result<process::ExitStatus> {
    use std::os::unix::process::CommandExt;
    Err(cmd.exec().into())
}

#[cfg(not(unix))]
fn exec_cmd(cmd: &mut process::Command) -> Result<process::ExitStatus> {
    cmd.status().map_err(|e| e.into())
}
<|endoftext|>


<commit_before>pub use dces::prelude::{ComponentStore, Entity, EntityComponentManager};

pub use crate::{
    application::*,
    css_engine::{Selector as SelectorValue, SelectorRelation, Theme as ThemeValue, ThemeBuilder},
    event::*,
    layout::*,
    properties::*,
    property,
    render_object::*,
    systems::*,
    tree::Tree,
    widget,
    widget::*,
};
<commit_msg>Add macros to api prelude.<commit_after>pub use dces::prelude::{ComponentStore, Entity, EntityComponentManager};

pub use crate::{
    application::*,
    css_engine::{Selector as SelectorValue, SelectorRelation, Theme as ThemeValue, ThemeBuilder},
    event::*,
    layout::*,
    properties::*,
    property,
    render_object::*,
    systems::*,
    tree::Tree,
    widget,
    widget::*,
    macros::*
};
<|endoftext|>


<commit_before>#[macro_use] extern crate macro_attr;
#[macro_use] extern crate enum_derive;

use std::io::Write;
use std::env;

mod keybinds;
use keybinds::*;

mod file;
use file::*;

mod terminal;
use terminal::*;

const LINENO_CHARS : i32 = 3;

fn render_file(mut out: &mut Terminal, file: &File) {
    let (screen_width, screen_height) = out.get_size();

    let mut x = 1;
    let mut y = 1;

    for (line_number_maybe, line) in file.wrapped_lines((screen_width - LINENO_CHARS - 1, screen_height - 3)) {
        if let Some(line_number) = line_number_maybe {
            out.goto((x, y));
            out.set_color_fg(Color::Grey);
            write!(out, "{:1$}",
                   line_number + 1, LINENO_CHARS as usize).unwrap();
            out.set_color_fg(Color::Reset);
        }
        x += LINENO_CHARS + 1;
        out.goto((x, y));
        write!(out, "{}", line).unwrap();
        x = 1;
        y += 1;
    }
}

fn render_footer(mut out: &mut Terminal, keys: &KeybindTable) {
    let (screen_width, screen_height) = out.get_size();

    let mut x = 1;
    let mut y = screen_height - 1;
    for (key, action) in keys.entries() {
        out.goto((x, y));
        out.set_color_fg(Color::Black);
        out.set_color_bg(Color::White);
        write!(out, "{}", key).unwrap();
        out.set_color_fg(Color::Reset);
        out.set_color_bg(Color::Reset);
        write!(out, " {}", action).unwrap();
        x += 16;
        if x > screen_width {
            x = 1;
            y -= 1;
        }
    }
}

fn render_status(mut out: &mut Terminal, file: &File) {
    let (width, height) = out.get_size();
    let file_size = (width - LINENO_CHARS - 1, height - 3);
    let x = 1;
    let y = height;
    out.goto((x, y));
    write!(out, "{}", file.debug(file_size)).unwrap();
}

fn run_command(c: Command) {
}

fn main() {
    let keys = KeybindTable::default();
    let mut term = Terminal::default();
    term.clear();
    term.flush().unwrap();
    render_footer(&mut term, &keys);
    let args: Vec<String> = env::args().collect();
    let filename = args.get(1).cloned().unwrap_or(String::from("README.md"));
    let mut file = File::open(&filename);
    render_file(&mut term, &file);
    render_status(&mut term, &file);
    let (screen_w, screen_h) = term.get_size();
    let file_size = (screen_w - LINENO_CHARS - 1, screen_h - 3);
    term.goto((file.cursor(file_size).x + LINENO_CHARS + 1, file.cursor(file_size).y));
    term.flush().unwrap();
    let mut file_lines = file.lines.len();
    let mut file_wrapped_lines = file.wrapped_lines(file_size).len();
    let mut file_dirty = false;
    let mut screen_dirty = false;
    for evt in term.keys() {
        let (screen_w, screen_h) = term.get_size();
        let file_size = (screen_w - LINENO_CHARS - 1, screen_h - 3);
        match evt {
            Event::Mouse(_) => (),
            Event::Unsupported(_) => (),
            Event::Key(Key::Null) => (),
            Event::Key(Key::Insert) => (),
            Event::Key(Key::F(_)) => (),
            Event::Key(Key::Esc) => (),
            Event::Key(Key::Ctrl(k)) => {
                match keys.lookup(Key::Ctrl(k)) {
                    Some(Command::Quit) => break,
                    Some(c) => run_command(c),
                    None => ()
                }
            },
            Event::Key(Key::Alt(k)) => {
                match keys.lookup(Key::Alt(k)) {
                    Some(Command::Quit) => break,
                    Some(c) => run_command(c),
                    None => ()
                }
            },
            Event::Key(Key::Left) => {
                screen_dirty = file.move_cursor_left(file_size);
            },
            Event::Key(Key::Right) => {
                screen_dirty = file.move_cursor_right(file_size);
            },
            Event::Key(Key::Up) => {
                screen_dirty = file.move_cursor_up(file_size);
            },
            Event::Key(Key::Down) => {
                screen_dirty = file.move_cursor_down(file_size);
            },
            Event::Key(Key::Home) => file.move_cursor_home(file_size),
            Event::Key(Key::End) => file.move_cursor_end(file_size),
            Event::Key(Key::PageUp) => {
                file.page_up(file_size);
                screen_dirty = true;
            },
            Event::Key(Key::PageDown) => {
                file.page_down(file_size);
                screen_dirty = true;
            },
            Event::Key(Key::Char('\n')) => {
                file.insert_newline(file_size);
                screen_dirty = true;
            },
            Event::Key(Key::Delete) => {
                file.delete(file_size);
                screen_dirty = true;
            },
            Event::Key(Key::Backspace) => {
                file.backspace(file_size);
                screen_dirty = true;
            },
            Event::Key(Key::Char(c)) => {
                file.insert(file_size, c);
                file_dirty = true;
            },
        }
        if screen_dirty {
            file_dirty = true;
        }
        if file_dirty {
            let new_file_lines = file.lines.len();
            let new_file_wrapped_lines = file.wrapped_lines(file_size).len();
            if new_file_lines != file_lines {
                screen_dirty = true;
                file_lines = new_file_lines;
            }
            if new_file_wrapped_lines != file_wrapped_lines {
                screen_dirty = true;
                file_wrapped_lines = new_file_wrapped_lines;
            }
        }
        if screen_dirty {
            term.clear();
            render_footer(&mut term, &keys);
            screen_dirty = false;
        }
        if file_dirty {
            render_file(&mut term, &file);
            file_dirty = false;
        }
        render_status(&mut term, &file);
        term.goto((file.cursor(file_size).x + LINENO_CHARS + 1, file.cursor(file_size).y));
        term.flush().unwrap();
    }
}
<commit_msg>Actually handle all the shortcuts in one place<commit_after>#[macro_use] extern crate macro_attr;
#[macro_use] extern crate enum_derive;

use std::io::Write;
use std::env;

mod keybinds;
use keybinds::*;

mod file;
use file::*;

mod terminal;
use terminal::*;

const LINENO_CHARS : i32 = 3;

fn render_file(mut out: &mut Terminal, file: &File) {
    let (screen_width, screen_height) = out.get_size();

    let mut x = 1;
    let mut y = 1;

    for (line_number_maybe, line) in file.wrapped_lines((screen_width - LINENO_CHARS - 1, screen_height - 3)) {
        if let Some(line_number) = line_number_maybe {
            out.goto((x, y));
            out.set_color_fg(Color::Grey);
            write!(out, "{:1$}",
                   line_number + 1, LINENO_CHARS as usize).unwrap();
            out.set_color_fg(Color::Reset);
        }
        x += LINENO_CHARS + 1;
        out.goto((x, y));
        write!(out, "{}", line).unwrap();
        x = 1;
        y += 1;
    }
}

fn render_footer(mut out: &mut Terminal, keys: &KeybindTable) {
    let (screen_width, screen_height) = out.get_size();

    let mut x = 1;
    let mut y = screen_height - 1;
    for (key, action) in keys.entries() {
        out.goto((x, y));
        out.set_color_fg(Color::Black);
        out.set_color_bg(Color::White);
        write!(out, "{}", key).unwrap();
        out.set_color_fg(Color::Reset);
        out.set_color_bg(Color::Reset);
        write!(out, " {}", action).unwrap();
        x += 16;
        if x > screen_width {
            x = 1;
            y -= 1;
        }
    }
}

fn render_status(mut out: &mut Terminal, file: &File) {
    let (width, height) = out.get_size();
    let file_size = (width - LINENO_CHARS - 1, height - 3);
    let x = 1;
    let y = height;
    out.goto((x, y));
    write!(out, "{}", file.debug(file_size)).unwrap();
}

fn run_command(c: Command) {
}

fn main() {
    let keys = KeybindTable::default();
    let mut term = Terminal::default();
    term.clear();
    term.flush().unwrap();
    render_footer(&mut term, &keys);
    let args: Vec<String> = env::args().collect();
    let filename = args.get(1).cloned().unwrap_or(String::from("README.md"));
    let mut file = File::open(&filename);
    render_file(&mut term, &file);
    render_status(&mut term, &file);
    let (screen_w, screen_h) = term.get_size();
    let file_size = (screen_w - LINENO_CHARS - 1, screen_h - 3);
    term.goto((file.cursor(file_size).x + LINENO_CHARS + 1, file.cursor(file_size).y));
    term.flush().unwrap();
    let mut file_lines = file.lines.len();
    let mut file_wrapped_lines = file.wrapped_lines(file_size).len();
    let mut file_dirty = false;
    let mut screen_dirty = false;
    for evt in term.keys() {
        let (screen_w, screen_h) = term.get_size();
        let file_size = (screen_w - LINENO_CHARS - 1, screen_h - 3);
        match evt {
            Event::Mouse(_) => (),
            Event::Unsupported(_) => (),
            Event::Key(Key::Null) => (),
            Event::Key(Key::Insert) => (),
            Event::Key(Key::F(_)) => (),
            Event::Key(Key::Esc) => (),
            Event::Key(k @ Key::Ctrl(_)) | Event::Key(k @ Key::Alt(_)) => {
                match keys.lookup(k) {
                    Some(Command::Quit) => break,
                    None => (),
                    _ => ()
                }
            },
            Event::Key(Key::Left) => {
                screen_dirty = file.move_cursor_left(file_size);
            },
            Event::Key(Key::Right) => {
                screen_dirty = file.move_cursor_right(file_size);
            },
            Event::Key(Key::Up) => {
                screen_dirty = file.move_cursor_up(file_size);
            },
            Event::Key(Key::Down) => {
                screen_dirty = file.move_cursor_down(file_size);
            },
            Event::Key(Key::Home) => file.move_cursor_home(file_size),
            Event::Key(Key::End) => file.move_cursor_end(file_size),
            Event::Key(Key::PageUp) => {
                file.page_up(file_size);
                screen_dirty = true;
            },
            Event::Key(Key::PageDown) => {
                file.page_down(file_size);
                screen_dirty = true;
            },
            Event::Key(Key::Char('\n')) => {
                file.insert_newline(file_size);
                screen_dirty = true;
            },
            Event::Key(Key::Delete) => {
                file.delete(file_size);
                screen_dirty = true;
            },
            Event::Key(Key::Backspace) => {
                file.backspace(file_size);
                screen_dirty = true;
            },
            Event::Key(Key::Char(c)) => {
                file.insert(file_size, c);
                file_dirty = true;
            },
        }
        if screen_dirty {
            file_dirty = true;
        }
        if file_dirty {
            let new_file_lines = file.lines.len();
            let new_file_wrapped_lines = file.wrapped_lines(file_size).len();
            if new_file_lines != file_lines {
                screen_dirty = true;
                file_lines = new_file_lines;
            }
            if new_file_wrapped_lines != file_wrapped_lines {
                screen_dirty = true;
                file_wrapped_lines = new_file_wrapped_lines;
            }
        }
        if screen_dirty {
            term.clear();
            render_footer(&mut term, &keys);
            screen_dirty = false;
        }
        if file_dirty {
            render_file(&mut term, &file);
            file_dirty = false;
        }
        render_status(&mut term, &file);
        term.goto((file.cursor(file_size).x + LINENO_CHARS + 1, file.cursor(file_size).y));
        term.flush().unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate recital;

use getopts::{Matches, Options};
use recital::prelude::*;
use std::{env, io, process};
use std::io::Write;

/// The current version of this program.
const VERSION: &'static str = "0.1.0";

/// Processes the command line arguments.
fn main() {
    let args: Vec<String> = env::args().collect();

    let mut rules = Options::new();

    rules.optflag("1", "major",
                  "Increment the major version number.");

    rules.optflag("2", "minor",
                  "Increment the minor version number.");

    rules.optflag("3", "patch",
                  "Increment the patch version number.");

    rules.optflag("e", "equal-to",
                  "Confirm VERSION is equal to VERSION.");

    rules.optflag("g", "greater-than",
                  "Confirm VERSION is greater than VERSION.");

    rules.optflag("h", "help",
                  "Displays this help mssage.");

    rules.optflag("l", "less-than",
                  "Confirm VERSION is less than VERSION.");

    rules.optflag("v", "version",
                  "Displays the version of this program.");

    let options = match rules.parse(&args[1..]) {
        Ok(result) => result,
        Err(error) => exit(1, &error.to_string()),
    };

    if options.opt_present("h") {
        usage(&args[0], &rules);
    }

    if options.opt_present("v") {
        println!("{} v{}", &args[0], &VERSION);

        process::exit(0);
    }

    match options.free.len() {
        0 => usage(&args[0], &rules),
        1 => modify(&options),
        2 => compare(&options),
        _ => exit(1, "Too many arguments provided."),
    }
}

/// Compares the given version numbers.
fn compare(options: &Matches) {
    let left = parse(&options.free[0]);
    let right = parse(&options.free[1]);

    if options.opt_present("g") && options.opt_present("l") {
        exit(1, "Cannot combine --greater-than and --less-than.");
    }

    if options.opt_present("e") {
        if left == right {
            return;
        }
    }

    if options.opt_present("g") {
        if left > right {
            return;
        }
    }

    if options.opt_present("l") {
        if left < right {
            return;
        }
    }

    process::exit(1);
}

/// Exits the program early with a message.
fn exit(code: i32, message: &str) -> ! {
    let _ = writeln!(io::stderr(), "{}", message);

    process::exit(code);
}

/// Modifies the given version number.
fn modify(options: &Matches) {
    let mut version = parse(&options.free[0]);

    if options.opt_present("1") {
        version.increment_major();
    }

    if options.opt_present("2") {
        version.increment_minor();
    }

    if options.opt_present("3") {
        version.increment_patch();
    }

    println!("{}", version);
}

/// Parses a version number.
fn parse(version: &str) -> Version {
    match version.parse() {
        Ok(result) => result,
        Err(_) => exit(1, &format!("Invalid version number: {}", version)),
    }
}

/// Displays the usage message.
fn usage(program: &str, options: &Options) {
    let b = format!("Usage: {} [OPTIONS] VERSION [VERSION]", program);
    let _ = writeln!(io::stderr(), "{}", options.usage(&b));

    process::exit(0);
}
<commit_msg>Adding description.<commit_after>extern crate getopts;
extern crate recital;

use getopts::{Matches, Options};
use recital::prelude::*;
use std::{env, io, process};
use std::io::Write;

/// The current version of this program.
const VERSION: &'static str = "0.1.0";

/// Processes the command line arguments.
fn main() {
    let args: Vec<String> = env::args().collect();

    let mut rules = Options::new();

    rules.optflag("1", "major",
                  "Increment the major version number.");

    rules.optflag("2", "minor",
                  "Increment the minor version number.");

    rules.optflag("3", "patch",
                  "Increment the patch version number.");

    rules.optflag("e", "equal-to",
                  "Confirm VERSION is equal to VERSION.");

    rules.optflag("g", "greater-than",
                  "Confirm VERSION is greater than VERSION.");

    rules.optflag("h", "help",
                  "Displays this help mssage.");

    rules.optflag("l", "less-than",
                  "Confirm VERSION is less than VERSION.");

    rules.optflag("v", "version",
                  "Displays the version of this program.");

    let options = match rules.parse(&args[1..]) {
        Ok(result) => result,
        Err(error) => exit(1, &error.to_string()),
    };

    if options.opt_present("h") {
        usage(&args[0], &rules);
    }

    if options.opt_present("v") {
        println!("{} v{}", &args[0], &VERSION);

        process::exit(0);
    }

    match options.free.len() {
        0 => usage(&args[0], &rules),
        1 => modify(&options),
        2 => compare(&options),
        _ => exit(1, "Too many arguments provided."),
    }
}

/// Compares the given version numbers.
fn compare(options: &Matches) {
    let left = parse(&options.free[0]);
    let right = parse(&options.free[1]);

    if options.opt_present("g") && options.opt_present("l") {
        exit(1, "Cannot combine --greater-than and --less-than.");
    }

    if options.opt_present("e") {
        if left == right {
            return;
        }
    }

    if options.opt_present("g") {
        if left > right {
            return;
        }
    }

    if options.opt_present("l") {
        if left < right {
            return;
        }
    }

    process::exit(1);
}

/// Exits the program early with a message.
fn exit(code: i32, message: &str) -> ! {
    let _ = writeln!(io::stderr(), "{}", message);

    process::exit(code);
}

/// Modifies the given version number.
fn modify(options: &Matches) {
    let mut version = parse(&options.free[0]);

    if options.opt_present("1") {
        version.increment_major();
    }

    if options.opt_present("2") {
        version.increment_minor();
    }

    if options.opt_present("3") {
        version.increment_patch();
    }

    println!("{}", version);
}

/// Parses a version number.
fn parse(version: &str) -> Version {
    match version.parse() {
        Ok(result) => result,
        Err(_) => exit(1, &format!("Invalid version number: {}", version)),
    }
}

/// Displays the usage message.
fn usage(program: &str, options: &Options) {
    let b = format!("Usage: {} [OPTIONS] VERSION [VERSION]\n{}", program,
                    "Edit and compare semantic version numbers.");
    let _ = writeln!(io::stderr(), "{}", options.usage(&b));

    process::exit(0);
}
<|endoftext|>