<commit_before>
mod stdout_writer;

extern crate clap;
extern crate xor_utils;
extern crate hex;
extern crate base64;

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

use log::LogLevel;
use clap::{App, Arg, ArgMatches};
use std::io;
use std::io::{Cursor};
use std::fs;
use std::path::Path;
use std::fs::{File, OpenOptions, DirEntry};
use std::io::{Write, Read};
use xor_utils::Xor;
use xor_utils::*;
use hex::{ToHex, FromHex};

enum Mode {
    Encrypt,
    Decrypt
}

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

    // Parse arguments and provide help.
    let matches = App::new("xor")
        .version("1.3.0")
        .about("XORs input against a provided key")
        .author("Gavyn Riebau")
        .arg(Arg::with_name("key")
             .help("The file containing the key data, or a provided string, against which input will be XOR'd.\nThis should be larger than the given input data or will need to be repeated to encode the input data.")
             .long("key")
             .short("k")
             .required(true)
             .value_name("KEY"))
        .arg(Arg::with_name("force")
             .help("Don't show warning prompt if the key size is too small and key bytes will have to be re-used.\nRe-using key bytes makes the encryption vulnerable to being decrypted.")
             .long("force")
             .short("f"))
        .arg(Arg::with_name("mode")
             .help("The operating mode (i.e. whether encrypting or decrypting).\nOnly applicable when encrypting directories and affects how the file will be renamed.\nWhen in encrypt mode, names are xor'd then converted to hex strings.\nWhen in decrypt mode, names are parsed from hex strings then xor'd to restore the original name.")
             .long("mode")
             .short("m")
             .possible_values(&["e", "d"])
             .default_value("e"))
        .arg(Arg::with_name("input")
             .help("The file from which input data will be read, if omitted input will be read from stdin.")
             .long("input")
             .short("i")
             .required(false)
             .value_name("FILE"))
        .arg(Arg::with_name("recursive")
             .help("Recursively encrypt / decrypt files and subfolders starting at the given directory.\nFiles and directory names will be encrypted / decrypted according to the \"mode\" argument.\nNames are xor encrypted then converted to a hex string.")
             .long("recursive")
             .short("r")
             .conflicts_with("output")
             .value_name("DIRECTORY")
             .conflicts_with("input")
             .conflicts_with("output"))
        .arg(Arg::with_name("output")
             .help("The file to which encoded data will be written, if omitted output will be written to stdout.\nIt's recommended to write output to a file for cases where the encoded data contains non-unicode characters which would otherwise not be printed to the console.")
             .long("output")
             .short("o")
             .required(false)
             .value_name("FILE"))
        .arg(Arg::with_name("verbose")
             .help("Increases the level of feedback given")
             .long("verbose")
             .short("v")
             .required(false))
         .get_matches();

    let mode = match matches.value_of("mode").unwrap() {
        "e" => Mode::Encrypt,
        "d" => Mode::Decrypt,
        _ => Mode::Encrypt
    };

    let key_bytes = get_key_bytes(&matches);

    if matches.is_present("recursive") {
        // Recursively encrypt files and folders in the specified directory.
        let starting_dir_name = matches.value_of("recursive").unwrap();
        let starting_dir = Path::new(starting_dir_name);

        encrypt_path(starting_dir, &key_bytes, &mode);
    } else {
        // If the "file" argument was supplied input will be read from the file, otherwise
        // input is read from stdin.
        let input : Box<Read> = if matches.is_present("input") {
            Box::new(File::open(matches.value_of("input").unwrap()).unwrap())
        } else {
            Box::new(io::stdin())
        };

        // If "output" argument was supplied output will be written to a file, otherwise
        // it's written to stdout.
        let output : Box<Write> = if matches.is_present("output") {
            Box::new(OpenOptions::new()
                .write(true)
                .create(true)
                .truncate(true)
                .open(matches.value_of("output").unwrap())
                .unwrap())
        } else {
            Box::new(stdout_writer::StdoutWriter{})
        };

        encrypt_reader(input, &key_bytes, output);
    }
}

fn encrypt_reader(mut input : Box<Read>, key : &Vec<u8>, mut output : Box<Write>) {
    let encoded_bytes = input.by_ref().xor(&key);
    let _ = output.write_all(encoded_bytes.as_slice());
    output.flush().unwrap();
}

fn encrypt_path(p : &Path, key : &Vec<u8>, mode : &Mode) {
    for item in fs::read_dir(p).unwrap() {
        let entry = item.unwrap();
        xor_entry(&entry, key, mode);
    }
}

fn xor_entry(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    if let Ok(entry_type) = entry.file_type() {
        if entry_type.is_dir() {
            xor_dir(entry, key, mode);
        } else if entry_type.is_file() {
            xor_file(entry, key, mode);
        } else if entry_type.is_symlink() {
            xor_symlink(entry, key, mode);
        }
    }
}

fn xor_file(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    info!("Encrypting file {:?}", entry);

    if let Ok(mut file) = File::open(entry.path()) {
        let mut reader = &mut file as &mut Read;
        let cypher_text = reader.xor(&key);

        let mut writer = OpenOptions::new()
            .write(true)
            .truncate(true)
            .open(entry.path())
            .unwrap();

        writer.write_all(cypher_text.as_slice()).unwrap();
    }

    rename_entry(entry, key, mode);
}

fn xor_symlink(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    info!("Encrypting symlink {:?}", entry);

    rename_entry(entry, key, mode);
}

fn xor_dir(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    info!("Encrypting dir {:?}", entry);

    match fs::read_dir(entry.path()) {
        Ok(entries) => {
            for child in entries {
                if let Ok(child) = child {
                    xor_entry(&child, key, mode);
                }
            }
        },
        Err(e) => {
            let mut stderr = io::stderr();
            let _ = stderr.write_fmt(format_args!("Failed to read directory: {}", e));
        }
    }

    rename_entry(entry, key, mode);
}

fn rename_entry(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    // Encrypt the directory entry itself.
    let file_name = entry.file_name();

    if let Some(original_name) = file_name.to_str() {
        debug!("original_name: {}", original_name);

        let mut key_repeated = repeat_key(key, original_name.len());

        let input_bytes = match *mode {
            Mode::Encrypt => original_name.to_string().into_bytes(),
            Mode::Decrypt => from_hex_string(String::from(original_name))
        };

        let mut encrypted = Vec::with_capacity(input_bytes.len());
        for (d, k) in input_bytes.iter().zip(key_repeated) {
            encrypted.push(d ^ k);
        }

        let replaced_name = match *mode {
            Mode::Encrypt => to_hex_string(encrypted),
            Mode::Decrypt => String::from_utf8(encrypted).unwrap()
        };
        debug!("replaced_name: {}", replaced_name);

        let full_path_buf = entry.path();
        let full_path = full_path_buf.as_path();
        let parent_path = full_path.parent().unwrap();

        let src_file_path_buf = parent_path.join(original_name);
        let dst_file_path_buf = parent_path.join(replaced_name);

        let src_file_path = src_file_path_buf.as_path();
        let dst_file_path = dst_file_path_buf.as_path();

        debug!("Moving {:?} to {:?}", src_file_path, dst_file_path);
        fs::rename(src_file_path, dst_file_path).unwrap();
    }
}

/// Create a vector of bytes equal in length to the name of the file.
/// If the key is too small it'll be repeated to make up the required length.
fn repeat_key(key : &Vec<u8>, required_len : usize) -> Vec<u8> {
    let mut key_repeated = Vec::with_capacity(required_len);

    while key_repeated.len() < required_len {
        for &b in key {
            key_repeated.push(b);

            if key_repeated.len() == required_len {
                break;
            }
        }
    }

    key_repeated
}

fn to_hex_string(bytes: Vec<u8>) -> String {
  let strings: Vec<String> = bytes.iter()
                               .map(|b| format!("{:02X}", b))
                               .collect();

  strings.join("")
}

fn from_hex_string(hex : String) -> Vec<u8> {
    hex::FromHex::from_hex(hex).unwrap()
}

