<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 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.4.0")
        .about(
"
XOR encrypt files or directories using a supplied key.

In it's simplest form, reads input from stdin, encrypts it against a key and writes the result to stdout.
The \"key\" option can be either a path to a file or a string of characters.

When the \"recursive\" option is used, files under a given directory are recursively encrypted.
Files are renamed by XORing the original name against the provided key, then hexifying the result.
To decrypt you must use the \"mode\" option with the value \"d\", files are then renamed by unhexifying then XORing.
")
        .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, and the \"recursive\" option isn't used, 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")
             .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"))
         .get_matches();

    // Parse the mode of operation, defaulting to encrypt mode.
    // The mode is used in conjunction with the "recursive" option and determines how file names
    // will be processed when renaming files.
    // When in "encrypt" mode, file names are XOR'd then hexified.
    // When in "decrypt" mode, file names are unhexified then XOR'd.
    let mode = match matches.value_of("mode").unwrap() {
        "e" => Mode::Encrypt,
        "d" => Mode::Decrypt,
        _ => Mode::Encrypt
    };

    // Read all the key bytes into memory.
    let key_bytes = get_key_bytes(&matches);

    if matches.is_present("recursive") {
        trace!("Recursively encrypting files and folders.");

        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 {

        let input : Box<Read> = if matches.is_present("input") {
            trace!("Reading input from a file.");
            Box::new(File::open(matches.value_of("input").unwrap()).unwrap())
        } else {
            trace!("Reading input from stdin.");
            Box::new(io::stdin())
        };

        let output : Box<Write> = if matches.is_present("output") {
            trace!("Writting output to a file.");
            Box::new(OpenOptions::new()
                .write(true)
                .create(true)
                .truncate(true)
                .open(matches.value_of("output").unwrap())
                .unwrap())
        } else {
            trace!("Writting output to stdout.");
            Box::new(stdout_writer::StdoutWriter{})
        };

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

/// XOR's all the bytes from reader against the provided key then writes the result to the output
/// writer.
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() {
        match item {
            Ok(entry) => xor_entry(&entry, key, mode),
            Err(err) => info!("Failed to read entry because: {}", err)
        }
    }
}

fn xor_entry(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    match entry.file_type() {
        Ok(entry_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);
            }
        },
        Err(err) => info!("Failed to get filetype for DirEntry {:?} because: {}", entry, err)
    }
}

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

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

            let output = OpenOptions::new()
                .write(true)
                .truncate(true)
                .open(entry.path());

            match output {
                Ok(mut writer) => {
                    match writer.write_all(cypher_text.as_slice()) {
                        Ok(_) => {},
                        Err(err) => info!("Failed to write encrypted bytes to file because: {}", err)
                    }
                },
                Err(err) => info!("Failed to open file with truncate option for DirEntry {:?} because: {}", entry, err)
            }
        },
        Err(err) => info!("Failed to open file for DirEntry {:?} because: {}", entry, err)
    }

    rename_entry(entry, key, mode);
}

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

    // TODO: Follow sym links

    rename_entry(entry, key, mode);
}

fn xor_dir(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    debug!("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());

        // If in Encrypt mode use the filename as is.
        // If in Decrypt mode unhexify the filename before getting it's bytes.
        let input_bytes = match *mode {
            Mode::Encrypt => original_name.to_string().into_bytes(),
            Mode::Decrypt => from_hex_string(String::from(original_name))
        };

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

        // If in Encrypt mode hexify the filename.
        // If in Decrypt mode just use the filename as is.
        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);

        match fs::rename(src_file_path, dst_file_path) {
            Ok(_) => {},
            Err(e) => info!("Failed to rename file because: {}", e)
        }
    }
}

/// 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>Minor refactoring and added some comments<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;

/// The mode is used in conjunction with the "recursive" option and determines how file names
/// will be processed when renaming files.
/// When in "encrypt" mode, file names are XOR'd then hexified.
/// When in "decrypt" mode, file names are unhexified then XOR'd.
enum Mode {
    Encrypt,
    Decrypt
}

static ABOUT: &str = "
XOR encrypt files or directories using a supplied key.

In it's simplest form, reads input from stdin, encrypts it against a key and writes the result to stdout.
The \"key\" option can be either a path to a file or a string of characters.

When the \"recursive\" option is used, files under a given directory are recursively encrypted.
Files are renamed by XORing the original name against the provided key, then hexifying the result.
To decrypt you must use the \"mode\" option with the value \"d\", files are then renamed by unhexifying then XORing.
";

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

    // Parse arguments and provide help.
    let matches = App::new("xor")
        .version("1.4.0")
        .about(ABOUT)
        .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("decrypt")
             .help("Decrypt directory names rather than encrypting them.\nApplies when using the \"recursive\" option to encrypt a directory.\nWhen set, directory names are decrypted by unhexifying then XORing.\nWhen not set, directory names are encrypted by XORing then hexifying.")
             .long("decrypt")
             .short("d"))
        .arg(Arg::with_name("input")
             .help("The file from which input data will be read, if omitted, and the \"recursive\" option isn't used, 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")
             .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"))
         .get_matches();

    // Parse the mode of operation, defaulting to encrypt mode.
    let mode = if matches.is_present("decrypt") {
        Mode::Decrypt
    } else {
        Mode::Encrypt
    };

    // Read all the key bytes into memory.
    let key_bytes = get_key_bytes(&matches);

    if matches.is_present("recursive") {
        trace!("Recursively encrypting files and folders.");

        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 {

        let input : Box<Read> = if matches.is_present("input") {
            trace!("Reading input from a file.");
            Box::new(File::open(matches.value_of("input").unwrap()).unwrap())
        } else {
            trace!("Reading input from stdin.");
            Box::new(io::stdin())
        };

        let output : Box<Write> = if matches.is_present("output") {
            trace!("Writting output to a file.");
            Box::new(OpenOptions::new()
                .write(true)
                .create(true)
                .truncate(true)
                .open(matches.value_of("output").unwrap())
                .unwrap())
        } else {
            trace!("Writting output to stdout.");
            Box::new(stdout_writer::StdoutWriter{})
        };

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

/// XOR's all the bytes from reader against the provided key then writes the result to the output
/// writer.
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() {
        match item {
            Ok(entry) => xor_entry(&entry, key, mode),
            Err(err) => info!("Failed to read entry because: {}", err)
        }
    }
}

fn xor_entry(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    match entry.file_type() {
        Ok(entry_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);
            }
        },
        Err(err) => info!("Failed to get filetype for DirEntry {:?} because: {}", entry, err)
    }
}

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

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

            let output = OpenOptions::new()
                .write(true)
                .truncate(true)
                .open(entry.path());

            match output {
                Ok(mut writer) => {
                    match writer.write_all(cypher_text.as_slice()) {
                        Ok(_) => {},
                        Err(err) => info!("Failed to write encrypted bytes to file because: {}", err)
                    }
                },
                Err(err) => info!("Failed to open file with truncate option for DirEntry {:?} because: {}", entry, err)
            }
        },
        Err(err) => info!("Failed to open file for DirEntry {:?} because: {}", entry, err)
    }

    rename_entry(entry, key, mode);
}

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

    rename_entry(entry, key, mode);
}

fn xor_dir(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    debug!("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);
}

/// Renames a directory entry.
/// When "mode" is Mode::Encrypt, the name of the entry is XOR'd then hexlified.
/// When "mode" is Mode::Decrypt, the name of the entry is unhexlified then XOR'd.
fn rename_entry(entry : &DirEntry, key : &Vec<u8>, mode : &Mode) {
    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());

        // If in Encrypt mode use the filename as is.
        // If in Decrypt mode unhexify the filename before getting it's bytes.
        let input_bytes = match *mode {
            Mode::Encrypt => original_name.to_string().into_bytes(),
            Mode::Decrypt => from_hex_string(String::from(original_name))
        };

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

        // If in Encrypt mode hexify the filename.
        // If in Decrypt mode just use the filename as is.
        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);

        match fs::rename(src_file_path, dst_file_path) {
            Ok(_) => {},
            Err(e) => info!("Failed to rename file because: {}", e)
        }
    }
}

/// 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>// Main Module
extern crate piston_window;
extern crate find_folder;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate gfx;
extern crate vecmath;
extern crate image as im;
extern crate time;
extern crate rand;
extern crate xml;

use piston_window::*;
use time::PreciseTime;

// modules
mod player;
mod io;
mod level;
mod inventory;
mod item;
mod actor;
mod field;
mod interactable;
mod coord;
mod camera;
mod bot;
mod renderable;
mod effect;

// own uses
use camera::Cam;
use player::{Player, LastKey, Direction, Weapon};
use bot::Bot;
use io::render_tile;
use io::tileset::Tileset;
use io::xml::load_xml;
use level::Level;
use effect::{EffectHandler, EffectOption};
use interactable::InteractableType;
use renderable::Renderable;
use io::all_sprites::SpriteMap;

//EINGABEN
const TWO_PLAYER: bool = true;
const SIZE_PER_TILE: u64 = 64;
const BORDER_BETWEEN_TILES: u64 = 1;
const CAMERA_BUF_X: u64 = 4;
const CAMERA_BUF_Y: u64 = 4;
const WIDTH: i64 = 584;
const HEIGHT: i64 = 584;
const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

/// struct for Settings
pub struct Settings {
    pub sprite_map: SpriteMap,
}

impl Settings {
    /// Constructor
    pub fn new(mut w: &mut PistonWindow) -> Self {
        let sprite_map = SpriteMap::init(w);
        Settings { sprite_map: sprite_map }
    }
}