fn get_key_bytes<'a>(matches: &'a ArgMatches<'a>) -> Vec<u8> {
    let mut key_bytes : Vec<u8> = Vec::new();

    let key = matches.value_of("key").unwrap();

    // If the key is a file, read the contents of the file.
    // Otherwise if key is a string, use the string bytes.
    if Path::new(key).exists() {
        File::open(key).unwrap().read_to_end(&mut key_bytes).unwrap();
    } else {
        key_bytes = key.to_string().into_bytes();
    }

    key_bytes
}

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

    #[test]
    fn to_hex_string_works() {
        let input_string = String::from("hello");
        let input_bytes = input_string.into_bytes();

        let hex_string = to_hex_string(input_bytes);
        assert_eq!(hex_string, "68656C6C6F");
    }

    #[test]
    fn from_hex_string_works() {
        let input_string = String::from("68656C6C6F");
        let ascii_bytes = from_hex_string(input_string);
        let expected_bytes = vec![104, 101, 108, 108, 111];

        assert_eq!(expected_bytes, ascii_bytes);
    }

}

<commit_msg>Fixed warnings<commit_after>
mod stdout_writer;

extern crate clap;
extern crate xor_utils;
extern crate hex;
extern crate base64;

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

use clap::{App, Arg, ArgMatches};
use std::io;
use std::fs;
use std::path::Path;
use std::fs::{File, OpenOptions, DirEntry};
use std::io::{Write, Read};
use xor_utils::Xor;

enum Mode {
    Encrypt,
    Decrypt
}

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

    // Parse arguments and provide help.
    let matches = App::new("xor")
        .version("1.3.0")
        .about("XORs input against a provided key")
        .author("Gavyn Riebau")
        .arg(Arg::with_name("key")
             .help("The file containing the key data, or a provided string, against which input will be XOR'd.\nThis should be larger than the given input data or will need to be repeated to encode the input data.")
             .long("key")
             .short("k")
             .required(true)
             .value_name("KEY"))
        .arg(Arg::with_name("force")
             .help("Don't show warning prompt if the key size is too small and key bytes will have to be re-used.\nRe-using key bytes makes the encryption vulnerable to being decrypted.")
             .long("force")
             .short("f"))
        .arg(Arg::with_name("mode")
             .help("The operating mode (i.e. whether encrypting or decrypting).\nOnly applicable when encrypting directories and affects how the file will be renamed.\nWhen in encrypt mode, names are xor'd then converted to hex strings.\nWhen in decrypt mode, names are parsed from hex strings then xor'd to restore the original name.")
             .long("mode")
             .short("m")
             .possible_values(&["e", "d"])
             .default_value("e"))
        .arg(Arg::with_name("input")
             .help("The file from which input data will be read, if omitted input will be read from stdin.")
             .long("input")
             .short("i")
             .required(false)
             .value_name("FILE"))
        .arg(Arg::with_name("recursive")
             .help("Recursively encrypt / decrypt files and subfolders starting at the given directory.\nFiles and directory names will be encrypted / decrypted according to the \"mode\" argument.\nNames are xor encrypted then converted to a hex string.")
             .long("recursive")
             .short("r")
             .conflicts_with("output")
             .value_name("DIRECTORY")
             .conflicts_with("input")
             .conflicts_with("output"))
        .arg(Arg::with_name("output")
             .help("The file to which encoded data will be written, if omitted output will be written to stdout.\nIt's recommended to write output to a file for cases where the encoded data contains non-unicode characters which would otherwise not be printed to the console.")
             .long("output")
             .short("o")
             .required(false)
             .value_name("FILE"))
        .arg(Arg::with_name("verbose")
             .help("Increases the level of feedback given")
             .long("verbose")
             .short("v")
             .required(false))
         .get_matches();

    let mode = match matches.value_of("mode").unwrap() {
        "e" => Mode::Encrypt,
        "d" => Mode::Decrypt,
        _ => Mode::Encrypt
    };

    let key_bytes = get_key_bytes(&matches);

    if matches.is_present("recursive") {
        // Recursively encrypt files and folders in the specified directory.
        let starting_dir_name = matches.value_of("recursive").unwrap();
        let starting_dir = Path::new(starting_dir_name);

        encrypt_path(starting_dir, &key_bytes, &mode);
    } else {
        // If the "file" argument was supplied input will be read from the file, otherwise
        // input is read from stdin.
        let input : Box<Read> = if matches.is_present("input") {
            Box::new(File::open(matches.value_of("input").unwrap()).unwrap())
        } else {
            Box::new(io::stdin())
        };

        // If "output" argument was supplied output will be written to a file, otherwise
        // it's written to stdout.
        let output : Box<Write> = if matches.is_present("output") {
            Box::new(OpenOptions::new()
                .write(true)
                .create(true)
                .truncate(true)
                .open(matches.value_of("output").unwrap())
                .unwrap())
        } else {
            Box::new(stdout_writer::StdoutWriter{})
        };

        encrypt_reader(input, &key_bytes, output);
    }
}

fn encrypt_reader(mut input : Box<Read>, key : &Vec<u8>, mut output : Box<Write>) {
    let encoded_bytes = input.by_ref().xor(&key);
    let _ = output.write_all(encoded_bytes.as_slice());
    output.flush().unwrap();
}

fn encrypt_path(p : &Path, key : &Vec<u8>, mode : &Mode) {
    for item in fs::read_dir(p).unwrap() {
        let entry = item.unwrap();
        xor_entry(&entry, key, mode);
    }
}

fn xor_entry(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    if let Ok(entry_type) = entry.file_type() {
        if entry_type.is_dir() {
            xor_dir(entry, key, mode);
        } else if entry_type.is_file() {
            xor_file(entry, key, mode);
        } else if entry_type.is_symlink() {
            xor_symlink(entry, key, mode);
        }
    }
}

fn xor_file(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    info!("Encrypting file {:?}", entry);

    if let Ok(mut file) = File::open(entry.path()) {
        let mut reader = &mut file as &mut Read;
        let cypher_text = reader.xor(&key);

        let mut writer = OpenOptions::new()
            .write(true)
            .truncate(true)
            .open(entry.path())
            .unwrap();

        writer.write_all(cypher_text.as_slice()).unwrap();
    }

    rename_entry(entry, key, mode);
}

fn xor_symlink(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    info!("Encrypting symlink {:?}", entry);

    rename_entry(entry, key, mode);
}

fn xor_dir(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    info!("Encrypting dir {:?}", entry);

    match fs::read_dir(entry.path()) {
        Ok(entries) => {
            for child in entries {
                if let Ok(child) = child {
                    xor_entry(&child, key, mode);
                }
            }
        },
        Err(e) => {
            let mut stderr = io::stderr();
            let _ = stderr.write_fmt(format_args!("Failed to read directory: {}", e));
        }
    }

    rename_entry(entry, key, mode);
}

fn rename_entry(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    // Encrypt the directory entry itself.
    let file_name = entry.file_name();

    if let Some(original_name) = file_name.to_str() {
        debug!("original_name: {}", original_name);

        let key_repeated = repeat_key(key, original_name.len());

        let input_bytes = match *mode {
            Mode::Encrypt => original_name.to_string().into_bytes(),
            Mode::Decrypt => from_hex_string(String::from(original_name))
        };

        let mut encrypted = Vec::with_capacity(input_bytes.len());
        for (d, k) in input_bytes.iter().zip(key_repeated) {
            encrypted.push(d ^ k);
        }

        let replaced_name = match *mode {
            Mode::Encrypt => to_hex_string(encrypted),
            Mode::Decrypt => String::from_utf8(encrypted).unwrap()
        };
        debug!("replaced_name: {}", replaced_name);

        let full_path_buf = entry.path();
        let full_path = full_path_buf.as_path();
        let parent_path = full_path.parent().unwrap();

        let src_file_path_buf = parent_path.join(original_name);
        let dst_file_path_buf = parent_path.join(replaced_name);

        let src_file_path = src_file_path_buf.as_path();
        let dst_file_path = dst_file_path_buf.as_path();

        debug!("Moving {:?} to {:?}", src_file_path, dst_file_path);
        fs::rename(src_file_path, dst_file_path).unwrap();
    }
}

/// Create a vector of bytes equal in length to the name of the file.
/// If the key is too small it'll be repeated to make up the required length.
fn repeat_key(key : &Vec<u8>, required_len : usize) -> Vec<u8> {
    let mut key_repeated = Vec::with_capacity(required_len);

    while key_repeated.len() < required_len {
        for &b in key {
            key_repeated.push(b);

            if key_repeated.len() == required_len {
                break;
            }
        }
    }

    key_repeated
}

fn to_hex_string(bytes: Vec<u8>) -> String {
  let strings: Vec<String> = bytes.iter()
                               .map(|b| format!("{:02X}", b))
                               .collect();

  strings.join("")
}

fn from_hex_string(hex : String) -> Vec<u8> {
    hex::FromHex::from_hex(hex).unwrap()
}

fn get_key_bytes<'a>(matches: &'a ArgMatches<'a>) -> Vec<u8> {
    let mut key_bytes : Vec<u8> = Vec::new();

    let key = matches.value_of("key").unwrap();

    // If the key is a file, read the contents of the file.
    // Otherwise if key is a string, use the string bytes.
    if Path::new(key).exists() {
        File::open(key).unwrap().read_to_end(&mut key_bytes).unwrap();
    } else {
        key_bytes = key.to_string().into_bytes();
    }

    key_bytes
}

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

    #[test]
    fn to_hex_string_works() {
        let input_string = String::from("hello");
        let input_bytes = input_string.into_bytes();

        let hex_string = to_hex_string(input_bytes);
        assert_eq!(hex_string, "68656C6C6F");
    }

    #[test]
    fn from_hex_string_works() {
        let input_string = String::from("68656C6C6F");
        let ascii_bytes = from_hex_string(input_string);
        let expected_bytes = vec![104, 101, 108, 108, 111];

        assert_eq!(expected_bytes, ascii_bytes);
    }

}

<|endoftext|>


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

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

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

mod payloads;

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

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

    let matches = app.get_matches();

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

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

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

    let bit_array = code.to_colors();

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

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

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

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

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

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

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

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

mod payloads;

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