/// Struct for the app
/// player_one: the first Player
/// Player_two: teh seconde Player if available
/// bots: Vector of all bots
/// cam: the Camera
pub struct App<'a> {
    player_one: Player<'a>,
    player_two: Option<Player<'a>>,
    bots: Vec<Bot<'a>>,
    cam: Cam,
}

impl<'a> App<'a> {
    /// Constructor
    fn new(mut players: Vec<Player<'a>>, mut bots: Vec<Bot<'a>>) -> Self {
        let mut p1 = match players.pop() {
            Some(p) => p,
            None => panic!("No player found!"),
        };

        let mut p2 = None;

        match players.pop() {
            Some(p) => {
                p2 = Some(p1);
                p1 = p;
            },
            None => (),
        };

        App {
            player_one: p1,
            player_two: p2,
            bots: bots,
            cam: Cam::new(CAMERA_BUF_X, CAMERA_BUF_Y),
        }
    }

    /// Handle the rendering of all Objects
    fn on_draw(&mut self,
               mut w: &mut PistonWindow,
               e: &Event,
               tileset: &Tileset,
               level: &mut Level,
               state: usize,
               effects: &EffectHandler) {
        // Range of the camera
        let range = self.cam.get_range();

        // draw in 2D
        w.draw_2d(e, |c, gl| {
            let player_one = &self.player_one;
            let player_two = &self.player_two;

            // Clear the screen.
            clear(BLACK, gl);

            let center_lv = c.transform.trans(0.0, 0.0);

            // render all Tiles if in Camera range
            for (h, j) in (range.x_min..range.x_max).enumerate() {
                for (w, i) in (range.y_min..range.y_max).enumerate() {
                    // get tile
                    let tile = match tileset.get_texture(level.get_data()[i as usize][j as usize].get_id()) {
                    Some(x) => x,
                    None => panic!("No texture found."),
                    };
                    // render tile
                    render_tile(&tile, gl, center_lv,  h as u32 * tileset.get_tile_height(),
                            w as u32 * tileset.get_tile_width(),
                            w as u32,
                            h as u32);
                }
            }
            // position of Player one in Pixel coordinates
            let center_p1 = c.transform.trans(((self.player_one.coord.get_x() - range.x_min )* (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64,
                                          ((self.player_one.coord.get_y() - range.y_min)*  (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64);

            // render player one
            player_one.render(gl, center_p1);

            // Render Player two
            if let Some(ref p2) = *player_two {

                let center_p2 = c.transform.trans(((p2.coord.get_x() - range.x_min) *  (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64,

                                              ((p2.coord.get_y() - range.y_min )*  (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64);
                 p2.render(gl, center_p2);

            }
            // Render all bots
            for b in &mut self.bots {
                    if b.coord.get_x() >= range.x_min &&  b.coord.get_x() < range.x_max &&
                        b.coord.get_y() >= range.y_min && b.coord.get_y() < range.y_max {

                        let center_b1 = c.transform.trans(((b.coord.get_x() - range.x_min )*  (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64,
                                                          ((b.coord.get_y() - range.y_min)*  (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64);
                        b.render(gl, center_b1);
                }
            }

            // Render all active effects
            for e in &effects.effects {
                let center = c.transform.trans(((e.coord.get_x() - range.x_min )*  (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64,
                                              ((e.coord.get_y() - range.y_min)*  (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64);
                e.render(gl, center);
            }
        });
    }
    /// Updates all Players, Bots, effects and camera
    fn on_update(&mut self,
                 args: &UpdateArgs,
                 level: &mut Level,
                 state: usize,
                 effects: &mut EffectHandler) {
        // Update Coordinates
        let coord1 = self.player_one.coord.clone();
        let mut coord2 = coord1.clone();
        if let Some(ref p2) = self.player_two {
            coord2 = p2.coord.clone();
        }
        // Update range with coordinates
        let range = self.cam.get_range_update();
        // Update Player one
        self.player_one.on_update(args, range, level, InteractableType::Player(1));
        // Update Player two
        if let Some(ref mut x) = self.player_two {
            x.on_update(args, range, level, InteractableType::Player(2));
        }
        // Updates bots
        for b in &mut self.bots {
            b.on_update(args, range, level, state);
        }
        // Update Camera
        self.cam.calc_coordinates(coord1, coord2, level);

        // FOR TESTING KEY Q TO ACTIVATE ANIMATION
        if self.player_one.dead {
            effects.handle(coord1, EffectOption::Sword, Direction::Down);
        }
        // END OB TESTING

        // Update Effects
        effects.on_update(args)
    }

    fn on_input(&mut self, inp: Button, pressed: bool, level: &mut Level) {

        match inp {
            // BUTTON Q FOR TESTING
            Button::Keyboard(Key::Q) => {

                self.player_one.dead = pressed;
            }
            // ENF OF TESTING
            Button::Keyboard(Key::Up) => {
                if pressed {
                    self.player_one.last = LastKey::Up;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::Down) => {
                if pressed {
                    self.player_one.last = LastKey::Down;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::Left) => {
                if pressed {
                    self.player_one.last = LastKey::Left;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::Right) => {
                if pressed {
                    self.player_one.last = LastKey::Right;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::W) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Up;
                    }
                    x.pressed = pressed;
                }
            }
            Button::Keyboard(Key::S) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Down;
                    }
                    x.pressed = pressed;
                }
            }
            Button::Keyboard(Key::A) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Left;
                    }
                    x.pressed = pressed;
                }
            }
            Button::Keyboard(Key::D) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Right;
                    }
                    x.pressed = pressed;
                }
            }
            Button::Keyboard(Key::Space) => {
                match self.player_one.weapon{
                    Weapon::Sword => {
                        let last = &self.player_one.last;
                        let p1_pos = &self.player_one.coord;

                        match *last {
                            LastKey::Up => {
                                let mut targets = Vec::new();
                                targets.push(level.get_data()[(p1_pos.get_y() - 1) as usize][p1_pos.get_x() as usize].get_fieldstatus());
                                &self.player_one.attack(targets, &mut self.bots);
                            },
                            LastKey::Down => {
                                let mut targets = Vec::new();
                                targets.push(level.get_data()[(p1_pos.get_y() + 1) as usize][p1_pos.get_x() as usize].get_fieldstatus());
                                &self.player_one.attack(targets, &mut self.bots);
                            },
                            LastKey::Left => {
                                let mut targets = Vec::new();
                                targets.push(level.get_data()[p1_pos.get_y() as usize][(p1_pos.get_x() -1) as usize].get_fieldstatus());
                                &self.player_one.attack(targets, &mut self.bots);
                            },
                            LastKey::Right => {
                                let mut targets = Vec::new();
                                targets.push(level.get_data()[p1_pos.get_y() as usize][(p1_pos.get_x() +1) as usize].get_fieldstatus());
                                &self.player_one.attack(targets, &mut self.bots);
                            },
                            _ => {}
                        }
                    }
                    _ => {}
                }
            }
            _ => {}

        }
    }
}

/// Main
fn main() {
    let mut window: PistonWindow = WindowSettings::new("chicken_fight_3000_ultimate_tournament_reloaded_uncut_director's_edition",
                                                       [WIDTH as u32, HEIGHT as u32])
        .exit_on_esc(true)
        .fullscreen(false)
        .resizable(false)
        .build()
        .unwrap();

    // Create map for sprites and load all sprites
    let map = Settings::new(&mut window).sprite_map;

    // Create EffectHandler
    let mut effects = EffectHandler::new(&map);

    // Lade XML und erstelle daraus das Level, das Tileset, die Player und die Bots
    let folder_level = match find_folder::Search::Kids(0).for_folder("src") {
        Ok(res) => res.join("level1.xml"),
        Err(_) => panic!("Folder 'src' not found!"),
    };

    let level_path = match folder_level.to_str() {
        Some(res) => res,
        None => panic!("Level not found!"),
    };

    let (lv, ts, bots, players) = load_xml(level_path, &map, &mut window);

    let tileset = ts;

    let mut level = lv;

    // Create new app with one or two players
    let mut app = App::new(players, bots);

    // Create window
    let mut events = window.events();

    // insert players in level
    level.get_data()[app.player_one.coord.get_x() as usize][app.player_one.coord.get_y() as usize]
        .set_fieldstatus(InteractableType::Player(1));
    if let Some(ref p2) = app.player_two {
        level.get_data()[p2.coord.get_x() as usize][p2.coord.get_y() as usize]
            .set_fieldstatus(InteractableType::Player(2));
    }

    // Start counter
    let mut start = PreciseTime::now();

    // set Level-borders to camera
    app.cam.set_borders((level.get_width() as u64, level.get_height() as u64));

    // sets border for player one
    app.player_one.set_borders((level.get_width() as u64, level.get_height() as u64));

    // load sprite for player two and sets border
    if let Some(ref mut p2) = app.player_two {
        p2.set_borders((level.get_width() as u64, level.get_height() as u64));
    }

    // Load sprite for each bot and set borders
    for b in &mut app.bots {
        b.set_borders((level.get_width() as u64, level.get_height() as u64));
    }

    // End of Loading start game
    while let Some(e) = events.next(&mut window) {
        // Calculate Milliseconds
        let now = start.to(PreciseTime::now()).num_milliseconds();

        // Calculate state
        let state = if now <= 500 { 0 } else { 1 };

        // If Render-Event
        if let Some(_) = e.render_args() {
            app.on_draw(&mut window,
                        &e,
                        &tileset,
                        &mut level,
                        now as usize,
                        &effects);
        }

        // If Key-Press-Event
        if let Some(i) = e.release_args() {
            app.on_input(i, false, &mut level);
        }
        // If Key-releas-Event
        if let Some(i) = e.press_args() {
            app.on_input(i, true, &mut level);
        }
        {
            // if update
            if let Some(u) = e.update_args() {
                app.on_update(&u, &mut level, state, &mut effects);
            }
        }

        // restart time if 1 second over
        if now > 1000 {
            start = PreciseTime::now();
        }
    }
}
<commit_msg>small fix<commit_after>// Main Module
extern crate piston_window;
extern crate find_folder;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate gfx;
extern crate vecmath;
extern crate image as im;
extern crate time;
extern crate rand;
extern crate xml;

use piston_window::*;
use time::PreciseTime;

// modules
mod player;
mod io;
mod level;
mod inventory;
mod item;
mod actor;
mod field;
mod interactable;
mod coord;
mod camera;
mod bot;
mod renderable;
mod effect;

// own uses
use camera::Cam;
use player::{Player, LastKey, Direction, Weapon};
use bot::Bot;
use actor::Actor;
use io::render_tile;
use io::tileset::Tileset;
use io::xml::load_xml;
use level::Level;
use effect::{EffectHandler, EffectOption};
use interactable::InteractableType;
use renderable::Renderable;
use io::all_sprites::SpriteMap;

//EINGABEN
const TWO_PLAYER: bool = true;
const SIZE_PER_TILE: u64 = 64;
const BORDER_BETWEEN_TILES: u64 = 1;
const CAMERA_BUF_X: u64 = 4;
const CAMERA_BUF_Y: u64 = 4;
const WIDTH: i64 = 584;
const HEIGHT: i64 = 584;
const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

/// struct for Settings
pub struct Settings {
    pub sprite_map: SpriteMap,
}

impl Settings {
    /// Constructor
    pub fn new(mut w: &mut PistonWindow) -> Self {
        let sprite_map = SpriteMap::init(w);
        Settings { sprite_map: sprite_map }
    }
}

/// Struct for the app
/// player_one: the first Player
/// Player_two: teh seconde Player if available
/// bots: Vector of all bots
/// cam: the Camera
pub struct App<'a> {
    player_one: Player<'a>,
    player_two: Option<Player<'a>>,
    bots: Vec<Bot<'a>>,
    cam: Cam,
}

impl<'a> App<'a> {
    /// Constructor
    fn new(mut players: Vec<Player<'a>>, mut bots: Vec<Bot<'a>>) -> Self {
        let mut p1 = match players.pop() {
            Some(p) => p,
            None => panic!("No player found!"),
        };

        let mut p2 = None;

        match players.pop() {
            Some(p) => {
                p2 = Some(p1);
                p1 = p;
            },
            None => (),
        };

        App {
            player_one: p1,
            player_two: p2,
            bots: bots,
            cam: Cam::new(CAMERA_BUF_X, CAMERA_BUF_Y),
        }
    }

    /// Handle the rendering of all Objects
    fn on_draw(&mut self,
               mut w: &mut PistonWindow,
               e: &Event,
               tileset: &Tileset,
               level: &mut Level,
               state: usize,
               effects: &EffectHandler) {
        // Range of the camera
        let range = self.cam.get_range();

        // draw in 2D
        w.draw_2d(e, |c, gl| {
            let player_one = &self.player_one;
            let player_two = &self.player_two;

            // Clear the screen.
            clear(BLACK, gl);

            let center_lv = c.transform.trans(0.0, 0.0);

            // render all Tiles if in Camera range
            for (h, j) in (range.x_min..range.x_max).enumerate() {
                for (w, i) in (range.y_min..range.y_max).enumerate() {
                    // get tile
                    let tile = match tileset.get_texture(level.get_data()[i as usize][j as usize].get_id()) {
                    Some(x) => x,
                    None => panic!("No texture found."),
                    };
                    // render tile
                    render_tile(&tile, gl, center_lv,  h as u32 * tileset.get_tile_height(),
                            w as u32 * tileset.get_tile_width(),
                            w as u32,
                            h as u32);
                }
            }
            // position of Player one in Pixel coordinates
            let center_p1 = c.transform.trans(((self.player_one.coord.get_x() - range.x_min )* (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64,
                                          ((self.player_one.coord.get_y() - range.y_min)*  (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64);

            // render player one
            player_one.render(gl, center_p1);

            // Render Player two
            if let Some(ref p2) = *player_two {

                let center_p2 = c.transform.trans(((p2.coord.get_x() - range.x_min) *  (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64,

                                              ((p2.coord.get_y() - range.y_min )*  (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64);
                 p2.render(gl, center_p2);

            }
            // Render all bots
            for b in &mut self.bots {
                    if b.coord.get_x() >= range.x_min &&  b.coord.get_x() < range.x_max &&
                        b.coord.get_y() >= range.y_min && b.coord.get_y() < range.y_max {

                        let center_b1 = c.transform.trans(((b.coord.get_x() - range.x_min )*  (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64,
                                                          ((b.coord.get_y() - range.y_min)*  (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64);
                        b.render(gl, center_b1);
                }
            }

            // Render all active effects
            for e in &effects.effects {
                let center = c.transform.trans(((e.coord.get_x() - range.x_min )*  (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64,
                                              ((e.coord.get_y() - range.y_min)*  (SIZE_PER_TILE+ BORDER_BETWEEN_TILES)) as f64);
                e.render(gl, center);
            }
        });
    }
    /// Updates all Players, Bots, effects and camera
    fn on_update(&mut self,
                 args: &UpdateArgs,
                 level: &mut Level,
                 state: usize,
                 effects: &mut EffectHandler) {
        // Update Coordinates
        let coord1 = self.player_one.coord.clone();
        let mut coord2 = coord1.clone();
        if let Some(ref p2) = self.player_two {
            coord2 = p2.coord.clone();
        }
        // Update range with coordinates
        let range = self.cam.get_range_update();
        // Update Player one
        self.player_one.on_update(args, range, level, InteractableType::Player(1));
        // Update Player two
        if let Some(ref mut x) = self.player_two {
            x.on_update(args, range, level, InteractableType::Player(2));
        }
        // Updates bots
        for b in &mut self.bots {
            b.on_update(args, range, level, state);
        }
        // Update Camera
        self.cam.calc_coordinates(coord1, coord2, level);

        // FOR TESTING KEY Q TO ACTIVATE ANIMATION
        if self.player_one.dead {
            effects.handle(coord1, EffectOption::Sword, Direction::Down);
        }
        // END OB TESTING

        // Update Effects
        effects.on_update(args)
    }

    fn on_input(&mut self, inp: Button, pressed: bool, level: &mut Level) {

        match inp {
            // BUTTON Q FOR TESTING
            Button::Keyboard(Key::Q) => {

                self.player_one.dead = pressed;
            }
            // ENF OF TESTING
            Button::Keyboard(Key::Up) => {
                if pressed {
                    self.player_one.last = LastKey::Up;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::Down) => {
                if pressed {
                    self.player_one.last = LastKey::Down;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::Left) => {
                if pressed {
                    self.player_one.last = LastKey::Left;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::Right) => {
                if pressed {
                    self.player_one.last = LastKey::Right;
                }
                self.player_one.pressed = pressed;
            }
            Button::Keyboard(Key::W) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Up;
                    }
                    x.pressed = pressed;
                }
            }
            Button::Keyboard(Key::S) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Down;
                    }
                    x.pressed = pressed;
                }
            }
            Button::Keyboard(Key::A) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Left;
                    }
                    x.pressed = pressed;
                }
            }
            Button::Keyboard(Key::D) => {
                if let Some(ref mut x) = self.player_two {
                    if pressed {
                        x.last = LastKey::Right;
                    }
                    x.pressed = pressed;
                }
            }
            Button::Keyboard(Key::Space) => {
                match self.player_one.weapon{
                    Weapon::Sword => {
                        let last = &self.player_one.last;
                        let p1_pos = &self.player_one.coord;

                        match *last {
                            LastKey::Up => {
                                let mut targets = Vec::new();
                                targets.push(level.get_data()[(p1_pos.get_y() - 1) as usize][p1_pos.get_x() as usize].get_fieldstatus());
                                &self.player_one.attack(targets, &mut self.bots);
                            },
                            LastKey::Down => {
                                let mut targets = Vec::new();
                                targets.push(level.get_data()[(p1_pos.get_y() + 1) as usize][p1_pos.get_x() as usize].get_fieldstatus());
                                &self.player_one.attack(targets, &mut self.bots);
                            },
                            LastKey::Left => {
                                let mut targets = Vec::new();
                                targets.push(level.get_data()[p1_pos.get_y() as usize][(p1_pos.get_x() -1) as usize].get_fieldstatus());
                                &self.player_one.attack(targets, &mut self.bots);
                            },
                            LastKey::Right => {
                                let mut targets = Vec::new();
                                targets.push(level.get_data()[p1_pos.get_y() as usize][(p1_pos.get_x() +1) as usize].get_fieldstatus());
                                &self.player_one.attack(targets, &mut self.bots);
                            },
                            _ => {}
                        }
                    }
                    _ => {}
                }
            }
            _ => {}

        }
    }
}

/// Main
fn main() {
    let mut window: PistonWindow = WindowSettings::new("chicken_fight_3000_ultimate_tournament_reloaded_uncut_director's_edition",
                                                       [WIDTH as u32, HEIGHT as u32])
        .exit_on_esc(true)
        .fullscreen(false)
        .resizable(false)
        .build()
        .unwrap();

    // Create map for sprites and load all sprites
    let map = Settings::new(&mut window).sprite_map;

    // Create EffectHandler
    let mut effects = EffectHandler::new(&map);

    // Lade XML und erstelle daraus das Level, das Tileset, die Player und die Bots
    let folder_level = match find_folder::Search::Kids(0).for_folder("src") {
        Ok(res) => res.join("level1.xml"),
        Err(_) => panic!("Folder 'src' not found!"),
    };

    let level_path = match folder_level.to_str() {
        Some(res) => res,
        None => panic!("Level not found!"),
    };

    let (lv, ts, bots, players) = load_xml(level_path, &map, &mut window);

    let tileset = ts;

    let mut level = lv;

    // Create new app with one or two players
    let mut app = App::new(players, bots);

    // Create window
    let mut events = window.events();

    // insert players in level
    level.get_data()[app.player_one.coord.get_x() as usize][app.player_one.coord.get_y() as usize]
        .set_fieldstatus(InteractableType::Player(1));
    if let Some(ref p2) = app.player_two {
        level.get_data()[p2.coord.get_x() as usize][p2.coord.get_y() as usize]
            .set_fieldstatus(InteractableType::Player(2));
    }

    // Start counter
    let mut start = PreciseTime::now();

    // set Level-borders to camera
    app.cam.set_borders((level.get_width() as u64, level.get_height() as u64));

    // sets border for player one
    app.player_one.set_borders((level.get_width() as u64, level.get_height() as u64));

    // load sprite for player two and sets border
    if let Some(ref mut p2) = app.player_two {
        p2.set_borders((level.get_width() as u64, level.get_height() as u64));
    }

    // Load sprite for each bot and set borders
    for b in &mut app.bots {
        b.set_borders((level.get_width() as u64, level.get_height() as u64));
    }

    // End of Loading start game
    while let Some(e) = events.next(&mut window) {
        // Calculate Milliseconds
        let now = start.to(PreciseTime::now()).num_milliseconds();

        // Calculate state
        let state = if now <= 500 { 0 } else { 1 };

        // If Render-Event
        if let Some(_) = e.render_args() {
            app.on_draw(&mut window,
                        &e,
                        &tileset,
                        &mut level,
                        now as usize,
                        &effects);
        }

        // If Key-Press-Event
        if let Some(i) = e.release_args() {
            app.on_input(i, false, &mut level);
        }
        // If Key-releas-Event
        if let Some(i) = e.press_args() {
            app.on_input(i, true, &mut level);
        }
        {
            // if update
            if let Some(u) = e.update_args() {
                app.on_update(&u, &mut level, state, &mut effects);
            }
        }

        // restart time if 1 second over
        if now > 1000 {
            start = PreciseTime::now();
        }
    }
}
<|endoftext|>


<commit_before>extern crate getopts;

extern crate otp_cop;

use std::{env, thread};
use std::sync::{mpsc};

use otp_cop::service::{CreateServiceResult, ServiceFactory};

struct ParallelIter<T> {
    count: usize,
    pos: usize,
    rx: mpsc::Receiver<T>
}

impl<T> Iterator for ParallelIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.pos < self.count {
            return self.rx.recv().ok();
        } else {
            return None;
        }
    }
}

fn parallel<T, U, F1>(objs: Vec<T>, f1: F1) -> ParallelIter<U>
        where F1: 'static + Fn(T) -> U + Send, T: Send, U: Send {
    let (tx, rx) = mpsc::channel();
    let mut threads = vec![];
    for o in objs {
        threads.push(thread::spawn(move || {
            tx.send(f1(o));
        }));
    }

    for t in threads {
        t.join();
    }

    return ParallelIter{count: threads.len(), pos: 0, rx: rx};
}

fn main() {
    let service_factories = vec![
        Box::new(otp_cop::SlackServiceFactory) as Box<ServiceFactory>,
        Box::new(otp_cop::GithubServiceFactory) as Box<ServiceFactory>,
    ];

    let mut opts = getopts::Options::new();

    for factory in service_factories.iter() {
        factory.add_options(&mut opts);
    }

    let matches = match opts.parse(env::args().skip(1)) {
        Ok(matches) => matches,
        Err(e) => panic!(e.to_string()),
    };

    let mut services = vec![];

    for factory in service_factories.iter() {
        match factory.create_service(&matches) {
            CreateServiceResult::Service(s) => services.push(s),
            CreateServiceResult::MissingArguments(arg) => panic!(format!("Missing arguments: {:?}", arg)),
            CreateServiceResult::None => continue,
        }
    }

    if services.is_empty() {
        print!("{}", opts.usage("otp-cop: <args>"));
    }

    for result in parallel(services, |service| service.get_users()) {
        println!("{}", result.service_name);
        println!("{}", "=".chars().cycle().take(result.service_name.len()).collect::<String>());
        println!("");
        for user in result.users {
            let email = match user.email {
                Some(email) => format!(" ({})", email),
                None => "".to_string(),
            };
            let details = match user.details {
                Some(details) => format!(" -- {}", details),
                None => "".to_string(),
            };
            println!("@{}{}{}", user.name, email, details);
        }
        println!("");
        println!("");
    }
}
<commit_msg>arithmetic<commit_after>extern crate getopts;

extern crate otp_cop;

use std::{env, thread};
use std::sync::{mpsc};

use otp_cop::service::{CreateServiceResult, ServiceFactory};

struct ParallelIter<T> {
    count: usize,
    pos: usize,
    rx: mpsc::Receiver<T>
}

impl<T> Iterator for ParallelIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.pos < self.count {
            self.count += 1;
            return self.rx.recv().ok();
        } else {
            return None;
        }
    }
}

fn parallel<T, U, F1>(objs: Vec<T>, f1: F1) -> ParallelIter<U>
        where F1: 'static + Fn(T) -> U + Send, T: Send, U: Send {
    let (tx, rx) = mpsc::channel();
    let mut threads = vec![];
    for o in objs {
        threads.push(thread::spawn(move || {
            tx.send(f1(o));
        }));
    }

    for t in threads {
        t.join();
    }

    return ParallelIter{count: threads.len(), pos: 0, rx: rx};
}

fn main() {
    let service_factories = vec![
        Box::new(otp_cop::SlackServiceFactory) as Box<ServiceFactory>,
        Box::new(otp_cop::GithubServiceFactory) as Box<ServiceFactory>,
    ];

    let mut opts = getopts::Options::new();

    for factory in service_factories.iter() {
        factory.add_options(&mut opts);
    }

    let matches = match opts.parse(env::args().skip(1)) {
        Ok(matches) => matches,
        Err(e) => panic!(e.to_string()),
    };

    let mut services = vec![];

    for factory in service_factories.iter() {
        match factory.create_service(&matches) {
            CreateServiceResult::Service(s) => services.push(s),
            CreateServiceResult::MissingArguments(arg) => panic!(format!("Missing arguments: {:?}", arg)),
            CreateServiceResult::None => continue,
        }
    }

    if services.is_empty() {
        print!("{}", opts.usage("otp-cop: <args>"));
    }

    for result in parallel(services, |service| service.get_users()) {
        println!("{}", result.service_name);
        println!("{}", "=".chars().cycle().take(result.service_name.len()).collect::<String>());
        println!("");
        for user in result.users {
            let email = match user.email {
                Some(email) => format!(" ({})", email),
                None => "".to_string(),
            };
            let details = match user.details {
                Some(details) => format!(" -- {}", details),
                None => "".to_string(),
            };
            println!("@{}{}{}", user.name, email, details);
        }
        println!("");
        println!("");
    }
}
<|endoftext|>


<commit_before>
#[macro_use]
extern crate lazy_static;

/// domain module
mod domain;
use domain::{ Enigma, Router, Reflector, Plugboard, SubstitutionTable };
use domain::{ Encrypter, EncryptValue };
use domain::{ SUBSTITUTION_TABLE1, SUBSTITUTION_TABLE2, SUBSTITUTION_TABLE3, REFLECTOR, PLUGBOARD };

/// utility module
mod utility;

fn main() {
    let mut encrypter = Encrypter {
        hash: Enigma::new(
            vec![
                Router::new(SubstitutionTable::new(SUBSTITUTION_TABLE1.to_vec())),
                Router::new(SubstitutionTable::new(SUBSTITUTION_TABLE2.to_vec())),
                Router::new(SubstitutionTable::new(SUBSTITUTION_TABLE3.to_vec())),
            ],
            Plugboard::new(SubstitutionTable::new(PLUGBOARD.to_vec())),
            Reflector::new(SubstitutionTable::new(REFLECTOR.to_vec()))
        )
    };

    let characters = "RBUSDGWMG EE CBGAYRV";

    print!("Encrypt string: [ {} => ", characters);
    for character in characters.chars() {
        let encrypted_value: EncryptValue<Enigma> = encrypter.encrypt(&character);
        print!("{}", encrypted_value.text);
    }
    println!(" ]");
}
<commit_msg>add attributes<commit_after>
#[macro_use]
extern crate lazy_static;

/// domain module
pub mod domain;
#[allow(unused_imports)]
use domain::{ Enigma, Router, Reflector, Plugboard, SubstitutionTable };
#[allow(unused_imports)]
use domain::{ Encrypter, EncryptValue };
#[allow(unused_imports)]
use domain::{ SUBSTITUTION_TABLE1, SUBSTITUTION_TABLE2, SUBSTITUTION_TABLE3, REFLECTOR, PLUGBOARD };

/// utility module
mod utility;

#[cfg(not(test))]
fn main() {
    let mut encrypter = Encrypter {
        hash: Enigma::new(
            vec![
                Router::new(SubstitutionTable::new(SUBSTITUTION_TABLE1.to_vec())),
                Router::new(SubstitutionTable::new(SUBSTITUTION_TABLE2.to_vec())),
                Router::new(SubstitutionTable::new(SUBSTITUTION_TABLE3.to_vec())),
            ],
            Plugboard::new(SubstitutionTable::new(PLUGBOARD.to_vec())),
            Reflector::new(SubstitutionTable::new(REFLECTOR.to_vec()))
        )
    };

    let characters = "RBUSDGWMG EE CBGAYRV";

    print!("Encrypt string: [ {} => ", characters);
    for character in characters.chars() {
        let encrypted_value: EncryptValue<Enigma> = encrypter.encrypt(&character);
        print!("{}", encrypted_value.text);
    }
    println!(" ]");
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;

extern crate gitlib;
extern crate term_painter;
extern crate pbr;

use std::error::Error;
use std::env;
use std::path::Path;
use std::fs::File;
use std::io::Write;

use term_painter::Color::{BrightRed, BrightCyan, BrightGreen, BrightMagenta, BrightYellow};
use term_painter::ToStyle;

use gitlib::{FileStatus, GitError, GitRepo, GitRepositories};

mod cli;

#[derive(Debug)]
enum RunOption {
    Checkout(String),
    Manifest(ManifestOption),
    Reset,
    Status,
}

#[derive(Debug)]
enum ManifestOption {
    Generate(File),
    Preview,
}

fn main() {
    let working_dir = match env::current_dir() {
        Ok(path) => path,
        Err(err) => {
            println!("Error getting working directory: {}", err.description());
            return;
        }
    };

    let matches = cli::build_cli().get_matches();

    let mut option = match matches.subcommand_name() {
        Some(cli::CMD_CHECKOUT) => {
            let branch_match = matches.subcommand_matches(cli::CMD_CHECKOUT).unwrap();
            let branch = value_t!(branch_match, cli::BRANCH, String).unwrap();
            RunOption::Checkout(branch)
        }
        Some(cli::CMD_MANIFEST) => {
            let matches = matches.subcommand_matches(cli::CMD_MANIFEST).unwrap();

            match matches.subcommand_name() {
                Some(cli::CMD_GENERATE) => {
                    let file = File::create("/manifest.txt").unwrap();
                    RunOption::Manifest(ManifestOption::Generate(file))
                }
                _ => RunOption::Manifest(ManifestOption::Preview),
            }
        }
        Some(cli::CMD_COMPLETIONS) => {
            if let Some(ref matches) = matches.subcommand_matches(cli::CMD_COMPLETIONS) {
                let shell = value_t!(matches, cli::SHELL, clap::Shell).unwrap();
                cli::build_cli().gen_completions_to(cli::APP_NAME, shell, &mut std::io::stdout());
            }

            return;
        }
        Some(cli::CMD_RESET) => RunOption::Reset,

        // By default, just show status.
        _ => RunOption::Status,
    };

    walk_dirs(&mut option, &working_dir);
}

fn walk_dirs(option: &mut RunOption, path: &Path) {
    let repos = GitRepositories::new(path);

    for repo in repos {
        match process(option, &repo) {
            Ok(_) => (),
            Err(_) => (),
        }
    }
}

fn process(option: &mut RunOption, repo: &GitRepo) -> Result<(), GitError> {
    match *option {
        RunOption::Checkout(ref branch) => checkout(repo, branch),
        RunOption::Manifest(ref mut opt) => manifest(repo, opt),
        RunOption::Reset => reset(repo),
        RunOption::Status => status(repo),
    }
}

fn checkout(repo: &GitRepo, branch: &str) -> Result<(), GitError> {
    repo.checkout(branch)?;

    println!("{}", repo.path().to_str().unwrap());
    //println!("    {}", BrightCyan.paint(branch));

    Ok(())
}

fn manifest(repo: &GitRepo, opt: &mut ManifestOption) -> Result<(), GitError> {
    let path_str = repo.path().to_str().unwrap();

    match *opt {
        ManifestOption::Preview => println!("{}", path_str),
        ManifestOption::Generate(ref mut file) => {
            writeln!(file, "{}", path_str)
                .map_err(|_| GitError::Manifest)
                .unwrap()
        }
    }

    Ok(())
}

fn reset(repo: &GitRepo) -> Result<(), GitError> {
    let head = repo.reset()?;
    let branch = BrightCyan.paint(head.name().unwrap());
    let l_brace = BrightYellow.paint("[");
    let r_brace = BrightYellow.paint("]");

    println!("{}  {}{}{}",
             repo.path().to_str().unwrap(),
             l_brace,
             branch,
             r_brace);

    Ok(())
}

fn status(repo: &GitRepo) -> Result<(), GitError> {
    let statuses = repo.statuses()?;

    if statuses.len() == 0 {
        return Ok(());
    }

    println!("{}", repo.path().to_str().unwrap());

    for entry in statuses.iter() {
        let (pre, colour) = match entry.status() {
            FileStatus::Deleted => ("    Deleted", BrightRed),
            FileStatus::Modified => ("   Modified", BrightCyan),
            FileStatus::New => ("        New", BrightGreen),
            FileStatus::Renamed => ("    Renamed", BrightCyan),
            FileStatus::Typechanged => ("Typechanged", BrightCyan),
            FileStatus::Unknown => ("    Unknown", BrightMagenta),
        };

        println!("  {} {}", colour.paint(pre), entry.path().unwrap());
    }

    Ok(())
}<commit_msg>Restructured manifest functionality<commit_after>#[macro_use]
extern crate clap;

extern crate gitlib;
extern crate term_painter;
extern crate pbr;

use std::error::Error;
use std::env;
use std::path::{Path, PathBuf};
use std::fs::File;
use std::io::Write;

use term_painter::Color::{BrightRed, BrightCyan, BrightGreen, BrightMagenta, BrightYellow};
use term_painter::ToStyle;

use gitlib::{FileStatus, GitError, GitRepo, GitRepositories};

mod cli;

#[derive(Debug)]
enum RunOption {
    Checkout(String),
    Manifest(ManifestOption),
    Reset,
    Status,
}

#[derive(Debug)]
enum ManifestOption {
    Generate(PathBuf),
    Preview,
}

fn main() {
    let working_dir = match env::current_dir() {
        Ok(path) => path,
        Err(err) => {
            println!("Error getting working directory: {}", err.description());
            return;
        }
    };

    let matches = cli::build_cli().get_matches();

    let option = match matches.subcommand_name() {
        Some(cli::CMD_CHECKOUT) => {
            let branch_match = matches.subcommand_matches(cli::CMD_CHECKOUT).unwrap();
            let branch = value_t!(branch_match, cli::BRANCH, String).unwrap();
            RunOption::Checkout(branch)
        }
        Some(cli::CMD_MANIFEST) => {
            let matches = matches.subcommand_matches(cli::CMD_MANIFEST).unwrap();

            match matches.subcommand_name() {
                Some(cli::CMD_GENERATE) => {
                    RunOption::Manifest(ManifestOption::Generate(PathBuf::from("/manifest.txt")))
                }
                _ => RunOption::Manifest(ManifestOption::Preview),
            }
        }
        Some(cli::CMD_COMPLETIONS) => {
            if let Some(ref matches) = matches.subcommand_matches(cli::CMD_COMPLETIONS) {
                let shell = value_t!(matches, cli::SHELL, clap::Shell).unwrap();
                cli::build_cli().gen_completions_to(cli::APP_NAME, shell, &mut std::io::stdout());
            }

            return;
        }
        Some(cli::CMD_RESET) => RunOption::Reset,

        // By default, just show status.
        _ => RunOption::Status,
    };

    process(&option, &working_dir);
}

fn process(option: &RunOption, path: &Path) {
    let repos = GitRepositories::new(path);

    if let RunOption::Manifest(ref m) = *option {
        match *m {
            ManifestOption::Generate(ref file) => manifest_generate(repos, file).unwrap(),
            ManifestOption::Preview => manifest_preview(repos),
        }
        return;
    }

    for repo in repos {
        match *option {
            RunOption::Checkout(ref branch) => {
                checkout(&repo, branch).unwrap_or_else(|_| println!("Error on checkout"))
            }
            RunOption::Reset => reset(&repo).unwrap(),
            RunOption::Status => status(&repo).unwrap(),
            _ => panic!("Unhandled run option")
        }
    }
}

fn checkout(repo: &GitRepo, branch: &str) -> Result<(), GitError> {
    repo.checkout(branch)?;

    println!("{}", repo.path().to_str().unwrap());
    //println!("    {}", BrightCyan.paint(branch));

    Ok(())
}

fn manifest_generate(repos: GitRepositories, path: &Path) -> Result<(), GitError> {
    let mut file = File::create(path).unwrap();

    for repo in repos {
        match writeln!(file, "{}", repo.path().to_str().unwrap()) {
            Ok(_) => (),
            Err(_) => ()
        }
    }

    Ok(())
}

fn manifest_preview(repos: GitRepositories) {
    for repo in repos {
        println!("{}", repo.path().to_str().unwrap());
    }
}

fn reset(repo: &GitRepo) -> Result<(), GitError> {
    let head = repo.reset()?;
    let branch = BrightCyan.paint(head.name().unwrap());
    let l_brace = BrightYellow.paint("[");
    let r_brace = BrightYellow.paint("]");

    println!("{}  {}{}{}",
             repo.path().to_str().unwrap(),
             l_brace,
             branch,
             r_brace);

    Ok(())
}

fn status(repo: &GitRepo) -> Result<(), GitError> {
    let statuses = repo.statuses()?;

    if statuses.len() == 0 {
        return Ok(());
    }

    println!("{}", repo.path().to_str().unwrap());

    for entry in statuses.iter() {
        let (pre, colour) = match entry.status() {
            FileStatus::Deleted => ("    Deleted", BrightRed),
            FileStatus::Modified => ("   Modified", BrightCyan),
            FileStatus::New => ("        New", BrightGreen),
            FileStatus::Renamed => ("    Renamed", BrightCyan),
            FileStatus::Typechanged => ("Typechanged", BrightCyan),
            FileStatus::Unknown => ("    Unknown", BrightMagenta),
        };

        println!("  {} {}", colour.paint(pre), entry.path().unwrap());
    }

    Ok(())
}<|endoftext|>


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

extern crate rustwlc;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate libc;

use rustwlc::interface::WlcInterface;
use rustwlc::types::LogType;

mod registry;
mod keys;
mod callbacks;

extern "C" fn log_handler(level: LogType, message_ptr: *const libc::c_char) {
    let message = unsafe { rustwlc::pointer_to_string(message_ptr) };
    match level {
        LogType::Info => info!("[wlc] {}", message),
        LogType::Warn => warn!("[wlc] {}", message),
        LogType::Error => error!("[wlc] {}", message),
        LogType::Wayland => info!("[wlc:wayland] {}", message)
    }
}

fn main() {
    let interface: WlcInterface = WlcInterface::new()
        .output_created(callbacks::output_created)
        .output_destroyed(callbacks::output_destroyed)
        .output_focus(callbacks::output_focus)
        .output_resolution(callbacks::output_resolution)
        //.output_render_pre(callbacks::output_render_pre)
        //.output_render_post(callbacks::output_render_post)
        .view_created(callbacks::view_created)
        .view_destroyed(callbacks::view_destroyed)
        .view_focus(callbacks::view_focus)
        .view_move_to_output(callbacks::view_move_to_output)
        .view_request_geometry(callbacks::view_request_geometry)
        .view_request_state(callbacks::view_request_state)
        .view_request_move(callbacks::view_request_move)
        .view_request_resize(callbacks::view_request_resize)
        .keyboard_key(callbacks::keyboard_key)
        .pointer_button(callbacks::pointer_button)
        .pointer_scroll(callbacks::pointer_scroll)
        .pointer_motion(callbacks::pointer_motion)
        //.touch_touch(callbacks::touch)
        .compositor_ready(callbacks::compositor_ready);
        //.input_created(input_created)
        //.input_destroyed(input_destroyed);

    env_logger::init().unwrap();
    info!("Logger initialized, setting wlc handler.");
    rustwlc::log_set_handler(log_handler);

    let run_wlc = rustwlc::init(interface).expect("Unable to initialize wlc!");

    info!("Started logger");

    run_wlc();
}
<commit_msg>Improve log format, use WAY_COOLER_LOG env variable<commit_after>//! Main module in way-cooler

extern crate rustwlc;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate libc;

use rustwlc::interface::WlcInterface;
use rustwlc::types::LogType;

use std::env;

mod registry;
mod keys;
mod callbacks;

/// Callback to route wlc logs into env_logger
extern "C" fn log_handler(level: LogType, message_ptr: *const libc::c_char) {
    let message = unsafe { rustwlc::pointer_to_string(message_ptr) };
    match level {
        LogType::Info => info!("wlc: {}", message),
        LogType::Warn => warn!("wlc: {}", message),
        LogType::Error => error!("wlc: {}", message),
        LogType::Wayland => info!("wayland: {}", message)
    }
}

/// Formats the log strings properly
fn log_format(record: &log::LogRecord) -> String {
    format!("{} [{}] {}", record.level(), record.location().module_path(),
            record.args())
}

fn main() {
    let interface: WlcInterface = WlcInterface::new()
        .output_created(callbacks::output_created)
        .output_destroyed(callbacks::output_destroyed)
        .output_focus(callbacks::output_focus)
        .output_resolution(callbacks::output_resolution)
        //.output_render_pre(callbacks::output_render_pre)
        //.output_render_post(callbacks::output_render_post)
        .view_created(callbacks::view_created)
        .view_destroyed(callbacks::view_destroyed)
        .view_focus(callbacks::view_focus)
        .view_move_to_output(callbacks::view_move_to_output)
        .view_request_geometry(callbacks::view_request_geometry)
        .view_request_state(callbacks::view_request_state)
        .view_request_move(callbacks::view_request_move)
        .view_request_resize(callbacks::view_request_resize)
        .keyboard_key(callbacks::keyboard_key)
        .pointer_button(callbacks::pointer_button)
        .pointer_scroll(callbacks::pointer_scroll)
        .pointer_motion(callbacks::pointer_motion)
        //.touch_touch(callbacks::touch)
        .compositor_ready(callbacks::compositor_ready);
        //.input_created(input_created)
        //.input_destroyed(input_destroyed);

    let mut builder = env_logger::LogBuilder::new();
    builder.format(log_format);
    builder.filter(None, log::LogLevelFilter::Trace);
    if env::var("WAY_COOLER_LOG").is_ok() {
        builder.parse(&env::var("WAY_COOLER_LOG").unwrap());
    }
    builder.init().unwrap();
    info!("Logger initialized, setting wlc handler.");
    rustwlc::log_set_handler(log_handler);

    let run_wlc = rustwlc::init(interface).expect("Unable to initialize wlc!");

    info!("Started logger");

    run_wlc();
}
<|endoftext|>


<commit_before>#![cfg_attr(feature="clippy", plugin(clippy))]
#![feature(plugin)]

extern crate flate2;
extern crate rusoto;
extern crate crossbeam;
extern crate chrono;
extern crate syslog;

use std::io;
use std::io::prelude::*;
use std::fs::{File, remove_file};
use std::env;
use std::str::FromStr;
use rusoto::{DefaultCredentialsProvider, Region};
use rusoto::s3::{S3Client, PutObjectRequest};
use rusoto::default_tls_client;
use flate2::Compression;
use flate2::write::GzEncoder;
use chrono::prelude::Local;
use chrono::{Datelike, Timelike, Duration};
use crossbeam::scope;
use syslog::{Facility, Severity};

fn main() {

    const MAX_LINES: usize = 50000;
    const MAX_BYTES: usize = 1000000; // 1M (this feels wrong though)
    const MAX_TIMEOUT: i64 = 5; // in seconds

    println!("MAX_LINES: {}    MAX_BYTES: {}    MAX_TIMEOUT: {}",
             MAX_LINES,
             MAX_BYTES,
             MAX_TIMEOUT);

    let reader = io::stdin();
    let mut buffer = reader.lock();
    let mut data = vec![0];
    let mut time = Local::now();
    let mut timeout = time + Duration::seconds(MAX_TIMEOUT);

    loop {
        match buffer.fill_buf() {
            Ok(bytes) => {
                // add the current bytes to our data vector
                data.extend(bytes);
                if data.lines().count() >= MAX_LINES || data.len() >= MAX_BYTES ||
                   timeout <= time && !data.is_empty() {
                    // send the data to the compress function
                    compress(data.as_slice());
                    // clear our data vector
                    data.clear();
                    // reset our timer
                    time = Local::now();
                    timeout = time + Duration::seconds(MAX_TIMEOUT);
                } else {
                    // update the time
                    time = Local::now();
                }
            }
            Err(err) => panic!(err),
        }

        // consume the data from the buffer so we don't reprocess it
        buffer.consume(data.len());
    }
}

fn compress(bytes: &[u8]) {
    // our compression routine will be sent to another thread
    scope(|scope| {
        scope.spawn(move || {
            // use our environment variable of hostname. will be essentially the CBID
            let hostname = match env::var("HOSTNAME") {
                Ok(hostname) => hostname,
                Err(err) => panic!("Unable to get hostname. {}", err),
            };

            let timestamp = Local::now();

            // setting the format for how we write out the file.
            let file = format!("{}.{}-{}.raw.gz",
                               timestamp.second(),
                               timestamp.timestamp_subsec_millis(),
                               &hostname);

            let mut output = File::create(&file).unwrap();

            let mut encoder = GzEncoder::new(Vec::new(), Compression::Default);

            encoder.write_all(bytes).unwrap();

            let encoded = encoder.finish().unwrap();

            output.write_all(&encoded).unwrap();

            write_s3(&file);
        });
    });
}

fn write_s3(file: &str) {
    scope(|scope| {
        scope.spawn(move || {

            let timestamp = Local::now();
            let path = format!("{}/{}/{}/{}/{}/{}",
                               timestamp.year(),
                               timestamp.month(),
                               timestamp.day(),
                               timestamp.hour(),
                               timestamp.minute(),
                               &file);

            let provider = match DefaultCredentialsProvider::new() {
                Ok(provider) => provider,
                Err(err) => panic!("Unable to load credentials. {}", err),
            };

            let region = match env::var("AWS_DEFAULT_REGION") {
                Ok(region) => region,
                Err(err) => panic!("environment AWS_DEFAULT_REGION is not set. {}", err),
            };

            let s3 = S3Client::new(default_tls_client().unwrap(),
                                   provider,
                                   Region::from_str(&region).unwrap());

            // Open the gzip'd log file
            let mut log = File::open(&file).unwrap();
            // create a u8 vector
            let mut contents: Vec<u8> = Vec::new();
            // if we can read the contents to the buffer we will attempt to send the log to s3
            match log.read_to_end(&mut contents) {
                Err(err) => panic!("Error opening file to send to S3: {}", err),
                Ok(_) => {
                    // need to build our request
                    let req = PutObjectRequest {
                        bucket: "jkordish-test".to_owned(),
                        key: path.to_owned(),
                        body: Some(contents),
                        ..Default::default()
                    };
                    match s3.put_object(&req) {
                        Ok(_) => {
                            // print notification to stdout.
                            println!("Successfully wrote {}/{}", &req.bucket, &path);
                            // only remove the file if we are successful
                            if remove_file(&file).is_ok() {
                                println!("Removed file {}", &file);
                            }
                        }
                        Err(e) => println!("Could not write file {} {}", &file, e),
                    }
                    // Send some notifications to SYSLOG
                    match syslog::unix(Facility::LOG_SYSLOG) {
                        Err(e) => println!("impossible to connect to syslog: {:?}", e),
                        Ok(writer) => {
                            let success = format!("wrote {}/{}", &req.bucket, &path);
                            let failure = format!("unable to write {}/{}", &req.bucket, &path);
                            if writer.send_3164(Severity::LOG_ALERT, &success).is_err() {
                                let _ = writer.send_3164(Severity::LOG_ERR, &failure);
                            }
                        }
                    }
                }
            }
        });
    });
}
<commit_msg>pass encoded from compress() -> write_s3()<commit_after>#![cfg_attr(feature="clippy", plugin(clippy))]
#![feature(plugin)]

extern crate flate2;
extern crate rusoto;
extern crate crossbeam;
extern crate chrono;
extern crate syslog;

use std::io;
use std::io::prelude::*;
use std::fs::{File, remove_file};
use std::env;
use std::str::FromStr;
use rusoto::{DefaultCredentialsProvider, Region};
use rusoto::s3::{S3Client, PutObjectRequest};
use rusoto::default_tls_client;
use flate2::Compression;
use flate2::write::GzEncoder;
use chrono::prelude::Local;
use chrono::{Datelike, Timelike, Duration};
use crossbeam::scope;
use syslog::{Facility, Severity};

fn main() {

    const MAX_LINES: usize = 50000;
    const MAX_BYTES: usize = 1000000; // 1M (this feels wrong though)
    const MAX_TIMEOUT: i64 = 5; // in seconds

    println!("MAX_LINES: {}    MAX_BYTES: {}    MAX_TIMEOUT: {}",
             MAX_LINES,
             MAX_BYTES,
             MAX_TIMEOUT);

    let reader = io::stdin();
    let mut buffer = reader.lock();
    let mut data = vec![0];
    let mut time = Local::now();
    let mut timeout = time + Duration::seconds(MAX_TIMEOUT);

    loop {
        match buffer.fill_buf() {
            Ok(bytes) => {
                // add the current bytes to our data vector
                data.extend(bytes);
                // evaulate if data and time meet of processing conditions
                if data.lines().count() >= MAX_LINES || data.len() >= MAX_BYTES ||
                   timeout <= time && !data.is_empty() {
                    // send the data to the compress function
                    compress(data.as_slice());
                    // clear our data vector
                    data.clear();
                    // reset our timer
                    time = Local::now();
                    timeout = time + Duration::seconds(MAX_TIMEOUT);
                } else {
                    // update the time
                    time = Local::now();
                }
            }
            Err(err) => panic!(err),
        }

        // consume the data from the buffer so we don't reprocess it
        buffer.consume(data.len());
    }
}

fn compress(bytes: &[u8]) {
    // our compression routine will be sent to another thread
    scope(|scope| {
        scope.spawn(move || {
            // use our environment variable of hostname. will be essentially the CBID
            let hostname = match env::var("HOSTNAME") {
                Ok(hostname) => hostname,
                Err(err) => panic!("Unable to get hostname. {}", err),
            };

            let timestamp = Local::now();

            // setting the format for how we write out the file.
            let file = format!("{}.{}-{}.raw.gz",
                               timestamp.second(),
                               timestamp.timestamp_subsec_millis(),
                               &hostname);

            let mut output = File::create(&file).unwrap();

            let mut encoder = GzEncoder::new(Vec::new(), Compression::Default);

            encoder.write_all(bytes).unwrap();

            let encoded = encoder.finish().unwrap();

            output.write_all(&encoded).unwrap();

            write_s3(&file, &encoded);
        });
    });
}

fn write_s3(file: &str, log: &[u8]) {
    // move to new thread
    scope(|scope| {
        scope.spawn(move || {

            let timestamp = Local::now();
            let path = format!("{}/{}/{}/{}/{}/{}",
                               timestamp.year(),
                               timestamp.month(),
                               timestamp.day(),
                               timestamp.hour(),
                               timestamp.minute(),
                               &file);

            // set up our credentials provider for aws
            let provider = match DefaultCredentialsProvider::new() {
                Ok(provider) => provider,
                Err(err) => panic!("Unable to load credentials. {}", err),
            };

            // obtain our aws default region so we know where to look
            let region = match env::var("AWS_DEFAULT_REGION") {
                Ok(region) => region,
                Err(err) => panic!("environment AWS_DEFAULT_REGION is not set. {}", err),
            };

            // create our s3 client initialization
            let s3 = S3Client::new(default_tls_client().unwrap(),
                                   provider,
                                   Region::from_str(&region).unwrap());

            // create a u8 vector
            let mut contents: Vec<u8> = Vec::new();
            // add our encoded log file to the vector
            contents.extend(log);

            // if we can read the contents to the buffer we will attempt to send the log to s3
            // need to build our request
            let req = PutObjectRequest {
                bucket: "jkordish-test".to_owned(),
                key: path.to_owned(),
                body: Some(contents),
                ..Default::default()
            };

            match s3.put_object(&req) {
                Ok(_) => {
                    // print notification to stdout.
                    println!("Successfully wrote {}/{}", &req.bucket, &path);
                    // only remove the file if we are successful
                    if remove_file(&file).is_ok() {
                        println!("Removed file {}", &file);
                    }
                }
                Err(e) => println!("Could not write file {} {}", &file, e),
            }

            // Send some notifications to SYSLOG
            match syslog::unix(Facility::LOG_SYSLOG) {
                Err(e) => println!("impossible to connect to syslog: {:?}", e),
                Ok(writer) => {
                    let success = format!("wrote {}/{}", &req.bucket, &path);
                    let failure = format!("unable to write {}/{}", &req.bucket, &path);
                    if writer.send_3164(Severity::LOG_ALERT, &success).is_err() {
                        let _ = writer.send_3164(Severity::LOG_ERR, &failure);
                    }
                }
            }
        });
    });
}
<|endoftext|>


<commit_before>// Playing with paths.

extern crate chrono;
extern crate rsure;
extern crate env_logger;
extern crate regex;

#[macro_use]
extern crate log;

#[macro_use]
extern crate clap;

use chrono::Local;
use clap::{App, AppSettings, Arg, SubCommand};

use std::collections::BTreeMap;
use std::path::Path;

use rsure::{show_tree, Progress, SureHash, TreeCompare, stdout_visitor, parse_store, StoreTags,
            StoreVersion, Version};

mod bkcmd;

// For now, just use the crate's error type.
pub use rsure::Result;

#[allow(dead_code)]
fn main() {
    env_logger::init().unwrap();

    let matches = App::new("rsure")
        .version(crate_version!())
        .setting(AppSettings::GlobalVersion)
        .arg(
            Arg::with_name("file")
                .short("f")
                .long("file")
                .takes_value(true)
                .help(
                    "Base of file name, default 2sure, will get .dat.gz appended",
                ),
        )
        .arg(
            Arg::with_name("dir")
                .short("d")
                .long("dir")
                .takes_value(true)
                .help("Directory to scan, defaults to \".\""),
        )
        .arg(
            Arg::with_name("tag")
                .long("tag")
                .takes_value(true)
                .multiple(true)
                .help("key=value to associate with scan"),
        )
        .arg(
            Arg::with_name("version")
                .short("v")
                .long("version")
                .takes_value(true)
                .help("Version of sure data to use (see 'list' output)"),
        )
        .setting(AppSettings::SubcommandRequired)
        .subcommand(SubCommand::with_name("scan").about(
            "Scan a directory for the first time",
        ))
        .subcommand(SubCommand::with_name("update").about(
            "Update the scan using the dat file",
        ))
        .subcommand(SubCommand::with_name("check").about(
            "Compare the directory with the dat file",
        ))
        .subcommand(SubCommand::with_name("signoff").about(
            "Compare the dat file with the bak file",
        ))
        .subcommand(SubCommand::with_name("show").about(
            "Pretty print the dat file",
        ))
        .subcommand(
            SubCommand::with_name("bknew")
                .about("Create a new bitkeeper-based sure store")
                .arg(Arg::with_name("dir").required(true).help(
                    "Directory to create bk-based store",
                )),
        )
        .subcommand(
            SubCommand::with_name("bkimport")
                .about("Import a tree of surefiles into a bk store")
                .arg(
                    Arg::with_name("src")
                        .long("src")
                        .takes_value(true)
                        .required(true),
                )
                .arg(
                    Arg::with_name("dest")
                        .long("dest")
                        .takes_value(true)
                        .required(true),
                ),
        )
        .subcommand(SubCommand::with_name("list").about(
            "List revisions in a given sure store",
        ))
        .get_matches();

    let dir = matches.value_of("dir").unwrap_or(".");

    let file = matches.value_of("file").unwrap_or("2sure.dat.gz");
    let store = parse_store(file).unwrap();

    let tags = decode_tags(matches.values_of("tag"));

    // Note that only the "check" command uses the version tag.
    let latest = match matches.value_of("version") {
        None => Version::Latest,
        Some(x) => Version::Tagged(x.to_string()),
    };

    match matches.subcommand() {
        ("scan", Some(_)) => {
            rsure::update(&dir, &*store, false, &tags).unwrap();
        }
        ("update", Some(_)) => {
            rsure::update(&dir, &*store, true, &tags).unwrap();
        }
        ("check", Some(_)) => {
            let old_tree = store.load(latest).unwrap();
            let mut new_tree = rsure::scan_fs(&dir).unwrap();
            let estimate = new_tree.hash_estimate();
            let pdir = &Path::new(dir);
            let mut progress = Progress::new(estimate.files, estimate.bytes);
            new_tree.hash_update(pdir, &mut progress);
            progress.flush();
            info!("check {:?}", file);
            new_tree.compare_from(&mut stdout_visitor(), &old_tree, pdir);
        }
        ("signoff", Some(_)) => {
            let old_tree = store.load(Version::Prior).unwrap();
            let new_tree = store.load(Version::Latest).unwrap();
            println!("signoff {}", file);
            new_tree.compare_from(&mut stdout_visitor(), &old_tree, &Path::new(dir));
        }
        ("show", Some(_)) => {
            println!("show {}", file);
            show_tree(&Path::new(&file)).unwrap();
        }
        ("bknew", Some(sub)) => {
            let bkdir = sub.value_of("dir").unwrap();
            bkcmd::new(bkdir).unwrap();
        }
        ("bkimport", Some(sub)) => {
            let src = sub.value_of("src").unwrap();
            let dest = sub.value_of("dest").unwrap();
            bkcmd::import(src, dest).unwrap();
        }
        ("list", Some(_)) => {
            let version = store.get_versions().unwrap();
            dump_versions(&version);
        }
        _ => {
            panic!("Unsupported command.");
        }
    }
}

/// Decode the command-line tags.  Tags should be of the form key=value, and multiple can be
/// specified, terminated by the command.  It is also possible to specify --tag multiple times.
fn decode_tags<'a, I>(tags: Option<I>) -> StoreTags
where
    I: Iterator<Item = &'a str>,
{
    match tags {
        None => BTreeMap::new(),
        Some(tags) => tags.map(|x| decode_tag(x)).collect(),
    }
}

fn decode_tag<'a>(tag: &'a str) -> (String, String) {
    let fields: Vec<_> = tag.splitn(2, '=').collect();
    if fields.len() != 2 {
        panic!("Tag must be key=value");
    }
    (fields[0].to_string(), fields[1].to_string())
}

fn dump_versions(versions: &[StoreVersion]) {
    println!("vers | Time captured       | name");
    println!("-----+---------------------+------------------");
    for v in versions {
        let vers = match v.version {
            Version::Latest => "tip",
            Version::Prior => "prev",
            Version::Tagged(ref v) => v,
        };
        println!(
            "{:4} | {} | {}",
            vers,
            v.time.with_timezone(&Local).format("%Y-%m-%d %H:%M:%S"),
            v.name
        );
    }
}
<commit_msg>main: Create a 'name' tag if not given<commit_after>// Playing with paths.

extern crate chrono;
extern crate rsure;
extern crate env_logger;
extern crate regex;

#[macro_use]
extern crate log;

#[macro_use]
extern crate clap;

use chrono::Local;
use clap::{App, AppSettings, Arg, SubCommand};

use std::collections::BTreeMap;
use std::path::Path;

use rsure::{show_tree, Progress, SureHash, TreeCompare, stdout_visitor, parse_store, StoreTags,
            StoreVersion, Version};

mod bkcmd;

// For now, just use the crate's error type.
pub use rsure::Result;

#[allow(dead_code)]
fn main() {
    env_logger::init().unwrap();

    let matches = App::new("rsure")
        .version(crate_version!())
        .setting(AppSettings::GlobalVersion)
        .arg(
            Arg::with_name("file")
                .short("f")
                .long("file")
                .takes_value(true)
                .help(
                    "Base of file name, default 2sure, will get .dat.gz appended",
                ),
        )
        .arg(
            Arg::with_name("dir")
                .short("d")
                .long("dir")
                .takes_value(true)
                .help("Directory to scan, defaults to \".\""),
        )
        .arg(
            Arg::with_name("tag")
                .long("tag")
                .takes_value(true)
                .multiple(true)
                .help("key=value to associate with scan"),
        )
        .arg(
            Arg::with_name("version")
                .short("v")
                .long("version")
                .takes_value(true)
                .help("Version of sure data to use (see 'list' output)"),
        )
        .setting(AppSettings::SubcommandRequired)
        .subcommand(SubCommand::with_name("scan").about(
            "Scan a directory for the first time",
        ))
        .subcommand(SubCommand::with_name("update").about(
            "Update the scan using the dat file",
        ))
        .subcommand(SubCommand::with_name("check").about(
            "Compare the directory with the dat file",
        ))
        .subcommand(SubCommand::with_name("signoff").about(
            "Compare the dat file with the bak file",
        ))
        .subcommand(SubCommand::with_name("show").about(
            "Pretty print the dat file",
        ))
        .subcommand(
            SubCommand::with_name("bknew")
                .about("Create a new bitkeeper-based sure store")
                .arg(Arg::with_name("dir").required(true).help(
                    "Directory to create bk-based store",
                )),
        )
        .subcommand(
            SubCommand::with_name("bkimport")
                .about("Import a tree of surefiles into a bk store")
                .arg(
                    Arg::with_name("src")
                        .long("src")
                        .takes_value(true)
                        .required(true),
                )
                .arg(
                    Arg::with_name("dest")
                        .long("dest")
                        .takes_value(true)
                        .required(true),
                ),
        )
        .subcommand(SubCommand::with_name("list").about(
            "List revisions in a given sure store",
        ))
        .get_matches();

    let dir = matches.value_of("dir").unwrap_or(".");

    let file = matches.value_of("file").unwrap_or("2sure.dat.gz");
    let store = parse_store(file).unwrap();

    let mut tags = decode_tags(matches.values_of("tag"));

    add_name_tag(&mut tags);

    // Note that only the "check" command uses the version tag.
    let latest = match matches.value_of("version") {
        None => Version::Latest,
        Some(x) => Version::Tagged(x.to_string()),
    };

    match matches.subcommand() {
        ("scan", Some(_)) => {
            rsure::update(&dir, &*store, false, &tags).unwrap();
        }
        ("update", Some(_)) => {
            rsure::update(&dir, &*store, true, &tags).unwrap();
        }
        ("check", Some(_)) => {
            let old_tree = store.load(latest).unwrap();
            let mut new_tree = rsure::scan_fs(&dir).unwrap();
            let estimate = new_tree.hash_estimate();
            let pdir = &Path::new(dir);
            let mut progress = Progress::new(estimate.files, estimate.bytes);
            new_tree.hash_update(pdir, &mut progress);
            progress.flush();
            info!("check {:?}", file);
            new_tree.compare_from(&mut stdout_visitor(), &old_tree, pdir);
        }
        ("signoff", Some(_)) => {
            let old_tree = store.load(Version::Prior).unwrap();
            let new_tree = store.load(Version::Latest).unwrap();
            println!("signoff {}", file);
            new_tree.compare_from(&mut stdout_visitor(), &old_tree, &Path::new(dir));
        }
        ("show", Some(_)) => {
            println!("show {}", file);
            show_tree(&Path::new(&file)).unwrap();
        }
        ("bknew", Some(sub)) => {
            let bkdir = sub.value_of("dir").unwrap();
            bkcmd::new(bkdir).unwrap();
        }
        ("bkimport", Some(sub)) => {
            let src = sub.value_of("src").unwrap();
            let dest = sub.value_of("dest").unwrap();
            bkcmd::import(src, dest).unwrap();
        }
        ("list", Some(_)) => {
            let version = store.get_versions().unwrap();
            dump_versions(&version);
        }
        _ => {
            panic!("Unsupported command.");
        }
    }
}

/// Decode the command-line tags.  Tags should be of the form key=value, and multiple can be
/// specified, terminated by the command.  It is also possible to specify --tag multiple times.
fn decode_tags<'a, I>(tags: Option<I>) -> StoreTags
where
    I: Iterator<Item = &'a str>,
{
    match tags {
        None => BTreeMap::new(),
        Some(tags) => tags.map(|x| decode_tag(x)).collect(),
    }
}

fn decode_tag<'a>(tag: &'a str) -> (String, String) {
    let fields: Vec<_> = tag.splitn(2, '=').collect();
    if fields.len() != 2 {
        panic!("Tag must be key=value");
    }
    (fields[0].to_string(), fields[1].to_string())
}

/// If the caller doesn't specify a 'name=' tag, generate one based on the current timestamp.
fn add_name_tag(tags: &mut StoreTags) {
    if !tags.contains_key("name") {
        tags.insert("name".to_string(), Local::now().to_rfc3339());
    }
}

fn dump_versions(versions: &[StoreVersion]) {
    println!("vers | Time captured       | name");
    println!("-----+---------------------+------------------");
    for v in versions {
        let vers = match v.version {
            Version::Latest => "tip",
            Version::Prior => "prev",
            Version::Tagged(ref v) => v,
        };
        println!(
            "{:4} | {} | {}",
            vers,
            v.time.with_timezone(&Local).format("%Y-%m-%d %H:%M:%S"),
            v.name
        );
    }
}
<|endoftext|>