/*TODO: add arguments for:
- ec Level
- size of qr code
- implement different types of qr payloads
*/
fn main() {
        .arg(Arg::with_name("safe_zone") //TODO: change this into an off switch
    let app = App::new(crate_name!())
        .version(crate_version!())
        .author(crate_authors!("\n"))
        .about(crate_description!())
        .global_setting(AppSettings::SubcommandsNegateReqs)
            .global(true)
            .required(false)
            .short("s")
            .long("safe-zone")
            .help("Sets wether the safe zone around the code should be drawn or not.")
            .takes_value(false)
            )
            //TODO: subcmds are not working like expected, if you have one the system assumes you have many
        .arg(Arg::with_name("INPUT")
            .help("The input string to use")
            .required(true))
        .subcommand(SubCommand::with_name(WIFI_COMMAND)
            .about("formats to a wifi access string")
            .arg(Arg::with_name("ssid").required(true))
            .arg(Arg::with_name("pwd").required(true))
            .arg(Arg::with_name("mode")
                .possible_values(&["WEP", "WPA", "nopass"])
                .default_value("WPA")
                .value_name("MODE"))
            .arg(Arg::with_name("hidden")
                .required(false)
                .possible_values(&["true", "false"])
                .default_value("false")
                .value_name("HIDDEN")))
        .subcommand(SubCommand::with_name(MAIL_COMMAND)
            .about("formats to a mail adress string")
            .arg(Arg::with_name("receiver").required(true))
            .arg(Arg::with_name("subject"))
            .arg(Arg::with_name("message"))
            .arg(Arg::with_name("encoding")
                .possible_values(&["MAILTO", "MATMSG", "SMTP"])
                .default_value("MAILTO")
                .value_name("ENCODING")))
        .subcommand(SubCommand::with_name(URL_COMMAND)
            .about("formats to an URL")
            .arg(Arg::with_name("url")
                .required(true)
                .value_name("URL")))
        .subcommand(SubCommand::with_name(PHONE_COMMAND)
            .about("formats to a phone number")
            .arg(Arg::with_name("number")
                .required(true)
                .value_name("NUMBER"))
        );

    let matches = app.get_matches();

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

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

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

    let bit_array = code.to_colors();

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

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

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

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

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

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


<commit_before>#![feature(lang_items,core_intrinsics,asm,start)]
#![no_std]
#![crate_type="staticlib"]

use core::intrinsics::volatile_store;

#[lang="eh_personality"]
extern "C" fn eh_personality() {}
#[lang="panic_fmt"]
#[no_mangle]
pub extern "C" fn rust_begin_unwind(_fmt: &core::fmt::Arguments,
                                    _file_line: &(&'static str, usize))
                                    -> ! {
    loop {}
}

#[no_mangle]
pub extern "C" fn __aeabi_unwind_cpp_pr0() -> () {
    loop {}
}

#[no_mangle]
pub extern "C" fn __aeabi_unwind_cpp_pr1() -> () {
    loop {}
}

macro_rules! GPIOC_PDOR   {() => (0x400FF080 as *mut u32);} // GPIOC_PDOR - page 1334,1335
macro_rules! WDOG_UNLOCK  {() => (0x4005200E as *mut u16);} // Watchdog Unlock register
macro_rules! WDOG_STCTRLH {() => (0x40052000 as *mut u16);} // Watchdog Status and Control Register High
macro_rules! GPIO_CONFIG  {() => (0x40048038 as *mut u32);}
macro_rules! PORTC_PCR5   {() => (0x4004B014 as *mut u32);} // PORTC_PCR5 - page 223/227
macro_rules! GPIOC_PDDR   {() => (0x400FF094 as *mut u32);} // GPIOC_PDDR - page 1334,1337
macro_rules! GPIOC_PDOR   {() => (0x400FF080 as *mut u32);} // GPIOC_PDOR - page 1334,1335

extern "C" {
    static mut _sflashdata: u32;
    static mut _sdata: u32;
    static mut _edata: u32;
    static mut _sbss: u32;
    static mut _ebss: u32;
    fn _estack();
}

#[link_section=".vectors"]
#[allow(non_upper_case_globals)]
#[no_mangle]
pub static ISRVectors: [Option<unsafe extern "C" fn()>; 16] = [Some(_estack), // Stack pointer
                                                               Some(startup), // Reset
                                                               Some(isr_nmi), // NMI
                                                               Some(isr_hardfault), // Hard Fault
                                                               Some(isr_mmfault), /* CM3 Memory Management Fault */
                                                               Some(isr_busfault), /* CM3 Bus Fault */
                                                               Some(isr_usagefault), /* CM3 Usage Fault */
                                                               Some(isr_reserved_1), /* Reserved - Used as NXP Checksum */
                                                               None, // Reserved
                                                               None, // Reserved
                                                               None, // Reserved
                                                               Some(isr_svcall), // SVCall
                                                               Some(isr_debugmon), /* Reserved for debug */
                                                               None, // Reserved
                                                               Some(isr_pendsv), // PendSV
                                                               Some(isr_systick) /* SysTick */];

#[link_section=".flashconfig"]
#[allow(non_upper_case_globals)]
#[no_mangle]
pub static flashconfigbytes: [usize; 4] = [0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE];

pub unsafe extern "C" fn startup() {
    let mut src: *mut u32 = &mut _sflashdata;
    let mut dest: *mut u32 = &mut _sdata;

    volatile_store(WDOG_UNLOCK!(), 0xC520);
    volatile_store(WDOG_UNLOCK!(), 0xD928);
    volatile_store(WDOG_STCTRLH!(), 0x01D2);

    while dest < &mut _edata as *mut u32 {
        *dest = *src;
        dest = ((dest as u32) + 4) as *mut u32;
        src = ((src as u32) + 4) as *mut u32;
    }

    dest = &mut _sbss as *mut u32;

    while dest < &mut _edata as *mut u32 {
        *dest = 0;
        dest = ((dest as u32) + 4) as *mut u32;
    }

    // Enable system clock on all GPIO ports - page 254
    *GPIO_CONFIG!() = 0x00043F82; // 0b1000011111110000010
    // Configure the led pin
    *PORTC_PCR5!() = 0x00000143; // Enables GPIO | DSE | PULL_ENABLE | PULL_SELECT - page 227
    // Set the led pin to output
    *GPIOC_PDDR!() = 0x20; // pin 5 on port c

    rust_loop();
}

pub fn led_on() {
    unsafe {
        volatile_store(GPIOC_PDOR!(), 0x20);
    }
}

pub fn led_off() {
    unsafe {
        volatile_store(GPIOC_PDOR!(), 0x0);
    }
}

pub fn delay(ms: i32) {
    for _ in 0..ms * 250 {
        unsafe {
            asm!("NOP");
        }
    }
}

pub fn rust_loop() {
    loop {
        led_on();
        delay(1000);
        led_off();
        delay(1000);
    }
}

#[start]
fn lang_start(_: isize, _: *const *const u8) -> isize {
    unsafe {
        startup();
    }
    0
}

pub unsafe extern "C" fn isr_nmi() {
    loop {}
}
pub unsafe extern "C" fn isr_hardfault() {
    loop {}
}
pub unsafe extern "C" fn isr_mmfault() {
    loop {}
}
pub unsafe extern "C" fn isr_busfault() {
    loop {}
}
pub unsafe extern "C" fn isr_usagefault() {
    loop {}
}
pub unsafe extern "C" fn isr_reserved_1() {
    loop {}
}
pub unsafe extern "C" fn isr_svcall() {
    loop {}
}
pub unsafe extern "C" fn isr_debugmon() {
    loop {}
}
pub unsafe extern "C" fn isr_pendsv() {
    loop {}
}
pub unsafe extern "C" fn isr_systick() {
    loop {}
}
<commit_msg>Recallibrate delay() for release mode.<commit_after>#![feature(lang_items,core_intrinsics,asm,start)]
#![no_std]
#![crate_type="staticlib"]

use core::intrinsics::volatile_store;

#[lang="eh_personality"]
extern "C" fn eh_personality() {}
#[lang="panic_fmt"]
#[no_mangle]
pub extern "C" fn rust_begin_unwind(_fmt: &core::fmt::Arguments,
                                    _file_line: &(&'static str, usize))
                                    -> ! {
    loop {}
}

#[no_mangle]
pub extern "C" fn __aeabi_unwind_cpp_pr0() -> () {
    loop {}
}

#[no_mangle]
pub extern "C" fn __aeabi_unwind_cpp_pr1() -> () {
    loop {}
}

macro_rules! GPIOC_PDOR   {() => (0x400FF080 as *mut u32);} // GPIOC_PDOR - page 1334,1335
macro_rules! WDOG_UNLOCK  {() => (0x4005200E as *mut u16);} // Watchdog Unlock register
macro_rules! WDOG_STCTRLH {() => (0x40052000 as *mut u16);} // Watchdog Status and Control Register High
macro_rules! GPIO_CONFIG  {() => (0x40048038 as *mut u32);}
macro_rules! PORTC_PCR5   {() => (0x4004B014 as *mut u32);} // PORTC_PCR5 - page 223/227
macro_rules! GPIOC_PDDR   {() => (0x400FF094 as *mut u32);} // GPIOC_PDDR - page 1334,1337
macro_rules! GPIOC_PDOR   {() => (0x400FF080 as *mut u32);} // GPIOC_PDOR - page 1334,1335

extern "C" {
    static mut _sflashdata: u32;
    static mut _sdata: u32;
    static mut _edata: u32;
    static mut _sbss: u32;
    static mut _ebss: u32;
    fn _estack();
}

#[link_section=".vectors"]
#[allow(non_upper_case_globals)]
#[no_mangle]
pub static ISRVectors: [Option<unsafe extern "C" fn()>; 16] = [Some(_estack), // Stack pointer
                                                               Some(startup), // Reset
                                                               Some(isr_nmi), // NMI
                                                               Some(isr_hardfault), // Hard Fault
                                                               Some(isr_mmfault), /* CM3 Memory Management Fault */
                                                               Some(isr_busfault), /* CM3 Bus Fault */
                                                               Some(isr_usagefault), /* CM3 Usage Fault */
                                                               Some(isr_reserved_1), /* Reserved - Used as NXP Checksum */
                                                               None, // Reserved
                                                               None, // Reserved
                                                               None, // Reserved
                                                               Some(isr_svcall), // SVCall
                                                               Some(isr_debugmon), /* Reserved for debug */
                                                               None, // Reserved
                                                               Some(isr_pendsv), // PendSV
                                                               Some(isr_systick) /* SysTick */];

#[link_section=".flashconfig"]
#[allow(non_upper_case_globals)]
#[no_mangle]
pub static flashconfigbytes: [usize; 4] = [0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE];

pub unsafe extern "C" fn startup() {
    let mut src: *mut u32 = &mut _sflashdata;
    let mut dest: *mut u32 = &mut _sdata;

    volatile_store(WDOG_UNLOCK!(), 0xC520);
    volatile_store(WDOG_UNLOCK!(), 0xD928);
    volatile_store(WDOG_STCTRLH!(), 0x01D2);

    while dest < &mut _edata as *mut u32 {
        *dest = *src;
        dest = ((dest as u32) + 4) as *mut u32;
        src = ((src as u32) + 4) as *mut u32;
    }

    dest = &mut _sbss as *mut u32;

    while dest < &mut _edata as *mut u32 {
        *dest = 0;
        dest = ((dest as u32) + 4) as *mut u32;
    }

    // Enable system clock on all GPIO ports - page 254
    *GPIO_CONFIG!() = 0x00043F82; // 0b1000011111110000010
    // Configure the led pin
    *PORTC_PCR5!() = 0x00000143; // Enables GPIO | DSE | PULL_ENABLE | PULL_SELECT - page 227
    // Set the led pin to output
    *GPIOC_PDDR!() = 0x20; // pin 5 on port c

    rust_loop();
}

pub fn led_on() {
    unsafe {
        volatile_store(GPIOC_PDOR!(), 0x20);
    }
}

pub fn led_off() {
    unsafe {
        volatile_store(GPIOC_PDOR!(), 0x0);
    }
}

pub fn delay(ms: u32) {
    for _ in 0..ms {
        for _ in 0..7200 {
            unsafe {
                asm!("NOP");
            }
        }
    }
}

pub fn rust_loop() {
    const CYCLE: u32 = 1000;
    const ON: u32 = 20;
    loop {
        led_on();
        delay(ON);
        led_off();
        delay(CYCLE - ON);
    }
}

#[start]
fn lang_start(_: isize, _: *const *const u8) -> isize {
    unsafe {
        startup();
    }
    0
}

pub unsafe extern "C" fn isr_nmi() {
    loop {}
}
pub unsafe extern "C" fn isr_hardfault() {
    loop {}
}
pub unsafe extern "C" fn isr_mmfault() {
    loop {}
}
pub unsafe extern "C" fn isr_busfault() {
    loop {}
}
pub unsafe extern "C" fn isr_usagefault() {
    loop {}
}
pub unsafe extern "C" fn isr_reserved_1() {
    loop {}
}
pub unsafe extern "C" fn isr_svcall() {
    loop {}
}
pub unsafe extern "C" fn isr_debugmon() {
    loop {}
}
pub unsafe extern "C" fn isr_pendsv() {
    loop {}
}
pub unsafe extern "C" fn isr_systick() {
    loop {}
}
<|endoftext|>


<commit_before>use std::cell::Cell;

struct Coordinates {
    x: Cell<i32>,
    y: Cell<i32>,
}

fn main() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(0) };
    let bike_two = Coordinates { x: Cell::new(0), y: Cell::new(0) };
    let mut one_pos = vec![];
    let mut two_pos = vec![];
    let mut all_pos = vec![];

    move_up(&bike_one.y);
    move_up(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_down(&bike_one.y);
    move_down(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_right(&bike_one.x);
    move_left(&bike_two.x);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_left(&bike_one.x);
    move_left(&bike_two.x);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    println!("Bike One");
    println!("X is {:?}, Y is {:?}", bike_one.x, bike_one.y);
    println!("{:?}", one_pos);

    println!("Bike Two");
    println!("X is {:?}, Y is {:?}", bike_two.x, bike_two.y);
    println!("{:?}", two_pos);

    println!("Final combined positions are: {:?}", all_pos)

}

fn add_positions<'a>(v_cc: &'a mut Vec<i32>, y: &Cell<i32>, x: &Cell<i32>) -> &'a mut Vec<i32> {
    v_cc.push(x.get());
    v_cc.push(y.get());
    v_cc
}

fn combined_positions<'a>(a_p: &'a mut Vec<i32>, o_p: &mut Vec<i32>, t_p: &mut Vec<i32>) -> &'a mut Vec<i32> {
    a_p.extend_from_slice(o_p);
    a_p.extend_from_slice(t_p);
    a_p
}

fn move_up(y_cord: &Cell<i32>) -> &Cell<i32> {
    y_cord.set(y_cord.get() + 1);
    y_cord
}

fn move_down(y_cord: &Cell<i32>) -> &Cell<i32> {
    y_cord.set(y_cord.get() - 1);
    y_cord
}

fn move_right(x_cord: &Cell<i32>) -> &Cell<i32> {
    x_cord.set(x_cord.get() + 1);
    x_cord
}

fn move_left(x_cord: &Cell<i32>) -> &Cell<i32> {
    x_cord.set(x_cord.get() - 1);
    x_cord
}

#[test]
fn it_can_move() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(0) };
    let mut one_pos = vec![];

    // test it starts at 0

    assert_eq!(0, bike_one.y.get());

    // test it can move up one and can add positions to the vector

    move_up(&bike_one.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);

    assert_eq!(1, bike_one.y.get());
    assert_eq!(0, one_pos[0]);
    assert_eq!(1, one_pos[1]);

    // test it can continue to move up and theat move logic is valid

    move_up(&bike_one.y);
    move_up(&bike_one.y);
    move_up(&bike_one.y);

    assert_eq!(4, bike_one.y.get());

    for _ in 0..19 { // _ instead of x so that rust does not complain about x not being used
        move_up(&bike_one.y); // moves up 19 times
    }

    assert_eq!(23, bike_one.y.get());

    // test it can move down

    for _ in 0..19 {
        move_down(&bike_one.y);
    }

    assert_eq!(4, bike_one.y.get());

    // test it can move right

    for _ in 0..19 {
        move_right(&bike_one.x);
    }

    assert_eq!(19, bike_one.x.get());

    // test it can move left

    for _ in 0..10 {
        move_left(&bike_one.x);
    }

    assert_eq!(9, bike_one.x.get());
}
<commit_msg>players start<commit_after>use std::cell::Cell;

struct Coordinates {
    x: Cell<i32>,
    y: Cell<i32>,
}

fn main() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(50) };
    let bike_two = Coordinates { x: Cell::new(100), y: Cell::new(50) };
    let mut one_pos = vec![];
    let mut two_pos = vec![];
    let mut all_pos = vec![];

    move_up(&bike_one.y);
    move_up(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_down(&bike_one.y);
    move_down(&bike_two.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_right(&bike_one.x);
    move_left(&bike_two.x);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    move_left(&bike_one.x);
    move_left(&bike_two.x);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);
    add_positions(&mut two_pos, &bike_two.y, &bike_two.x);
    combined_positions(&mut all_pos, &mut one_pos, &mut two_pos);

    println!("Bike One");
    println!("X is {:?}, Y is {:?}", bike_one.x, bike_one.y);
    println!("{:?}", one_pos);

    println!("Bike Two");
    println!("X is {:?}, Y is {:?}", bike_two.x, bike_two.y);
    println!("{:?}", two_pos);

    println!("Final combined positions are: {:?}", all_pos)

}

fn add_positions<'a>(v_cc: &'a mut Vec<i32>, y: &Cell<i32>, x: &Cell<i32>) -> &'a mut Vec<i32> {
    v_cc.push(x.get());
    v_cc.push(y.get());
    v_cc
}

fn combined_positions<'a>(a_p: &'a mut Vec<i32>, o_p: &mut Vec<i32>, t_p: &mut Vec<i32>) -> &'a mut Vec<i32> {
    a_p.extend_from_slice(o_p);
    a_p.extend_from_slice(t_p);
    a_p
}

fn move_up(y_cord: &Cell<i32>) -> &Cell<i32> {
    y_cord.set(y_cord.get() + 1);
    y_cord
}

fn move_down(y_cord: &Cell<i32>) -> &Cell<i32> {
    y_cord.set(y_cord.get() - 1);
    y_cord
}

fn move_right(x_cord: &Cell<i32>) -> &Cell<i32> {
    x_cord.set(x_cord.get() + 1);
    x_cord
}

fn move_left(x_cord: &Cell<i32>) -> &Cell<i32> {
    x_cord.set(x_cord.get() - 1);
    x_cord
}

#[test]
fn it_can_move() {
    let bike_one = Coordinates { x: Cell::new(0), y: Cell::new(0) };
    let mut one_pos = vec![];

    // test it starts at 0

    assert_eq!(0, bike_one.y.get());

    // test it can move up one and can add positions to the vector

    move_up(&bike_one.y);
    add_positions(&mut one_pos, &bike_one.y, &bike_one.x);

    assert_eq!(1, bike_one.y.get());
    assert_eq!(0, one_pos[0]);
    assert_eq!(1, one_pos[1]);

    // test it can continue to move up and theat move logic is valid

    move_up(&bike_one.y);
    move_up(&bike_one.y);
    move_up(&bike_one.y);

    assert_eq!(4, bike_one.y.get());

    for _ in 0..19 { // _ instead of x so that rust does not complain about x not being used
        move_up(&bike_one.y); // moves up 19 times
    }

    assert_eq!(23, bike_one.y.get());

    // test it can move down

    for _ in 0..19 {
        move_down(&bike_one.y);
    }

    assert_eq!(4, bike_one.y.get());

    // test it can move right

    for _ in 0..19 {
        move_right(&bike_one.x);
    }

    assert_eq!(19, bike_one.x.get());

    // test it can move left

    for _ in 0..10 {
        move_left(&bike_one.x);
    }

    assert_eq!(9, bike_one.x.get());
}
<|endoftext|>


<commit_before>// Copyright 2015 click2stream, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Arrow Client definitions.

pub mod cmd_handler;
pub mod config;
pub mod context;
pub mod futures_ex;
pub mod net;
pub mod runtime;
pub mod scanner;
pub mod svc_table;
pub mod utils;

use std::process;

use std::error::Error;
use std::fmt::Debug;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};

use futures::{Future, Stream};

use tokio::timer::{Delay, Interval};

use crate::net::arrow;

use crate::cmd_handler::{Command, CommandChannel};
use crate::config::ApplicationConfig;
use crate::context::{ApplicationContext, ConnectionState};
use crate::net::arrow::{ArrowError, ErrorKind};
use crate::utils::logger::{BoxLogger, Logger};

use crate::config::usage;

/// Connectionn retry timeout.
const RETRY_TIMEOUT: f64 = 60.0;

/// Get maximum duration of the pairing mode.
const PAIRING_MODE_TIMEOUT: f64 = 1200.0;

/// Unwrap a given result (if possible) or print the error message and exit
/// the process printing application usage.
fn result_or_usage<T, E>(res: Result<T, E>) -> T
where
    E: Error + Debug,
{
    match res {
        Ok(res) => res,
        Err(err) => {
            println!("ERROR: {}\n", err);
            usage(1);
        }
    }
}

/// This future ensures maintaining connection with a remote Arrow Service.
struct ArrowMainTask {
    app_context: ApplicationContext,
    cmd_channel: CommandChannel,
    logger: BoxLogger,
    default_addr: String,
    current_addr: String,
    last_attempt: f64,
    pairing_mode_timeout: f64,
    diagnostic_mode: bool,
}

impl ArrowMainTask {
    /// Create a new task.
    fn new(
        app_context: ApplicationContext,
        cmd_channel: CommandChannel,
    ) -> impl Future<Item = (), Error = ()> {
        let logger = app_context.get_logger();
        let addr = app_context.get_arrow_service_address();
        let diagnostic_mode = app_context.get_diagnostic_mode();

        let t = time::precise_time_s();

        let pairing_mode_timeout = t + PAIRING_MODE_TIMEOUT;

        let task = ArrowMainTask {
            app_context: app_context,
            cmd_channel: cmd_channel,
            logger: logger,
            default_addr: addr.clone(),
            current_addr: addr,
            last_attempt: t,
            pairing_mode_timeout: pairing_mode_timeout,
            diagnostic_mode: diagnostic_mode,
        };

        let task = Arc::new(Mutex::new(task));

        let connector = task.clone();
        let rhandler = task;

        futures::stream::repeat(())
            .and_then(move |_| connector.lock().unwrap().connect())
            .then(move |res| rhandler.lock().unwrap().process_result(res))
            .for_each(|_| Ok(()))
    }

    /// Connect to the Arrow service.
    fn connect(&mut self) -> impl Future<Item = String, Error = ArrowError> {
        log_info!(
            &mut self.logger,
            "connecting to remote Arrow Service {}",
            self.current_addr
        );

        self.last_attempt = time::precise_time_s();

        self.app_context
            .set_connection_state(ConnectionState::Connected);

        arrow::connect(
            self.app_context.clone(),
            self.cmd_channel.clone(),
            &self.current_addr,
        )
    }

    /// Process a given connection result.
    fn process_result(
        &mut self,
        res: Result<String, ArrowError>,
    ) -> impl Future<Item = (), Error = ()> {
        if self.diagnostic_mode {
            diagnose_connection_result(&res);
        } else if let Ok(addr) = res {
            // set redirection
            self.current_addr = addr;

            Box::new(futures::future::ok(()))
        } else if let Err(err) = res {
            if err.kind() == ErrorKind::Unauthorized {
                log_info!(
                    &mut self.logger,
                    "connection rejected by the remote service {}; is the client paired?",
                    self.current_addr
                );
            } else {
                log_warn!(&mut self.logger, "{}", err.description());
            }

            let cstate = match err.kind() {
                ErrorKind::Unauthorized => ConnectionState::Unauthorized,
                _ => ConnectionState::Disconnected,
            };

            self.app_context.set_connection_state(cstate);

            let retry = process_connection_error(err, self.last_attempt, self.pairing_mode_timeout);

            self.current_addr = self.default_addr.clone();

            wait_for_retry(&mut self.logger, retry)
        } else {
            panic!("unexpected Result variant")
        }
    }
}

/// Connection retry variants. There are only two options - the connection can
/// be either retried after a specified timeout or there should be no more
/// connection attempts because of a specified reason.
#[derive(Debug, Copy, Clone)]
enum ConnectionRetry {
    Timeout(f64),
    Suspend(SuspendReason),
}

/// Reason for suspending the Arrow connection thread.
#[derive(Debug, Copy, Clone)]
enum SuspendReason {
    NotInPairingMode,
    UnsupportedProtocolVersion,
}

impl SuspendReason {
    fn to_string(&self) -> &str {
        match *self {
            SuspendReason::NotInPairingMode => "pairing window timeout",
            SuspendReason::UnsupportedProtocolVersion => "unsupported protocol version",
        }
    }
}

/// Process a given connection error and return a ConnectionRetry instance.
fn process_connection_error(
    connection_error: ArrowError,
    last_attempt: f64,
    pairing_mode_timeout: f64,
) -> ConnectionRetry {
    let t = time::precise_time_s();

    match connection_error.kind() {
        // the client is not authorized to access the service yet; check the
        // pairing mode timeout
        ErrorKind::Unauthorized => match pairing_mode_timeout {
            // retry every 10 seconds in the first 10 minutes since the first
            // "unauthorized" response
            timeout if t < (timeout - 600.0) => ConnectionRetry::Timeout(10.0),
            // retry every 30 seconds after the first 10 minutes since the
            // first "unauthorized" response
            timeout if t < timeout => ConnectionRetry::Timeout(30.0),
            // suspend the thread after the first 20 minutes since the client
            // thread start
            _ => ConnectionRetry::Suspend(SuspendReason::NotInPairingMode),
        },
        // suspend the thread if the version of the Arrow Protocol is not
        // supported by either side
        ErrorKind::UnsupportedProtocolVersion => {
            ConnectionRetry::Suspend(SuspendReason::UnsupportedProtocolVersion)
        }
        // in all other cases
        _ => ConnectionRetry::Timeout(RETRY_TIMEOUT + last_attempt - t),
    }
}

/// Process a given connection retry object.
fn wait_for_retry(
    logger: &mut Logger,
    connection_retry: ConnectionRetry,
) -> Box<Future<Item = (), Error = ()> + Send + Sync> {
    match connection_retry {
        ConnectionRetry::Timeout(t) if t > 0.5 => {
            log_info!(logger, "retrying in {:.3} seconds", t);

            let time = Duration::from_millis((t * 1000.0) as u64);
            let sleep = Delay::new(Instant::now() + time).map_err(|_| ());

            Box::new(sleep)
        }
        ConnectionRetry::Timeout(_) => Box::new(futures::future::ok(())),
        ConnectionRetry::Suspend(reason) => {
            log_info!(logger, "{}", reason.to_string());
            log_info!(logger, "suspending the connection thread");

            Box::new(futures::future::empty())
        }
    }
}

/// Diagnose a given connection result and exit with exit code 0 if the
/// connection was successful or the server responded with UNAUTHORIZED,
/// otherwise exit with exit code 1.
fn diagnose_connection_result(connection_result: &Result<String, ArrowError>) -> ! {
    match connection_result {
        &Ok(_) => process::exit(0),
        &Err(ref err) => match err.kind() {
            ErrorKind::Unauthorized => process::exit(0),
            _ => process::exit(1),
        },
    }
}

/// Arrow Client main function.
fn main() {
    let config = result_or_usage(ApplicationConfig::create());

    let context = ApplicationContext::new(config);

    let mut logger = context.get_logger();

    log_info!(
        &mut logger,
        "application started (uuid: {}, mac: {})",
        context.get_arrow_uuid(),
        context.get_arrow_mac_address()
    );

    // create command handler
    let (tx, rx) = cmd_handler::new(context.clone());

    let cmd_channel = tx.clone();

    // create Arrow client main task
    let arrow_main_task = ArrowMainTask::new(context, cmd_channel);

    let interval = Duration::from_millis(1000);

    // schedule periodic network scan
    let periodic_network_scan = Interval::new(Instant::now() + interval, interval)
        .for_each(move |_| {
            tx.send(Command::PeriodicNetworkScan);

            Ok(())
        })
        .map_err(|_| ());

    runtime::run(futures::future::lazy(|| {
        tokio::spawn(rx);
        tokio::spawn(periodic_network_scan);

        arrow_main_task
    }));
}
<commit_msg>Fix macro imports<commit_after>// Copyright 2015 click2stream, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Arrow Client definitions.

#[macro_use]
extern crate futures;

#[macro_use]
extern crate json;

#[cfg(feature = "discovery")]
#[macro_use]
extern crate lazy_static;

#[macro_use]
pub mod utils;

pub mod cmd_handler;
pub mod config;
pub mod context;
pub mod futures_ex;
pub mod net;
pub mod runtime;
pub mod scanner;
pub mod svc_table;

use std::process;

use std::error::Error;
use std::fmt::Debug;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};

use futures::{Future, Stream};

use tokio::timer::{Delay, Interval};

use crate::net::arrow;

use crate::cmd_handler::{Command, CommandChannel};
use crate::config::ApplicationConfig;
use crate::context::{ApplicationContext, ConnectionState};
use crate::net::arrow::{ArrowError, ErrorKind};
use crate::utils::logger::{BoxLogger, Logger};

use crate::config::usage;

/// Connectionn retry timeout.
const RETRY_TIMEOUT: f64 = 60.0;

/// Get maximum duration of the pairing mode.
const PAIRING_MODE_TIMEOUT: f64 = 1200.0;

/// Unwrap a given result (if possible) or print the error message and exit
/// the process printing application usage.
fn result_or_usage<T, E>(res: Result<T, E>) -> T
where
    E: Error + Debug,
{
    match res {
        Ok(res) => res,
        Err(err) => {
            println!("ERROR: {}\n", err);
            usage(1);
        }
    }
}

/// This future ensures maintaining connection with a remote Arrow Service.
struct ArrowMainTask {
    app_context: ApplicationContext,
    cmd_channel: CommandChannel,
    logger: BoxLogger,
    default_addr: String,
    current_addr: String,
    last_attempt: f64,
    pairing_mode_timeout: f64,
    diagnostic_mode: bool,
}

impl ArrowMainTask {
    /// Create a new task.
    fn new(
        app_context: ApplicationContext,
        cmd_channel: CommandChannel,
    ) -> impl Future<Item = (), Error = ()> {
        let logger = app_context.get_logger();
        let addr = app_context.get_arrow_service_address();
        let diagnostic_mode = app_context.get_diagnostic_mode();

        let t = time::precise_time_s();

        let pairing_mode_timeout = t + PAIRING_MODE_TIMEOUT;

        let task = ArrowMainTask {
            app_context: app_context,
            cmd_channel: cmd_channel,
            logger: logger,
            default_addr: addr.clone(),
            current_addr: addr,
            last_attempt: t,
            pairing_mode_timeout: pairing_mode_timeout,
            diagnostic_mode: diagnostic_mode,
        };

        let task = Arc::new(Mutex::new(task));

        let connector = task.clone();
        let rhandler = task;

        futures::stream::repeat(())
            .and_then(move |_| connector.lock().unwrap().connect())
            .then(move |res| rhandler.lock().unwrap().process_result(res))
            .for_each(|_| Ok(()))
    }

    /// Connect to the Arrow service.
    fn connect(&mut self) -> impl Future<Item = String, Error = ArrowError> {
        log_info!(
            &mut self.logger,
            "connecting to remote Arrow Service {}",
            self.current_addr
        );

        self.last_attempt = time::precise_time_s();

        self.app_context
            .set_connection_state(ConnectionState::Connected);

        arrow::connect(
            self.app_context.clone(),
            self.cmd_channel.clone(),
            &self.current_addr,
        )
    }

    /// Process a given connection result.
    fn process_result(
        &mut self,
        res: Result<String, ArrowError>,
    ) -> impl Future<Item = (), Error = ()> {
        if self.diagnostic_mode {
            diagnose_connection_result(&res);
        } else if let Ok(addr) = res {
            // set redirection
            self.current_addr = addr;

            Box::new(futures::future::ok(()))
        } else if let Err(err) = res {
            if err.kind() == ErrorKind::Unauthorized {
                log_info!(
                    &mut self.logger,
                    "connection rejected by the remote service {}; is the client paired?",
                    self.current_addr
                );
            } else {
                log_warn!(&mut self.logger, "{}", err.description());
            }

            let cstate = match err.kind() {
                ErrorKind::Unauthorized => ConnectionState::Unauthorized,
                _ => ConnectionState::Disconnected,
            };

            self.app_context.set_connection_state(cstate);

            let retry = process_connection_error(err, self.last_attempt, self.pairing_mode_timeout);

            self.current_addr = self.default_addr.clone();

            wait_for_retry(&mut self.logger, retry)
        } else {
            panic!("unexpected Result variant")
        }
    }
}

/// Connection retry variants. There are only two options - the connection can
/// be either retried after a specified timeout or there should be no more
/// connection attempts because of a specified reason.
#[derive(Debug, Copy, Clone)]
enum ConnectionRetry {
    Timeout(f64),
    Suspend(SuspendReason),
}

/// Reason for suspending the Arrow connection thread.
#[derive(Debug, Copy, Clone)]
enum SuspendReason {
    NotInPairingMode,
    UnsupportedProtocolVersion,
}

impl SuspendReason {
    fn to_string(&self) -> &str {
        match *self {
            SuspendReason::NotInPairingMode => "pairing window timeout",
            SuspendReason::UnsupportedProtocolVersion => "unsupported protocol version",
        }
    }
}

/// Process a given connection error and return a ConnectionRetry instance.
fn process_connection_error(
    connection_error: ArrowError,
    last_attempt: f64,
    pairing_mode_timeout: f64,
) -> ConnectionRetry {
    let t = time::precise_time_s();

    match connection_error.kind() {
        // the client is not authorized to access the service yet; check the
        // pairing mode timeout
        ErrorKind::Unauthorized => match pairing_mode_timeout {
            // retry every 10 seconds in the first 10 minutes since the first
            // "unauthorized" response
            timeout if t < (timeout - 600.0) => ConnectionRetry::Timeout(10.0),
            // retry every 30 seconds after the first 10 minutes since the
            // first "unauthorized" response
            timeout if t < timeout => ConnectionRetry::Timeout(30.0),
            // suspend the thread after the first 20 minutes since the client
            // thread start
            _ => ConnectionRetry::Suspend(SuspendReason::NotInPairingMode),
        },
        // suspend the thread if the version of the Arrow Protocol is not
        // supported by either side
        ErrorKind::UnsupportedProtocolVersion => {
            ConnectionRetry::Suspend(SuspendReason::UnsupportedProtocolVersion)
        }
        // in all other cases
        _ => ConnectionRetry::Timeout(RETRY_TIMEOUT + last_attempt - t),
    }
}

/// Process a given connection retry object.
fn wait_for_retry(
    logger: &mut Logger,
    connection_retry: ConnectionRetry,
) -> Box<Future<Item = (), Error = ()> + Send + Sync> {
    match connection_retry {
        ConnectionRetry::Timeout(t) if t > 0.5 => {
            log_info!(logger, "retrying in {:.3} seconds", t);

            let time = Duration::from_millis((t * 1000.0) as u64);
            let sleep = Delay::new(Instant::now() + time).map_err(|_| ());

            Box::new(sleep)
        }
        ConnectionRetry::Timeout(_) => Box::new(futures::future::ok(())),
        ConnectionRetry::Suspend(reason) => {
            log_info!(logger, "{}", reason.to_string());
            log_info!(logger, "suspending the connection thread");

            Box::new(futures::future::empty())
        }
    }
}

/// Diagnose a given connection result and exit with exit code 0 if the
/// connection was successful or the server responded with UNAUTHORIZED,
/// otherwise exit with exit code 1.
fn diagnose_connection_result(connection_result: &Result<String, ArrowError>) -> ! {
    match connection_result {
        &Ok(_) => process::exit(0),
        &Err(ref err) => match err.kind() {
            ErrorKind::Unauthorized => process::exit(0),
            _ => process::exit(1),
        },
    }
}

/// Arrow Client main function.
fn main() {
    let config = result_or_usage(ApplicationConfig::create());

    let context = ApplicationContext::new(config);

    let mut logger = context.get_logger();

    log_info!(
        &mut logger,
        "application started (uuid: {}, mac: {})",
        context.get_arrow_uuid(),
        context.get_arrow_mac_address()
    );

    // create command handler
    let (tx, rx) = cmd_handler::new(context.clone());

    let cmd_channel = tx.clone();

    // create Arrow client main task
    let arrow_main_task = ArrowMainTask::new(context, cmd_channel);

    let interval = Duration::from_millis(1000);

    // schedule periodic network scan
    let periodic_network_scan = Interval::new(Instant::now() + interval, interval)
        .for_each(move |_| {
            tx.send(Command::PeriodicNetworkScan);

            Ok(())
        })
        .map_err(|_| ());

    runtime::run(futures::future::lazy(|| {
        tokio::spawn(rx);
        tokio::spawn(periodic_network_scan);

        arrow_main_task
    }));
}
<|endoftext|>


<commit_before>extern crate image;

use std::env::args;
use std::process::exit;
use std::fs::File;
use std::path::Path;
use image::GenericImage;

fn get_top_left(in_path: &str) -> u32 {
	let im = image::open(&Path::new(in_path)).unwrap();
	for x in 0..(im.dimensions().1) {
		for y in 0..(im.dimensions().0) {
			let col = im.get_pixel(y, x);
			if col[0] != 255 && col[1] != 255 && col[2] != 255 {
				return x;
			}
		}
	}
	unreachable!();
}

fn get_top_right(in_path: &str) -> u32 {
	let im = image::open(&Path::new(in_path)).unwrap();
	for x in 0..(im.dimensions().0) {
		for y in 0..(im.dimensions().1) {
			let col = im.get_pixel(x, y);
			if col[0] != 255 && col[1] != 255 && col[2] != 255 {
				return x;
			}
		}
	}
	unreachable!();
}

fn get_lower_left(in_path: &str) -> u32 {
	let im = image::open(&Path::new(in_path)).unwrap();
	let mut x = im.dimensions().1 as i32 - 1;
	// Using while loop as there is no reliable way
	// to use custom steps in range() currently
	while x >= 0 {
		let mut y = im.dimensions().0 as i32 - 1;
		while y >= 0 {
			let col = im.get_pixel(y as u32, x as u32);
			if col[0] != 255 && col[1] != 255 && col[2] != 255 {
				return x as u32 + 1;
			}
			y -= 1;
		}
		x -= 1;
	}
	unreachable!();
}

fn get_lower_right(in_path: &str) -> u32 {
	let im = image::open(&Path::new(in_path)).unwrap();
	let mut x = im.dimensions().0 as i32 - 1;
	// Using while loop as there is no reliable way
	// to use custom steps in range() currently
	while x >= 0 {
		let mut y = im.dimensions().1 as i32 - 1;
		while y >= 0 {
			let col = im.get_pixel(x as u32, y as u32);
			if col[0] != 255 && col[1] != 255 && col[2] != 255 {
				return x as u32 + 1;
			}
			y -= 1;
		}
		x -= 1;
	}
	unreachable!();
}

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

	let (in_path, out_path) = if args.len() == 3 {
		(args[1].as_str(), args[2].as_str())
	} else {
		println!("usage: {} <input_image> <output_image>", args[0]);
		exit(1)
	};

	// Top left corner
	let (b, a) = (get_top_left(in_path), get_top_right(in_path));
	// Lower right corner
	let (y, x) = (get_lower_left(in_path), get_lower_right(in_path));

	println!("Cropping area ({0}, {1}, {2}, {3}) from {4} to {5}",
	a, b, x, y, in_path, out_path);

	let mut im = image::open(&Path::new(in_path)).unwrap();
	let subim = im.crop(a, b, x - a, y - b);

	let ref mut fout = File::create(&Path::new(out_path)).unwrap();

	let _ = subim.save(fout, image::PNG).unwrap();
}
<commit_msg>Show correct coordinates<commit_after>extern crate image;

use std::env::args;
use std::process::exit;
use std::fs::File;
use std::path::Path;
use image::GenericImage;

fn get_top_left(in_path: &str) -> u32 {
	let im = image::open(&Path::new(in_path)).unwrap();
	for x in 0..(im.dimensions().1) {
		for y in 0..(im.dimensions().0) {
			let col = im.get_pixel(y, x);
			if col[0] != 255 && col[1] != 255 && col[2] != 255 {
				return x;
			}
		}
	}
	unreachable!();
}

fn get_top_right(in_path: &str) -> u32 {
	let im = image::open(&Path::new(in_path)).unwrap();
	for x in 0..(im.dimensions().0) {
		for y in 0..(im.dimensions().1) {
			let col = im.get_pixel(x, y);
			if col[0] != 255 && col[1] != 255 && col[2] != 255 {
				return x;
			}
		}
	}
	unreachable!();
}

fn get_lower_left(in_path: &str) -> u32 {
	let im = image::open(&Path::new(in_path)).unwrap();
	let mut x = im.dimensions().1 as i32 - 1;
	// Using while loop as there is no reliable way
	// to use custom steps in range() currently
	while x >= 0 {
		let mut y = im.dimensions().0 as i32 - 1;
		while y >= 0 {
			let col = im.get_pixel(y as u32, x as u32);
			if col[0] != 255 && col[1] != 255 && col[2] != 255 {
				return x as u32 + 1;
			}
			y -= 1;
		}
		x -= 1;
	}
	unreachable!();
}

fn get_lower_right(in_path: &str) -> u32 {
	let im = image::open(&Path::new(in_path)).unwrap();
	let mut x = im.dimensions().0 as i32 - 1;
	// Using while loop as there is no reliable way
	// to use custom steps in range() currently
	while x >= 0 {
		let mut y = im.dimensions().1 as i32 - 1;
		while y >= 0 {
			let col = im.get_pixel(x as u32, y as u32);
			if col[0] != 255 && col[1] != 255 && col[2] != 255 {
				return x as u32 + 1;
			}
			y -= 1;
		}
		x -= 1;
	}
	unreachable!();
}

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

	let (in_path, out_path) = if args.len() == 3 {
		(args[1].as_str(), args[2].as_str())
	} else {
		println!("usage: {} <input_image> <output_image>", args[0]);
		exit(1)
	};

	// Top left corner
	let (b, a) = (get_top_left(in_path), get_top_right(in_path));
	// Lower right corner
	let (y, x) = (get_lower_left(in_path), get_lower_right(in_path));

	println!("Cropping area ({0}, {1}, {2}, {3}) from {4} to {5}",
	a, b, x, y, in_path, out_path);

	let mut im = image::open(&Path::new(in_path)).unwrap();
	let subim = im.crop(a, b, x - a, y - b);

	let ref mut fout = File::create(&Path::new(out_path)).unwrap();

	let _ = subim.save(fout, image::JPEG).unwrap();
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::io::prelude::*;
use std::env;
use std::fs::File;
use std::error::Error;
use std::default::Default;
use std::char;

mod tokenizer;      // Tokenizes files into words, sentences, and paragraphs.
mod calculator;     // Does all the

#[derive(Default, Copy, Clone)]
struct Metadata {
    word_total: f32,    // Intermediary for calculator.
    wordlen: f32,
    sentlen: f32,
    paralen: i32,
    comma: i32,
    semicolon: i32,
    quote: i32,
    bangs: i32,
    dashes: i32,
    ands: i32,
    buts: i32,
    however: i32,
    condition: i32,		// Prevent confusion with if.
    thats: i32,
    more: i32,
    musts: i32,
    mights: i32,
    thises: i32,
    very: i32,
}

fn main() {

    let mut off = Metadata {..Default::default()};
    let mut pseu = Metadata {..Default::default()};

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

    let mut file1 = match File::open(&args[1]) {
        Err(why) => panic!("Couldn't open {}: {}", &args[1], Error::description(&why)),
        Ok(file1) => file1,
    };
    let mut file2 = match File::open(&args[2]) {
        Err(why) => panic!("Couldn't open {}: {}", &args[2], Error::description(&why)),
        Ok(file2) => file2,
    };

    let (mut s1, mut s2) = (String::new(), String::new());

    match file1.read_to_string(&mut s1) {
        Err(why) => panic!("Couldn't read file1: {}", Error::description(&why)),
        Ok(_) => println!("File 1 read."),
    };

    match file2.read_to_string(&mut s2) {
        Err(why) => panic!("Couldn't read file2: {}", Error::description(&why)),
        Ok(_) => println!("File 2 read."),
    };

    let s1_token: Vec<&str> = tokenizer::word_token(&s1);
    let s2_token: Vec<&str> = tokenizer::word_token(&s2);
    off.word_total = calculator::num_words(&s1_token);
    pseu.word_total = calculator::num_words(&s2_token);
    off.wordlen = calculator::word_mean(&s1_token);
    pseu.wordlen = calculator::word_mean(&s2_token);
    println!("Mean word length #1: {}", off.wordlen);
    println!("Mean word length #2: {}", pseu.wordlen);

    let s1_sent: Vec<&str> = tokenizer::sent_token(&s1);
    let s2_sent: Vec<&str> = tokenizer::sent_token(&s2);
    off.sentlen = calculator::sent_mean(&off.word_total, &s1_sent);
    pseu.sentlen = calculator::sent_mean(&pseu.word_total, &s2_sent);
    println!("Mean sentence length #1: {}", off.sentlen);
    println!("Mean sentence length #2: {}", pseu.sentlen);

}<commit_msg>Started struct function design<commit_after>#![allow(dead_code)]

use std::io::prelude::*;
use std::env;
use std::fs::File;
use std::error::Error;
use std::default::Default;

mod tokenizer;      // Tokenizes files into words, sentences, and paragraphs.
mod calculator;     // Does all the calculations for stats

#[derive(Default, Copy, Clone)]
struct Metadata {
    word_total: f32,    // Intermediary for calculator.
    wordlen: f32,
    sentlen: f32,
    paralen: i32,
    comma: i32,
    semicolon: i32,
    quote: i32,
    bangs: i32,
    dashes: i32,
    ands: i32,
    buts: i32,
    however: i32,
    condition: i32,		// Prevent confusion with if.
    thats: i32,
    more: i32,
    musts: i32,
    mights: i32,
    thises: i32,
    very: i32,
}

impl Metadata {
    fn words(&mut self, s: Vec<&str>) {
        self.word_total = calculator::num_words(&s);
        self.wordlen = calculator::word_mean(&s);
        println!("Mean word length: {}", self.wordlen);
    }

    fn sents(&mut self, s: Vec<&str>) {
        self.sentlen = calculator::sent_mean(&self.word_total, &s);
        println!("Mean sentence length: {}", self.sentlen);
    }
}

fn main() {

    let mut off = Metadata {..Default::default()};
    let mut pseu = Metadata {..Default::default()};

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

    let mut file1 = match File::open(&args[1]) {
        Err(why) => panic!("Couldn't open {}: {}", &args[1], Error::description(&why)),
        Ok(file1) => file1,
    };
    let mut file2 = match File::open(&args[2]) {
        Err(why) => panic!("Couldn't open {}: {}", &args[2], Error::description(&why)),
        Ok(file2) => file2,
    };

    let (mut s1, mut s2) = (String::new(), String::new());

    match file1.read_to_string(&mut s1) {
        Err(why) => panic!("Couldn't read file1: {}", Error::description(&why)),
        Ok(_) => println!("File 1 read."),
    };

    match file2.read_to_string(&mut s2) {
        Err(why) => panic!("Couldn't read file2: {}", Error::description(&why)),
        Ok(_) => println!("File 2 read."),
    };

    let s1_token: Vec<&str> = tokenizer::word_token(&s1);
    let s2_token: Vec<&str> = tokenizer::word_token(&s2);
    let s1_sent: Vec<&str> = tokenizer::sent_token(&s1);
    let s2_sent: Vec<&str> = tokenizer::sent_token(&s2);
    off.words(s1_token);
    pseu.words(s2_token);
    off.sents(s1_sent);
    pseu.sents(s2_sent);

}<|endoftext|>