<commit_before>
/// Mode of input similar to Vim input mode.
///
/// In each mode the key will have a different meaning
pub enum InputMode {
    /// Default game mode
    Default,
    /// Move cursor freely around to identify things
    Explore,
    /// Menu
    Menu,
    /// Yes or no question
    YesOrNo,
    /// Help files
    Help,
}

pub struct InputHandler {
    mode: InputMode,
}

impl InputHandler {
    pub fn new() -> InputHandler {
        InputHandler { mode: InputMode::Default }
    }

    pub fn change_mode(&mut self, new_mode: InputMode) {
        self.mode = new_mode;
    }

    pub fn process_key(&self, key: char) {

        match key {
            'h' => info!("west"),
            'j' => info!("south"),
            'k' => info!("north"),
            'l' => info!("left"),
            'y' => info!("left"),
            'u' => info!("left"),
            'b' => info!("left"),
            'n' => info!("left"),
            _ => info!("error"),
        }

    }
}
<commit_msg>add structure for processing in multiple input modes<commit_after>#![allow(unused_variables)]

/// Mode of input similar to Vim input mode.
///
/// In each mode the key will have a different meaning
#[derive(Debug)]
pub enum InputMode {
    /// Normal game mode
    Normal,
    /// Move cursor freely around to identify things
    Explore,
    /// Menu
    Menu,
    /// Yes or no question
    YesOrNo,
    /// Help files
    Help,
}

pub struct InputHandler {
    mode: InputMode,
}

impl InputHandler {
    pub fn new() -> InputHandler {
        InputHandler { mode: InputMode::Normal }
    }

    pub fn change_mode(&mut self, new_mode: InputMode) {
        self.mode = new_mode;
    }

    pub fn process_key(&self, key: char) {
        match self.mode {
            InputMode::Normal => self.process_normal(key),
            InputMode::Explore => self.process_explore(key),
            InputMode::Menu => self.process_menu(key),
            InputMode::YesOrNo => self.process_yesorno(key),
            InputMode::Help => self.process_help(key),
        }
    }

    fn process_normal(&self, key: char) {
        match key {
            'h' => info!("west"),
            'j' => info!("south"),
            'k' => info!("north"),
            'l' => info!("left"),
            'y' => info!("left"),
            'u' => info!("left"),
            'b' => info!("left"),
            'n' => info!("left"),
            _ => warn!("unknown command in {:?} mode : {}", self.mode, key),
        }
    }

    fn process_explore(&self, key: char) {
        unimplemented!();
    }

    fn process_menu(&self, key: char) {
        unimplemented!();
    }

    fn process_yesorno(&self, key: char) {
        unimplemented!();
    }

    fn process_help(&self, key: char) {
        unimplemented!();
    }
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types, non_snake_case)]
extern crate ncurses;

use ncurses::ll::{chtype, attr_t, WINDOW, wattrset};

use ncurses::NCURSES_ATTR_SHIFT;

pub fn NCURSES_BITS(mask: u32, shift: u32) -> u32 {
    mask << (shift + NCURSES_ATTR_SHIFT) as usize
}

pub const A_NORMAL: attr_t = 0u32 as attr_t;
pub const A_ATTRIBUTES: attr_t = (!0u32 << (0u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_CHARTEXT: attr_t = (1u32 << (0u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_COLOR: attr_t = ((((1u32) << 8) - 1u32) << (0u32 + NCURSES_ATTR_SHIFT)) as attr_t;

// pub fn A_STANDOUT() -> attr_t
// { NCURSES_BITS(1u32, 8u32) as attr_t }
//
// pub fn A_UNDERLINE() -> attr_t
// { NCURSES_BITS(1u32, 9u32) as attr_t }
//
// pub fn A_REVERSE() -> attr_t
// { NCURSES_BITS(1u32, 10u32) as attr_t }
//
// pub fn A_BLINK() -> attr_t
// { NCURSES_BITS(1u32, 11u32) as attr_t }
//
// pub fn A_DIM() -> attr_t
// { NCURSES_BITS(1u32, 12u32) as attr_t }
//

pub const A_BOLD: attr_t = (1u32 << (13u32 + NCURSES_ATTR_SHIFT)) as attr_t;

pub fn COLOR_PAIR(n: chtype) -> attr_t {
    NCURSES_BITS(n as u32, 0u32) as attr_t
}

pub fn _attrset(w: WINDOW, attributes: chtype) -> i32 {
    unsafe { wattrset(w, attributes as i32) }
}
<commit_msg>Defined KEY_RESIZE for the unix module<commit_after>#![allow(non_camel_case_types, non_snake_case)]
extern crate ncurses;

use ncurses::ll::{chtype, attr_t, WINDOW, wattrset};

use ncurses::NCURSES_ATTR_SHIFT;

pub fn NCURSES_BITS(mask: u32, shift: u32) -> u32 {
    mask << (shift + NCURSES_ATTR_SHIFT) as usize
}

pub const A_NORMAL: attr_t = 0u32 as attr_t;
pub const A_ATTRIBUTES: attr_t = (!0u32 << (0u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_CHARTEXT: attr_t = (1u32 << (0u32 + NCURSES_ATTR_SHIFT)) as attr_t;
pub const A_COLOR: attr_t = ((((1u32) << 8) - 1u32) << (0u32 + NCURSES_ATTR_SHIFT)) as attr_t;

// pub fn A_STANDOUT() -> attr_t
// { NCURSES_BITS(1u32, 8u32) as attr_t }
//
// pub fn A_UNDERLINE() -> attr_t
// { NCURSES_BITS(1u32, 9u32) as attr_t }
//
// pub fn A_REVERSE() -> attr_t
// { NCURSES_BITS(1u32, 10u32) as attr_t }
//
// pub fn A_BLINK() -> attr_t
// { NCURSES_BITS(1u32, 11u32) as attr_t }
//
// pub fn A_DIM() -> attr_t
// { NCURSES_BITS(1u32, 12u32) as attr_t }
//

pub const A_BOLD: attr_t = (1u32 << (13u32 + NCURSES_ATTR_SHIFT)) as attr_t;

pub const KEY_RESIZE: i32 = 0632;

pub fn COLOR_PAIR(n: chtype) -> attr_t {
    NCURSES_BITS(n as u32, 0u32) as attr_t
}

pub fn _attrset(w: WINDOW, attributes: chtype) -> i32 {
    unsafe { wattrset(w, attributes as i32) }
}
<|endoftext|>


<commit_before>use std::os;
use std::io;
use std::collections::HashMap;
use std::io::fs::PathExtensions;
use std::borrow::ToOwned;

use atomicwrites::{AtomicFile,AllowOverwrite};

use utils::{
    Contact, add_contact_from_email, index_query, index_item_from_contact
};

macro_rules! main_try {
    ($result: expr, $errmsg: expr) => (
        match $result {
            Ok(m) => m,
            Err(e) => {
                println!("{}: {}", $errmsg, e);
                os::set_exit_status(1);
                return;
            }
        }
    )
}

fn build_index(outfile: &Path, dir: &Path) -> io::IoResult<()> {
    if !dir.is_dir() {
        return Err(io::IoError {
            kind: io::MismatchedFileTypeForOperation,
            desc: "MATES_DIR must be a directory.",
            detail: None
        });
    };

    let af = AtomicFile::new(outfile, AllowOverwrite, None);
    let entries = try!(io::fs::readdir(dir));
    let mut errors = false;

    try!(af.write(|&mut: outf| {
        for entry in entries.iter() {
            if !entry.is_file() || !entry.filename_str().unwrap_or("").ends_with(".vcf") {
                continue;
            }

            let contact = match Contact::from_file(entry.clone()) {
                Ok(x) => x,
                Err(e) => {
                    println!("Error while reading {}: {}", entry.display(), e);
                    errors = true;
                    continue
                }
            };

            match index_item_from_contact(&contact) {
                Ok(index_string) => {
                    try!(outf.write_str(index_string.as_slice()));
                },
                Err(e) => {
                    println!("Error while indexing {}: {}", entry.display(), e);
                    errors = true;
                    continue
                }
            };
        };
        Ok(())
    }));

    if errors {
        Err(io::IoError {
            kind: io::OtherIoError,
            desc: "Several errors happened while generating the index.",
            detail: None
        })
    } else {
        Ok(())
    }
}

pub fn cli_main() {
    let mut args = os::args().into_iter();
    let program = args.next().unwrap_or("mates".to_string());

    let help = format!("Usage: {} COMMAND
Commands:
    index:
        Rewrite/create the index.
    mutt-query <query>:
        Search for contact, output is usable for mutt's query_command.
    file-query <query>:
        Search for contact, return just the filename.
    email-query <query>:
        Search for contact, return \"name <email>\".
    add:
        Take mail from stdin, add sender to contacts. Print filename.
    edit <file-or-query>:
        Open contact (given by filepath or search-string) in $MATES_EDITOR. If
        the file is cleared, the contact is removed.", program);

    let print_help = |&:| {
        println!("{}", help);
    };

    let command = match args.next() {
        Some(x) => x,
        None => {
            print_help();
            os::set_exit_status(1);
            return;
        }
    };

    if command == "--help" || command == "help" || command == "-h" {
        print_help();
        return;
    }

    let config = match Configuration::new() {
        Ok(x) => x,
        Err(e) => {
            println!("Error while reading configuration: {}", e);
            os::set_exit_status(1);
            return;
        }
    };

    match command.as_slice() {
        "index" => {
            println!("Rebuilding index file \"{}\"...", config.index_path.display());
            main_try!(build_index(&config.index_path, &config.vdir_path), "Failed to build index");
        },
        "mutt-query" => {
            let query = args.next().unwrap_or("".to_string());
            main_try!(mutt_query(&config, query.as_slice()), "Failed to execute grep");
        },
        "file-query" => {
            let query = args.next().unwrap_or("".to_string());
            main_try!(file_query(&config, query.as_slice()), "Failed to execute grep");
        },
        "email-query" => {
            let query = args.next().unwrap_or("".to_string());
            main_try!(email_query(&config, query.as_slice()), "Failed to execute grep");
        },
        "add" => {
            let email = main_try!(io::stdin().lock().read_to_string(), "Failed to read email");
            let contact = main_try!(add_contact_from_email(&config.vdir_path,
                                                           email.as_slice()), "Failed to add contact");
            println!("{}", contact.path.display());

            let mut index_fp = main_try!(io::File::open_mode(
                &config.index_path,
                io::Append,
                io::Write),
                "Failed to open index"
            );

            let index_entry = main_try!(index_item_from_contact(&contact), "Failed to generate index");
            main_try!(index_fp.write_str(index_entry.as_slice()), "Failed to write to index");
        },
        "edit" => {
            let query = args.next().unwrap_or("".to_string());
            main_try!(edit_contact(&config, query.as_slice()), "Failed to edit contact");
        },
        _ => {
            println!("Invalid command: {}", command);
            print_help();
            os::set_exit_status(1);
        }
    };
}

fn edit_contact(config: &Configuration, query: &str) -> Result<(), String> {

    let results = {
        if config.vdir_path.join(query).is_file() {
            vec![query.to_string()]
        } else {
            let results_iter = match index_query(config, query) {
                Ok(x) => x,
                Err(e) => return Err(format!("Error while fetching index: {}", e))
            };

            results_iter.filter_map(|x| {
                if x.filepath.len() > 0 {
                    Some(x.filepath)
                } else {
                    None
                }}).collect()
        }
    };

    if results.len() < 1 {
        return Err("No such contact.".to_string());
    } else if results.len() > 1 {
        return Err("Ambiguous query.".to_string());
    }

    let fpath = results[0].as_slice();
    let mut process = match io::Command::new("sh")
        .arg("-c")
        // clear stdin, http://unix.stackexchange.com/a/77593
        .arg(format!("$0 -- \"$1\" < $2"))
        .arg(config.editor_cmd.as_slice())
        .arg(fpath)
        .arg("/dev/tty")
        .stdin(io::process::InheritFd(0))
        .stdout(io::process::InheritFd(1))
        .stderr(io::process::InheritFd(2))
        .spawn() {
            Ok(x) => x,
            Err(e) => return Err(format!("Error while invoking editor: {}", e))
        };

    match process.wait() {
        Ok(_) => (),
        Err(e) => return Err(format!("Error while invoking editor: {}", e))
    };

    if match io::File::open(&Path::new(fpath)).read_to_string() {
        Ok(x) => x,
        Err(e) => return Err(format!("File can't be read after user edited it: {}", e))
    }.as_slice().trim().len() == 0 {
        return Err(format!("Contact emptied, file removed."));
    };

    Ok(())
}

fn mutt_query<'a>(config: &Configuration, query: &str) -> io::IoResult<()> {
    println!("");  // For some reason mutt requires an empty line
    for item in try!(index_query(config, query)) {
        if item.email.len() > 0 && item.name.len() > 0 {
            println!("{}\t{}\t{}", item.email, item.name, item.filepath);
        };
    };
    Ok(())
}

fn file_query<'a>(config: &Configuration, query: &str) -> io::IoResult<()> {
    for item in try!(index_query(config, query)) {
        if item.filepath.len() > 0 {
            println!("{}", item.filepath)
        };
    };
    Ok(())
}

fn email_query<'a>(config: &Configuration, query: &str) -> io::IoResult<()> {
    for item in try!(index_query(config, query)) {
        if item.name.len() > 0 && item.email.len() > 0 {
            println!("{} <{}>", item.name, item.email);
        };
    };
    Ok(())
}

pub struct Configuration {
    pub index_path: Path,
    pub vdir_path: Path,
    pub editor_cmd: String,
    pub grep_cmd: String
}

impl Configuration {
    pub fn from_env(env: Vec<(String, String)>) -> Result<Configuration, String> {
        let mut dict = HashMap::new();
        dict.extend(env.into_iter().filter(|&(_, ref v)| v.len() > 0));
        Ok(Configuration {
            index_path: match dict.remove("MATES_INDEX") {
                Some(x) => Path::new(x),
                None => match dict.get("HOME") {
                    Some(home) => {
                        os::make_absolute(&Path::new(home).join(".mates_index")).unwrap()
                    },
                    None => return Err("Unable to determine user's home directory.".to_owned())
                }
            },
            vdir_path: match dict.remove("MATES_DIR") {
                Some(x) => Path::new(x),
                None => return Err("MATES_DIR must be set to your vdir path (directory of vcf-files).".to_owned())
            },
            editor_cmd: match dict.remove("MATES_EDITOR") {
                Some(x) => x,
                None => match dict.remove("EDITOR") {
                    Some(x) => x,
                    None => return Err("MATES_EDITOR or EDITOR must be set.".to_owned())
                }
            },
            grep_cmd: match dict.remove("MATES_GREP") {
                Some(x) => x,
                None => "grep".to_owned()
            }
        })
    }

    pub fn new() -> Result<Configuration, String> {
        Configuration::from_env(os::env())
    }
}

<commit_msg>deal with filepaths in `edit` properly<commit_after>use std::os;
use std::io;
use std::collections::HashMap;
use std::io::fs::PathExtensions;
use std::borrow::ToOwned;

use atomicwrites::{AtomicFile,AllowOverwrite};

use utils::{
    Contact, add_contact_from_email, index_query, index_item_from_contact
};

macro_rules! main_try {
    ($result: expr, $errmsg: expr) => (
        match $result {
            Ok(m) => m,
            Err(e) => {
                println!("{}: {}", $errmsg, e);
                os::set_exit_status(1);
                return;
            }
        }
    )
}

fn build_index(outfile: &Path, dir: &Path) -> io::IoResult<()> {
    if !dir.is_dir() {
        return Err(io::IoError {
            kind: io::MismatchedFileTypeForOperation,
            desc: "MATES_DIR must be a directory.",
            detail: None
        });
    };

    let af = AtomicFile::new(outfile, AllowOverwrite, None);
    let entries = try!(io::fs::readdir(dir));
    let mut errors = false;

    try!(af.write(|&mut: outf| {
        for entry in entries.iter() {
            if !entry.is_file() || !entry.filename_str().unwrap_or("").ends_with(".vcf") {
                continue;
            }

            let contact = match Contact::from_file(entry.clone()) {
                Ok(x) => x,
                Err(e) => {
                    println!("Error while reading {}: {}", entry.display(), e);
                    errors = true;
                    continue
                }
            };

            match index_item_from_contact(&contact) {
                Ok(index_string) => {
                    try!(outf.write_str(index_string.as_slice()));
                },
                Err(e) => {
                    println!("Error while indexing {}: {}", entry.display(), e);
                    errors = true;
                    continue
                }
            };
        };
        Ok(())
    }));

    if errors {
        Err(io::IoError {
            kind: io::OtherIoError,
            desc: "Several errors happened while generating the index.",
            detail: None
        })
    } else {
        Ok(())
    }
}

pub fn cli_main() {
    let mut args = os::args().into_iter();
    let program = args.next().unwrap_or("mates".to_string());

    let help = format!("Usage: {} COMMAND
Commands:
    index:
        Rewrite/create the index.
    mutt-query <query>:
        Search for contact, output is usable for mutt's query_command.
    file-query <query>:
        Search for contact, return just the filename.
    email-query <query>:
        Search for contact, return \"name <email>\".
    add:
        Take mail from stdin, add sender to contacts. Print filename.
    edit <file-or-query>:
        Open contact (given by filepath or search-string) in $MATES_EDITOR. If
        the file is cleared, the contact is removed.", program);

    let print_help = |&:| {
        println!("{}", help);
    };

    let command = match args.next() {
        Some(x) => x,
        None => {
            print_help();
            os::set_exit_status(1);
            return;
        }
    };

    if command == "--help" || command == "help" || command == "-h" {
        print_help();
        return;
    }

    let config = match Configuration::new() {
        Ok(x) => x,
        Err(e) => {
            println!("Error while reading configuration: {}", e);
            os::set_exit_status(1);
            return;
        }
    };

    match command.as_slice() {
        "index" => {
            println!("Rebuilding index file \"{}\"...", config.index_path.display());
            main_try!(build_index(&config.index_path, &config.vdir_path), "Failed to build index");
        },
        "mutt-query" => {
            let query = args.next().unwrap_or("".to_string());
            main_try!(mutt_query(&config, query.as_slice()), "Failed to execute grep");
        },
        "file-query" => {
            let query = args.next().unwrap_or("".to_string());
            main_try!(file_query(&config, query.as_slice()), "Failed to execute grep");
        },
        "email-query" => {
            let query = args.next().unwrap_or("".to_string());
            main_try!(email_query(&config, query.as_slice()), "Failed to execute grep");
        },
        "add" => {
            let email = main_try!(io::stdin().lock().read_to_string(), "Failed to read email");
            let contact = main_try!(add_contact_from_email(&config.vdir_path,
                                                           email.as_slice()), "Failed to add contact");
            println!("{}", contact.path.display());

            let mut index_fp = main_try!(io::File::open_mode(
                &config.index_path,
                io::Append,
                io::Write),
                "Failed to open index"
            );

            let index_entry = main_try!(index_item_from_contact(&contact), "Failed to generate index");
            main_try!(index_fp.write_str(index_entry.as_slice()), "Failed to write to index");
        },
        "edit" => {
            let query = args.next().unwrap_or("".to_string());
            main_try!(edit_contact(&config, query.as_slice()), "Failed to edit contact");
        },
        _ => {
            println!("Invalid command: {}", command);
            print_help();
            os::set_exit_status(1);
        }
    };
}

fn edit_contact(config: &Configuration, query: &str) -> Result<(), String> {

    let results = {
        if match os::make_absolute(&Path::new(query)) {
            Ok(x) => x.is_file(),
            Err(_) => false
        } {
            vec![query.to_string()]
        } else {
            let results_iter = match index_query(config, query) {
                Ok(x) => x,
                Err(e) => return Err(format!("Error while fetching index: {}", e))
            };

            results_iter.filter_map(|x| {
                if x.filepath.len() > 0 {
                    Some(x.filepath)
                } else {
                    None
                }}).collect()
        }
    };

    if results.len() < 1 {
        return Err("No such contact.".to_string());
    } else if results.len() > 1 {
        return Err("Ambiguous query.".to_string());
    }

    let fpath = results[0].as_slice();
    let mut process = match io::Command::new("sh")
        .arg("-c")
        // clear stdin, http://unix.stackexchange.com/a/77593
        .arg(format!("$0 -- \"$1\" < $2"))
        .arg(config.editor_cmd.as_slice())
        .arg(fpath)
        .arg("/dev/tty")
        .stdin(io::process::InheritFd(0))
        .stdout(io::process::InheritFd(1))
        .stderr(io::process::InheritFd(2))
        .spawn() {
            Ok(x) => x,
            Err(e) => return Err(format!("Error while invoking editor: {}", e))
        };

    match process.wait() {
        Ok(_) => (),
        Err(e) => return Err(format!("Error while invoking editor: {}", e))
    };

    if match io::File::open(&Path::new(fpath)).read_to_string() {
        Ok(x) => x,
        Err(e) => return Err(format!("File can't be read after user edited it: {}", e))
    }.as_slice().trim().len() == 0 {
        return Err(format!("Contact emptied, file removed."));
    };

    Ok(())
}

fn mutt_query<'a>(config: &Configuration, query: &str) -> io::IoResult<()> {
    println!("");  // For some reason mutt requires an empty line
    for item in try!(index_query(config, query)) {
        if item.email.len() > 0 && item.name.len() > 0 {
            println!("{}\t{}\t{}", item.email, item.name, item.filepath);
        };
    };
    Ok(())
}

fn file_query<'a>(config: &Configuration, query: &str) -> io::IoResult<()> {
    for item in try!(index_query(config, query)) {
        if item.filepath.len() > 0 {
            println!("{}", item.filepath)
        };
    };
    Ok(())
}

fn email_query<'a>(config: &Configuration, query: &str) -> io::IoResult<()> {
    for item in try!(index_query(config, query)) {
        if item.name.len() > 0 && item.email.len() > 0 {
            println!("{} <{}>", item.name, item.email);
        };
    };
    Ok(())
}

pub struct Configuration {
    pub index_path: Path,
    pub vdir_path: Path,
    pub editor_cmd: String,
    pub grep_cmd: String
}

impl Configuration {
    pub fn from_env(env: Vec<(String, String)>) -> Result<Configuration, String> {
        let mut dict = HashMap::new();
        dict.extend(env.into_iter().filter(|&(_, ref v)| v.len() > 0));
        Ok(Configuration {
            index_path: match dict.remove("MATES_INDEX") {
                Some(x) => Path::new(x),
                None => match dict.get("HOME") {
                    Some(home) => {
                        os::make_absolute(&Path::new(home).join(".mates_index")).unwrap()
                    },
                    None => return Err("Unable to determine user's home directory.".to_owned())
                }
            },
            vdir_path: match dict.remove("MATES_DIR") {
                Some(x) => Path::new(x),
                None => return Err("MATES_DIR must be set to your vdir path (directory of vcf-files).".to_owned())
            },
            editor_cmd: match dict.remove("MATES_EDITOR") {
                Some(x) => x,
                None => match dict.remove("EDITOR") {
                    Some(x) => x,
                    None => return Err("MATES_EDITOR or EDITOR must be set.".to_owned())
                }
            },
            grep_cmd: match dict.remove("MATES_GREP") {
                Some(x) => x,
                None => "grep".to_owned()
            }
        })
    }

    pub fn new() -> Result<Configuration, String> {
        Configuration::from_env(os::env())
    }
}

<|endoftext|>


<commit_before>pub mod ffi;

use std::result;

use libc::c_char;

const NGX_OK:        ffi::ngx_int_t =  0;
const NGX_ERROR:     ffi::ngx_int_t = -1;
const NGX_AGAIN:     ffi::ngx_int_t = -2;
const NGX_BUSY:      ffi::ngx_int_t = -3;
const NGX_DONE:      ffi::ngx_int_t = -4;
const NGX_DECLINED:  ffi::ngx_int_t = -5;
const NGX_ABORT:     ffi::ngx_int_t = -6;

pub type Result = result::Result<(), ffi::ngx_int_t>;

pub struct Connection {
   raw: *mut ffi::ngx_connection_t,
}

impl Connection {
   pub fn new(raw: *mut ffi::ngx_connection_t) -> Self {
      Connection {
         raw: raw
      }
   }

   pub fn log(&self) -> Option<Log> {
      let raw = unsafe { (*self.raw).log };

      if raw.is_null() {
         None
      } else {
         Some(
            Log::new(raw)
         )
      }
   }
}

pub struct Log {
   pub raw: *mut ffi::ngx_log_t,
}

impl Log {
   pub fn new(raw: *mut ffi::ngx_log_t) -> Self {
      Log {
         raw: raw
      }
   }
}

pub struct HttpRequest {
   raw: *mut ffi::ngx_http_request_t,
}

impl HttpRequest {
   pub fn new(raw: *mut ffi::ngx_http_request_t) -> Self {
      HttpRequest {
         raw: raw
      }
   }

   pub fn connection(&self) -> Option<Connection> {
      let raw = unsafe { (*self.raw).connection };

      if raw.is_null() {
         None
      } else {
         Some(
            Connection::new(raw)
         )
      }
   }

   pub fn headers_out(&self) -> HttpHeadersOut {
      HttpHeadersOut::new(self.raw)
   }

   pub fn http_send_header(&self) -> Result {
      let rc = unsafe { ffi::ngx_http_send_header(self.raw) };

      if rc == NGX_OK {
         Ok(())
      } else {
         Err(rc)
      }
   }
}

pub struct HttpHeadersOut {
   request_raw: *mut ffi::ngx_http_request_t,
}

impl HttpHeadersOut {
   pub fn new(request_raw: *mut ffi::ngx_http_request_t) -> Self {
      HttpHeadersOut {
         request_raw: request_raw
      }
   }

   pub fn set_status(&mut self, status: ffi::ngx_uint_t) {
      unsafe {
         (*self.request_raw).headers_out.status = status;
      };
   }

   pub fn set_content_length_n(&mut self, content_length_n: ffi::off_t) {
      unsafe {
         (*self.request_raw).headers_out.content_length_n = content_length_n;
      };
   }
}
<commit_msg>HttpHeadersOut keeping a pointer to ngx_http_headers_out_t, not the request.<commit_after>pub mod ffi;

use std::result;

use libc::c_char;

const NGX_OK:        ffi::ngx_int_t =  0;
const NGX_ERROR:     ffi::ngx_int_t = -1;
const NGX_AGAIN:     ffi::ngx_int_t = -2;
const NGX_BUSY:      ffi::ngx_int_t = -3;
const NGX_DONE:      ffi::ngx_int_t = -4;
const NGX_DECLINED:  ffi::ngx_int_t = -5;
const NGX_ABORT:     ffi::ngx_int_t = -6;

pub type Result = result::Result<(), ffi::ngx_int_t>;

pub struct Connection {
   raw: *mut ffi::ngx_connection_t,
}

impl Connection {
   pub fn new(raw: *mut ffi::ngx_connection_t) -> Self {
      Connection {
         raw: raw
      }
   }

   pub fn log(&self) -> Option<Log> {
      let raw = unsafe { (*self.raw).log };

      if raw.is_null() {
         None
      } else {
         Some(
            Log::new(raw)
         )
      }
   }
}

pub struct Log {
   pub raw: *mut ffi::ngx_log_t,
}

impl Log {
   pub fn new(raw: *mut ffi::ngx_log_t) -> Self {
      Log {
         raw: raw
      }
   }
}

pub struct HttpRequest {
   raw: *mut ffi::ngx_http_request_t,
}

impl HttpRequest {
   pub fn new(raw: *mut ffi::ngx_http_request_t) -> Self {
      HttpRequest {
         raw: raw
      }
   }

   pub fn connection(&self) -> Option<Connection> {
      let raw = unsafe { (*self.raw).connection };

      if raw.is_null() {
         None
      } else {
         Some(
            Connection::new(raw)
         )
      }
   }

   pub fn headers_out(&self) -> HttpHeadersOut {
      let raw: *mut ffi::ngx_http_headers_out_t = &mut unsafe { (*self.raw).headers_out };

      HttpHeadersOut::new(raw)
   }

   pub fn http_send_header(&self) -> Result {
      let rc = unsafe { ffi::ngx_http_send_header(self.raw) };

      if rc == NGX_OK {
         Ok(())
      } else {
         Err(rc)
      }
   }
}

pub struct HttpHeadersOut {
   raw: *mut ffi::ngx_http_headers_out_t,
}

impl HttpHeadersOut {
   pub fn new(raw: *mut ffi::ngx_http_headers_out_t) -> Self {
      HttpHeadersOut {
         raw: raw
      }
   }

   pub fn set_status(&mut self, status: ffi::ngx_uint_t) {
      unsafe {
         (*self.raw).status = status;
      };
   }

   pub fn set_content_length_n(&mut self, content_length_n: ffi::off_t) {
      unsafe {
         (*self.raw).content_length_n = content_length_n;
      };
   }
}
<|endoftext|>


<commit_before>extern crate collections;
extern crate pcre;

use collections::EnumSet;
use pcre::{CompileOption, Pcre, StudyOption};

#[test]
#[should_fail]
fn test_compile_nul() {
    // Nul bytes are not allowed in the pattern string.
    drop(Pcre::compile("\0abc"));
}

#[test]
fn test_compile_bad_pattern() {
    let err = Pcre::compile("[").unwrap_err();
    assert_eq!(err.offset(), 1u);
}

#[test]
#[should_fail]
fn test_compile_bad_pattern2() {
    drop(Pcre::compile("[").unwrap()); // Should be Err, will fail.
}

#[test]
fn test_compile_capture_count() {
    let re = Pcre::compile("(?:abc)(def)").unwrap();
    assert_eq!(re.capture_count(), 1u);
}

#[test]
fn test_exec_basic() {
    let re = Pcre::compile("^...$").unwrap();
    assert_eq!(re.capture_count(), 0u);
    let m = re.exec("abc").unwrap();
    assert_eq!(m.group(0), "abc");
}

#[test]
fn test_exec_no_match() {
    let re = Pcre::compile("abc").unwrap();
    assert!(re.exec("def").is_none());
}

#[test]
fn test_exec_nul_byte() {
    // Nul bytes *are* allowed in subject strings, however.
    let re = Pcre::compile("abc\\0def").unwrap();
    let m = re.exec("abc\0def").unwrap();
    assert_eq!(m.group(0), "abc\0def");
}

#[test]
fn test_exec_from_basic() {
    let re = Pcre::compile("abc").unwrap();
    let subject = "abcabc";
    let m1 = re.exec_from(subject, 1u).unwrap();
    assert_eq!(m1.group_start(0u), 3u);
    assert_eq!(m1.group_end(0u), 6u);
    assert_eq!(m1.group_len(0u), 3u);
    let m2 = re.exec(subject).unwrap();
    assert_eq!(m2.group_start(0u), 0u);
}

#[test]
fn test_study_basic() {
    let mut re = Pcre::compile("abc").unwrap();
    let mut study_res = re.study();
    assert!(study_res);
    // Re-study the pattern two more times (to check for leaks when the test program
    // is run through Valgrind).
    study_res = re.study();
    assert!(study_res);
    study_res = re.study();
    assert!(study_res);
}

#[test]
fn test_matches_basic() {
    let subject = "\0abc1111abcabc___ababc+a";
    let mut it = {
        let re = Pcre::compile("abc").unwrap();
        re.matches(subject)

        // The MatchIterator should retain a reference to the `pcre`.
    };

    let mut opt_m = it.next();
    assert!(opt_m.is_some());
    let mut m = opt_m.unwrap();
    assert_eq!(m.group_start(0u), 1u);
    assert_eq!(m.group_end(0u), 4u);

    let opt_m2 = it.next();
    assert!(opt_m2.is_some());
    let m2 = opt_m2.unwrap();
    assert_eq!(m2.group_start(0u), 8u);
    assert_eq!(m2.group_end(0u), 11u);
    // Verify that getting the next match has not changed the first match data.
    assert_eq!(m.group_start(0u), 1u);
    assert_eq!(m.group_end(0u), 4u);

    opt_m = it.next();
    assert!(opt_m.is_some());
    m = opt_m.unwrap();
    assert_eq!(m.group_start(0u), 11u);
    assert_eq!(m.group_end(0u), 14u);

    opt_m = it.next();
    assert!(opt_m.is_some());
    m = opt_m.unwrap();
    assert_eq!(m.group_start(0u), 19u);
    assert_eq!(m.group_end(0u), 22u);

    opt_m = it.next();
    assert!(opt_m.is_none());
}

#[test]
fn test_extra_mark() {
    let pattern = "X(*MARK:A)Y|X(*MARK:B)Z";
    let subject1 = "XY";
    let subject2 = "XZ";

    let mut compile_options: EnumSet<CompileOption> = EnumSet::empty();
    compile_options.add(pcre::Extra);

    let mut re = Pcre::compile_with_options(pattern, &compile_options).unwrap();

    // first try to get the mark from the compile to make sure it fails
    assert_eq!(re.mark(), None);

    let mut study_options: EnumSet<StudyOption> = EnumSet::empty();
    study_options.add(pcre::StudyExtraNeeded);
    study_options.add(pcre::StudyJitCompile);
    let study = re.study_with_options(&study_options);
    // Double check to make sure the study worked
    assert!(study);

    // Now after studying, we still should not be able to get the mark (since we still need
    // to set the option in the extra AND execute it)
    assert_eq!(re.mark(), None);

    // set that I am using the extra mark field
    let extra = re.enable_mark();
    // This will fail only if I didn't study first
    assert!(extra);

    // We still haven't run the pcre_exec yet so get mark should be None still
    assert_eq!(re.mark(), None);

    // Now execute and we should be able to get the mark
    let opt_m1 = re.exec(subject1);
    assert!(opt_m1.is_some());

    // It should match XY
    let m1 = opt_m1.unwrap();
    assert_eq!(m1.group(0), "XY");

    // and the marked value should be A
    let mark1 = re.mark();
    assert!(mark1.is_some());
    assert_eq!(mark1.unwrap(), "A");

    let opt_m2 = re.exec(subject2);
    assert!(opt_m2.is_some());

    let m2 = opt_m2.unwrap();
    // It should match XZ
    assert_eq!(m2.group(0), "XZ");

    // and the marked value should be B
    assert_eq!(re.mark().unwrap(), "B");
}
<commit_msg>Don't use StudyExtraNeeded<commit_after>extern crate collections;
extern crate pcre;

use collections::EnumSet;
use pcre::{CompileOption, Pcre, StudyOption};

#[test]
#[should_fail]
fn test_compile_nul() {
    // Nul bytes are not allowed in the pattern string.
    drop(Pcre::compile("\0abc"));
}

#[test]
fn test_compile_bad_pattern() {
    let err = Pcre::compile("[").unwrap_err();
    assert_eq!(err.offset(), 1u);
}

#[test]
#[should_fail]
fn test_compile_bad_pattern2() {
    drop(Pcre::compile("[").unwrap()); // Should be Err, will fail.
}

#[test]
fn test_compile_capture_count() {
    let re = Pcre::compile("(?:abc)(def)").unwrap();
    assert_eq!(re.capture_count(), 1u);
}

#[test]
fn test_exec_basic() {
    let re = Pcre::compile("^...$").unwrap();
    assert_eq!(re.capture_count(), 0u);
    let m = re.exec("abc").unwrap();
    assert_eq!(m.group(0), "abc");
}

#[test]
fn test_exec_no_match() {
    let re = Pcre::compile("abc").unwrap();
    assert!(re.exec("def").is_none());
}

#[test]
fn test_exec_nul_byte() {
    // Nul bytes *are* allowed in subject strings, however.
    let re = Pcre::compile("abc\\0def").unwrap();
    let m = re.exec("abc\0def").unwrap();
    assert_eq!(m.group(0), "abc\0def");
}

#[test]
fn test_exec_from_basic() {
    let re = Pcre::compile("abc").unwrap();
    let subject = "abcabc";
    let m1 = re.exec_from(subject, 1u).unwrap();
    assert_eq!(m1.group_start(0u), 3u);
    assert_eq!(m1.group_end(0u), 6u);
    assert_eq!(m1.group_len(0u), 3u);
    let m2 = re.exec(subject).unwrap();
    assert_eq!(m2.group_start(0u), 0u);
}

#[test]
fn test_study_basic() {
    let mut re = Pcre::compile("abc").unwrap();
    let mut study_res = re.study();
    assert!(study_res);
    // Re-study the pattern two more times (to check for leaks when the test program
    // is run through Valgrind).
    study_res = re.study();
    assert!(study_res);
    study_res = re.study();
    assert!(study_res);
}

#[test]
fn test_matches_basic() {
    let subject = "\0abc1111abcabc___ababc+a";
    let mut it = {
        let re = Pcre::compile("abc").unwrap();
        re.matches(subject)

        // The MatchIterator should retain a reference to the `pcre`.
    };

    let mut opt_m = it.next();
    assert!(opt_m.is_some());
    let mut m = opt_m.unwrap();
    assert_eq!(m.group_start(0u), 1u);
    assert_eq!(m.group_end(0u), 4u);

    let opt_m2 = it.next();
    assert!(opt_m2.is_some());
    let m2 = opt_m2.unwrap();
    assert_eq!(m2.group_start(0u), 8u);
    assert_eq!(m2.group_end(0u), 11u);
    // Verify that getting the next match has not changed the first match data.
    assert_eq!(m.group_start(0u), 1u);
    assert_eq!(m.group_end(0u), 4u);

    opt_m = it.next();
    assert!(opt_m.is_some());
    m = opt_m.unwrap();
    assert_eq!(m.group_start(0u), 11u);
    assert_eq!(m.group_end(0u), 14u);

    opt_m = it.next();
    assert!(opt_m.is_some());
    m = opt_m.unwrap();
    assert_eq!(m.group_start(0u), 19u);
    assert_eq!(m.group_end(0u), 22u);

    opt_m = it.next();
    assert!(opt_m.is_none());
}

#[test]
fn test_extra_mark() {
    let pattern = "X(*MARK:A)Y|X(*MARK:B)Z";
    let subject1 = "XY";
    let subject2 = "XZ";

    let mut compile_options: EnumSet<CompileOption> = EnumSet::empty();
    compile_options.add(pcre::Extra);

    let mut re = Pcre::compile_with_options(pattern, &compile_options).unwrap();

    // first try to get the mark from the compile to make sure it fails
    assert_eq!(re.mark(), None);

    let mut study_options: EnumSet<StudyOption> = EnumSet::empty();
    //study_options.add(pcre::StudyExtraNeeded);
    study_options.add(pcre::StudyJitCompile);
    let study = re.study_with_options(&study_options);
    // Double check to make sure the study worked
    assert!(study);

    // Now after studying, we still should not be able to get the mark (since we still need
    // to set the option in the extra AND execute it)
    assert_eq!(re.mark(), None);

    // set that I am using the extra mark field
    let extra = re.enable_mark();
    // This will fail only if I didn't study first
    assert!(extra);

    // We still haven't run the pcre_exec yet so get mark should be None still
    assert_eq!(re.mark(), None);

    // Now execute and we should be able to get the mark
    let opt_m1 = re.exec(subject1);
    assert!(opt_m1.is_some());

    // It should match XY
    let m1 = opt_m1.unwrap();
    assert_eq!(m1.group(0), "XY");

    // and the marked value should be A
    let mark1 = re.mark();
    assert!(mark1.is_some());
    assert_eq!(mark1.unwrap(), "A");

    let opt_m2 = re.exec(subject2);
    assert!(opt_m2.is_some());

    let m2 = opt_m2.unwrap();
    // It should match XZ
    assert_eq!(m2.group(0), "XZ");

    // and the marked value should be B
    assert_eq!(re.mark().unwrap(), "B");
}
<|endoftext|>


<commit_before>//! Library service providers implementation.

extern crate hyper;

use hyper::client::{Client, RequestBuilder};

/// Used to specify which provider to use to generate a short URL.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Provider {
    /// https://bn.gy provider
    BnGy,
    /// https://is.gd provider
    IsGd,
    /// https://v.gd provider
    VGd,
}

impl Provider {
    /// Converts the Provider variant into its domain name equivilant
    pub fn to_name(&self) -> &str {
        match *self {
            Provider::BnGy => "bn.gy",
            Provider::IsGd => "is.gd",
            Provider::VGd => "v.gd",
        }
    }
}

/// Returns a vector of all `Provider` variants.
pub fn providers() -> Vec<Provider> {
    vec![Provider::BnGy, Provider::IsGd, Provider::VGd]
}

fn bngy_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let iter = string.split("<ShortenedUrl>").skip(1).next();
    if iter.is_none() {
        return None
    }
    if let Some(string) = iter.unwrap().split("</ShortenedUrl>").next() {
        return Some(string.to_owned())
    }
    None
}

fn bngy_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("https://bn.gy/API.asmx/CreateUrl?real_url={}", url))
}

fn isgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn isgd_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("https://is.gd/create.php?format=simple&url={}", url))
}

fn vgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn vgd_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("http://v.gd/create.php?format=simple&url={}", url))
}

/// Parses the response from a successful request to a provider into the
/// URL-shortened string.
pub fn parse(res: &str, provider: Provider) -> Option<String> {
    match provider {
        Provider::BnGy => bngy_parse(res),
        Provider::IsGd => isgd_parse(res),
        Provider::VGd => vgd_parse(res),
    }
}

/// Prepares the Hyper client for a connection to a provider, providing the long
/// URL to be shortened.
pub fn prepare<'a>(url: &str, client: &'a Client, provider: Provider) -> RequestBuilder<'a> {
    match provider {
        Provider::BnGy => bngy_prepare(url, client),
        Provider::IsGd => isgd_prepare(url, client),
        Provider::VGd => vgd_prepare(url, client),
    }
}
<commit_msg>Added RLU provider<commit_after>//! Library service providers implementation.

extern crate hyper;

use hyper::client::{Client, RequestBuilder};

/// Used to specify which provider to use to generate a short URL.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Provider {
    /// https://bn.gy provider
    BnGy,
    /// https://is.gd provider
    IsGd,
    /// https://v.gd provider
    VGd,
    /// https://rlu.ru provider
    /// * Attention! If you send a lot of requests from one IP, it can be blocked. If you plan to add more then 100 URLs in one hour, please let the technical support know. Otherwise your IP can be blocked unexpectedly. Prior added URLs can be deleted.
    Rlu,
}

impl Provider {
    /// Converts the Provider variant into its domain name equivilant
    pub fn to_name(&self) -> &str {
        match *self {
            Provider::BnGy => "bn.gy",
            Provider::IsGd => "is.gd",
            Provider::VGd => "v.gd",
            Provider::Rlu => "rlu.ru",
        }
    }
}

/// Returns a vector of all `Provider` variants.
pub fn providers() -> Vec<Provider> {
    vec![
        Provider::BnGy,
        Provider::IsGd,
        Provider::VGd,
        Provider::Rlu,
    ]
}

fn bngy_parse(res: &str) -> Option<String> {
    if res.is_empty() {
        return None
    }
    let string = res.to_owned();
    let iter = string.split("<ShortenedUrl>").skip(1).next();
    if iter.is_none() {
        return None
    }
    if let Some(string) = iter.unwrap().split("</ShortenedUrl>").next() {
        return Some(string.to_owned())
    }
    None
}

fn bngy_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("https://bn.gy/API.asmx/CreateUrl?real_url={}", url))
}

fn isgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn isgd_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("https://is.gd/create.php?format=simple&url={}", url))
}

fn vgd_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn vgd_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("http://v.gd/create.php?format=simple&url={}", url))
}

fn rlu_parse(res: &str) -> Option<String> {
    Some(res.to_owned())
}

fn rlu_prepare<'a>(url: &str, client: &'a Client) -> RequestBuilder<'a> {
    client.get(&format!("http://rlu.ru/index.sema?a=api&link={}", url))
}

/// Parses the response from a successful request to a provider into the
/// URL-shortened string.
pub fn parse(res: &str, provider: Provider) -> Option<String> {
    match provider {
        Provider::BnGy => bngy_parse(res),
        Provider::IsGd => isgd_parse(res),
        Provider::VGd => vgd_parse(res),
        Provider::Rlu => rlu_parse(res),
    }
}

/// Prepares the Hyper client for a connection to a provider, providing the long
/// URL to be shortened.
pub fn prepare<'a>(url: &str, client: &'a Client, provider: Provider) -> RequestBuilder<'a> {
    match provider {
        Provider::BnGy => bngy_prepare(url, client),
        Provider::IsGd => isgd_prepare(url, client),
        Provider::VGd => vgd_prepare(url, client),
        Provider::Rlu => rlu_prepare(url, client),
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::collections::BTreeSet;
use std::fmt::{self, Display};

#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct Range(pub char, pub char);

impl fmt::Display for Range {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.0, self.1)
    }
}

#[derive(Debug, PartialEq, Eq)]
pub struct Set(BTreeSet<Range>);

impl fmt::Display for Set {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let Set(ref set) = *self;
        let len = BTreeSet::len(set);

        for (count, s) in set.iter().enumerate() {
            if count < len - 1 { try!(write!(f, "{}, ", s)) }
            else { return write!(f, "{}", s) }
        }

        Ok(())
    }
}

impl Set {
    pub fn new() -> Self { Set(BTreeSet::new()) }
    pub fn insert(&mut self, value: Range) {
        let mut ret = BTreeSet::new();
        // value is a complete subset of one of the other ranges.
        let mut subset = false;

        {   let Set(ref set) = *self;

            let Range(mut min_val, mut max_val) = value;
            if min_val > max_val { panic!("First value cannot be greater than the second.") }

            for &Range(min, max) in &*set {
                // value overlaps at the beginning.
                if min_val < min && max_val >= min && max_val < max { max_val = max }
                // value overlaps at the end.
                else if min_val > min && min_val <= max && max_val > max { min_val = min }
                // value is entirely contained between min and max. Insert original
                // into new array because new is a subset.
                else if min_val > min && max_val < max {
                    ret.insert(Range(min, max));
                    subset = true;
                }
                // value is a superset to the current so don't add current.
                else if min_val <= min && max_val >= max {}
                // value is disjoint with current so add current.
                else { ret.insert(Range(min, max)); }
            }

            // Insert value only when it's not a subset.
            if !subset { ret.insert(Range(min_val, max_val)); }
        }

        *self = Set(ret);
    }
    pub fn union(&mut self, value: Range) {
        if !self.0.contains(&value) { self.insert(value) }
    }
}

#[cfg(test)]
mod test {
    use super::{Range, Set};
    use std::collections::BTreeSet;

    fn generate(vec: Vec<(char, char)>) -> Set {
        let mut set = Set::new();

        for (a, b) in vec {
            set.insert(Range(a, b));
        }

        set
    }
    #[test]
    fn partial_overlap() {
        let set1 = generate(vec![('3', '5'), ('4', '6')]);
        let set2 = generate(vec![('3', '5'), ('1', '4')]);

        let mut other1 = BTreeSet::new();
        let mut other2 = BTreeSet::new();

        other1.insert(Range('3', '6'));
        other2.insert(Range('1', '5'));
        assert_eq!(Set(other1), set1);
        assert_eq!(Set(other2), set2);
    }
    #[test]
    fn subset() {
        let set = generate(vec![('1', '5'), ('2', '3')]);

        let mut other = BTreeSet::new();
        other.insert(Range('1', '5'));
        assert_eq!(Set(other), set);
    }
    #[test]
    fn superset() {
        let set = generate(vec![('3', '5'), ('2', '6')]);

        let mut other = BTreeSet::new();
        other.insert(Range('2', '6'));
        assert_eq!(Set(other), set);
    }
    #[test]
    fn disjoint() {
        let set = generate(vec![('3', '5'), ('6', '8')]);

        let mut other = BTreeSet::new();
        other.insert(Range('3', '5'));
        other.insert(Range('6', '8'));

        assert_eq!(Set(other), set);
    }
    #[test]
    #[should_panic]
    fn panic_on_decreasing_order() {
        generate(vec![('5', '3')]);
    }
}
<commit_msg>Union is between the same type<commit_after>#![allow(dead_code)]

use std::collections::BTreeSet;
use std::fmt::{self, Display};

#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
pub struct Range(pub char, pub char);

impl fmt::Display for Range {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.0, self.1)
    }
}

#[derive(Debug, PartialEq, Eq)]
pub struct Set(BTreeSet<Range>);

impl fmt::Display for Set {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let Set(ref set) = *self;
        let len = BTreeSet::len(set);

        for (count, s) in set.iter().enumerate() {
            if count < len - 1 { try!(write!(f, "{}, ", s)) }
            else { return write!(f, "{}", s) }
        }

        Ok(())
    }
}

impl Set {
    pub fn new() -> Self { Set(BTreeSet::new()) }
    pub fn insert(&mut self, value: Range) {
        let mut ret = BTreeSet::new();
        // value is a complete subset of one of the other ranges.
        let mut subset = false;

        {   let Set(ref set) = *self;

            let Range(mut min_val, mut max_val) = value;
            if min_val > max_val { panic!("First value cannot be greater than the second.") }

            for &Range(min, max) in &*set {
                // value overlaps at the beginning.
                if min_val < min && max_val >= min && max_val < max { max_val = max }
                // value overlaps at the end.
                else if min_val > min && min_val <= max && max_val > max { min_val = min }
                // value is entirely contained between min and max. Insert original
                // into new array because new is a subset.
                else if min_val > min && max_val < max {
                    ret.insert(Range(min, max));
                    subset = true;
                }
                // value is a superset to the current so don't add current.
                else if min_val <= min && max_val >= max {}
                // value is disjoint with current so add current.
                else { ret.insert(Range(min, max)); }
            }

            // Insert value only when it's not a subset.
            if !subset { ret.insert(Range(min_val, max_val)); }
        }

        *self = Set(ret);
    }
    pub fn union(&mut self, value: Self) {
        for x in value.0 { self.insert(x) }
    }
}

#[cfg(test)]
mod test {
    use super::{Range, Set};
    use std::collections::BTreeSet;

    fn generate(vec: Vec<(char, char)>) -> Set {
        let mut set = Set::new();

        for (a, b) in vec {
            set.insert(Range(a, b));
        }

        set
    }
    #[test]
    fn partial_overlap() {
        let set1 = generate(vec![('3', '5'), ('4', '6')]);
        let set2 = generate(vec![('3', '5'), ('1', '4')]);

        let mut other1 = BTreeSet::new();
        let mut other2 = BTreeSet::new();

        other1.insert(Range('3', '6'));
        other2.insert(Range('1', '5'));
        assert_eq!(Set(other1), set1);
        assert_eq!(Set(other2), set2);
    }
    #[test]
    fn subset() {
        let set = generate(vec![('1', '5'), ('2', '3')]);

        let mut other = BTreeSet::new();
        other.insert(Range('1', '5'));
        assert_eq!(Set(other), set);
    }
    #[test]
    fn superset() {
        let set = generate(vec![('3', '5'), ('2', '6')]);

        let mut other = BTreeSet::new();
        other.insert(Range('2', '6'));
        assert_eq!(Set(other), set);
    }
    #[test]
    fn disjoint() {
        let set = generate(vec![('3', '5'), ('6', '8')]);

        let mut other = BTreeSet::new();
        other.insert(Range('3', '5'));
        other.insert(Range('6', '8'));

        assert_eq!(Set(other), set);
    }
    #[test]
    #[should_panic]
    fn panic_on_decreasing_order() {
        generate(vec![('5', '3')]);
    }
}
<|endoftext|>


<commit_before>use chan::{Sender, Receiver};
use chan;
use chan_signal::Signal;
use chan_signal;

use std::collections::HashMap;
use std::fmt::{Debug, Formatter};
use std::fmt;
use std::thread::JoinHandle;
use std::thread;
use std::sync::{Arc, Mutex};
use std::time::Duration;

use Msg;
use config::Config;
use collectors::{Collector, Error};
use collectors::Id;
use bosun::{Bosun, BosunRequest, Metadata, Sample};

pub fn run(collectors: Vec<Box<Collector + Send>>, config: &Config) -> () {
    let signal = chan_signal::notify(&[Signal::INT, Signal::TERM]);
    let timer = chan::tick(Duration::from_secs(TICK_INTERVAL_SEC));
    info!("Scheduler thread started.");

    let (to_main_tx, from_runners_rx) = chan::async();
    let controllers = create_controllers(collectors, to_main_tx);
    info!("Loaded {} collectors: {:#?}", controllers.len(), controllers);

    let (to_bosun_tx, from_main_rx) = chan::async();
    let bosun_thread = if config.DontSend.or(Some(false)).unwrap() {
        None
    } else {
        let bosun = Bosun::new(&config.Host, &config.Hostname, &config.Tags, from_main_rx);
        Some(bosun.spawn())
    };

    event_loop(&controllers,
               &signal,
               &timer,
               &from_runners_rx,
               &to_bosun_tx);

    // TODO: Generalize tear_down for all threads / JoinHandles
    tear_down(controllers);
    to_bosun_tx.send(BosunRequest::Shutdown);
    if let Some(thread) = bosun_thread {
        let _ = thread.join();
    }

    info!("Scheduler thread finished.");
}

static TICK_INTERVAL_SEC: u64 = 15u64;

#[derive(Debug)]
enum CollectorRequest {
    Helo,
    Init,
    Metadata,
    Sample,
    Shutdown,
}

#[derive(Debug)]
enum CollectorResponse {
    Id(Id),
    Metadata(Metadata),
    Sample(Sample),
    CollectionError(Error)
}

/**
* Handle for Main Thread to communicate with CollectorRunner
**/
struct CollectorController {
    id: Id,
    runner_tx: Sender<CollectorRequest>,
    runner_thread: Option<JoinHandle<()>>,
}

impl Debug for CollectorController {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "CollectorController {{ id: {:#?} }}", self.id)
    }
}

impl CollectorController {
    fn new(id: Id, runner_tx: Sender<CollectorRequest>) -> CollectorController {
        CollectorController {
            id: id,
            runner_tx: runner_tx,
            runner_thread: None,
        }
    }
}

/**
* Periodically runs the collector <T>
**/
struct CollectorRunner {
    id: Id,
    runner_rx: Receiver<CollectorRequest>,
    controller_tx: Sender<Msg<CollectorResponse>>,
    collector: Arc<Mutex<Box<Collector + Send>>>,
}

impl CollectorRunner {
    fn new(id: Id,
           runner_rx: Receiver<CollectorRequest>,
           controller_tx: Sender<Msg<CollectorResponse>>,
           collector: Box<Collector + Send>)
           -> CollectorRunner {
        CollectorRunner {
            id: id,
            runner_rx: runner_rx,
            controller_tx: controller_tx,
            collector: Arc::new(Mutex::new(collector)),
        }
    }

    fn spawn(mut self) -> JoinHandle<()> {
        thread::spawn(move || {
            info!("CollectorRunner {} thread started.", self.id);
            loop {
                let message = self.runner_rx.recv();
                match message {
                    Some(CollectorRequest::Helo) => {
                        debug!("CollectorRunner {} received 'Helo' message.", &self.id);
                        self.controller_tx.send(
                            Msg::Collector(self.id.clone(),CollectorResponse::Id(self.id.clone())));
                    },
                    Some(CollectorRequest::Init) => {
                        // TODO: Add failure management exp backoff timer to wait before reconnecting.
                        let exp_backoff = 10;
                        debug!("CollectorRunner {} received 'Init' message. Waiting {} sec.", &self.id, exp_backoff);
                        thread::sleep(Duration::from_secs(exp_backoff));
                        let collector = self.collector.clone();
                        let mut collector = collector.lock().unwrap();
                        match collector.init() {
                            Ok(_) => {
                                info!("CollectorRunner {} successfully re-initialized collector.", &self.id);
                            },
                            Err(_) => {
                                error!("CollectorRunner {} failed to re-initialize collector.", &self.id);
                            }
                        }
                    },
                    Some(CollectorRequest::Metadata) => {
                        debug!("CollectorRunner {} received 'Metadata' message.", &self.id);
                        self.collect_metadata();
                    },
                    Some(CollectorRequest::Sample) => {
                        debug!("CollectorRunner {} received 'Sample' message.", &self.id);
                        self.collect_sample();
                    },
                    Some(CollectorRequest::Shutdown) => {
                        debug!("CollectorRunner {} received 'Shutdown' message.", &self.id);
                        let collector = self.collector.clone();
                        let mut collector = collector.lock().unwrap();
                        collector.shutdown();
                        self.controller_tx.send(
                            Msg::Collector(self.id.clone(),CollectorResponse::Id(self.id.clone())));
                        break;
                    },
                    None => {
                        break;
                    },
                }
            }
            info!("CollectorRunner {} thread finished.", self.id);
        })
    }

    fn collect_metadata(&mut self) {
        let collector = self.collector.clone();
        let lock = collector.try_lock();
        match lock {
            Ok(_) => {
                let id = self.id.clone();
                let tx = self.controller_tx.clone();
                let collector = self.collector.clone();
                thread::spawn(move || {
                    debug!("CollectorRunner {} spawned metadata thread.", &id);
                    let ref collector = *collector.lock().unwrap();
                    let metadata = collector.metadata();
                    for m in metadata.into_iter() {
                        tx.send(
                            Msg::Collector(id.clone(), CollectorResponse::Metadata(m)));
                    }
                    debug!("CollectorRunner {} finished metadata thread.", &id);
                });
            }
            Err(_) => {
                trace!("CollectorRunner {} metadata already running ...", &self.id);
            }
        }
    }

    fn collect_sample(&mut self) {
        let collector = self.collector.clone();
        let lock = collector.try_lock();
        match lock {
            Ok(_) => {
                let id = self.id.clone();
                let tx = self.controller_tx.clone();
                let collector = self.collector.clone();
                thread::spawn(move || {
                    debug!("CollectorRunner {} spawned sample thread.", &id);
                    let ref collector = *collector.lock().unwrap();
                    match collector.collect() {
                        Ok(samples) => {
                            for s in samples.into_iter() {
                                tx.send(
                                    Msg::Collector(id.clone(), CollectorResponse::Sample(s)));
                            }
                        },
                        Err(error) => {
                            warn!("CollectorResponse {} received collection error {}", &id, error);
                            tx.send(
                                Msg::Collector(id.clone(), CollectorResponse::CollectionError(error)));
                        }

                    }
                    debug!("CollectorRunner {} finished sample thread.", &id);
                });
            }
            Err(_) => {
                trace!("CollectorRunner {} sampling already running ...", &self.id);
            }
        }
    }
}

fn create_controllers(
    collectors: Vec<Box<Collector + Send>>,
    runners_to_main_tx: Sender<Msg<CollectorResponse>>)
    -> HashMap<String, CollectorController> {

    let mut controllers: HashMap<String, CollectorController> = HashMap::new();

    for mut c in collectors.into_iter() {
        // Initialization might be moved to collector threads?
        match c.init() {
            Ok(_) => {
                info!("Initialized collector {}", c.id());
            }
            Err(err) => {
                error!("Failed to initialize collector {}: {:?}. Adding anyway.", c.id(), err);
            }
        }

        let (to_runner_tx, from_controller_rx) = chan::async();
        let id = c.id().clone();
        let mut controller = CollectorController::new(id.clone(), to_runner_tx);
        let runner = CollectorRunner::new(id.clone(),
                                          from_controller_rx,
                                          runners_to_main_tx.clone(),
                                          c);
        let runner_thread = runner.spawn();

        controller.runner_thread = Some(runner_thread);
        controllers.insert(id, controller);}

    controllers
}

fn event_loop(threads: &HashMap<String, CollectorController>,
              signal_rx: &Receiver<Signal>,
              timer: &Receiver<Sender<()>>,
              collectors_rx: &Receiver<Msg<CollectorResponse>>,
              bosun_tx: &Sender<BosunRequest>)
              -> () {
    info!("Scheduler thread entering event loop.");

    // TODO: This should not be here.
    // Transmit metadata once.
    for cc in threads.values() {
        cc.runner_tx.send(CollectorRequest::Metadata)
    }

    loop {
        debug!("Scheduler thread event loop.");
        chan_select! {
            signal_rx.recv() => {
                break
            },
            timer.recv() => {
                trace!("Scheduler: I've been ticked.");
                for cc in threads.values() {
                    cc.runner_tx.send(CollectorRequest::Sample)
                }
            },
            collectors_rx.recv() -> message => {
                match message {
                    Some(Msg::Collector(_, CollectorResponse::Id(id))) => {
                        debug!("Scheduler received 'Helo' from collector {}.", id);
                    }
                    Some(Msg::Collector(id, CollectorResponse::Metadata(metadata))) => {
                        debug!("Scheduler received metadata from '{}' for '{}'.", &id, &metadata.metric );
                        bosun_tx.send(BosunRequest::Metadata(metadata));
                    }
                    Some(Msg::Collector(id, CollectorResponse::Sample(sample))) => {
                        debug!("Scheduler received sample from '{}' for '{}'.", &id, &sample.time );
                        bosun_tx.send(BosunRequest::Sample(sample));
                    },
                    Some(Msg::Collector(id, CollectorResponse::CollectionError(error))) => {
                        debug!("Scheduler received collection error from {} '{}'.", &id, &error);
                        // TODO: Take care of failure case
                        if let Some(cc) = threads.get(&id) {
                            cc.runner_tx.send(CollectorRequest::Init);
                        }
                    },
                    None => {
                        error!("Channel unexpectedly shut down.");
                        break
                    }
                }
            }
        };
    }
}

fn tear_down(mut threads: HashMap<String, CollectorController>) -> () {
    info!("Scheduler thread shutting down ...");
    for cc in threads.values() {
        cc.runner_tx.send(CollectorRequest::Shutdown)
    }

    info!("Scheduler thread waiting for collector threads to finish ...");
    for (_, cc) in threads.drain() {
        let jh = cc.runner_thread.unwrap();
        let _ = jh.join();
    }
}
<commit_msg>Increase re-init timeout to 60 sec<commit_after>use chan::{Sender, Receiver};
use chan;
use chan_signal::Signal;
use chan_signal;

use std::collections::HashMap;
use std::fmt::{Debug, Formatter};
use std::fmt;
use std::thread::JoinHandle;
use std::thread;
use std::sync::{Arc, Mutex};
use std::time::Duration;

use Msg;
use config::Config;
use collectors::{Collector, Error};
use collectors::Id;
use bosun::{Bosun, BosunRequest, Metadata, Sample};

pub fn run(collectors: Vec<Box<Collector + Send>>, config: &Config) -> () {
    let signal = chan_signal::notify(&[Signal::INT, Signal::TERM]);
    let timer = chan::tick(Duration::from_secs(TICK_INTERVAL_SEC));
    info!("Scheduler thread started.");

    let (to_main_tx, from_runners_rx) = chan::async();
    let controllers = create_controllers(collectors, to_main_tx);
    info!("Loaded {} collectors: {:#?}", controllers.len(), controllers);

    let (to_bosun_tx, from_main_rx) = chan::async();
    let bosun_thread = if config.DontSend.or(Some(false)).unwrap() {
        None
    } else {
        let bosun = Bosun::new(&config.Host, &config.Hostname, &config.Tags, from_main_rx);
        Some(bosun.spawn())
    };

    event_loop(&controllers,
               &signal,
               &timer,
               &from_runners_rx,
               &to_bosun_tx);

    // TODO: Generalize tear_down for all threads / JoinHandles
    tear_down(controllers);
    to_bosun_tx.send(BosunRequest::Shutdown);
    if let Some(thread) = bosun_thread {
        let _ = thread.join();
    }

    info!("Scheduler thread finished.");
}

static TICK_INTERVAL_SEC: u64 = 15u64;

#[derive(Debug)]
enum CollectorRequest {
    Helo,
    Init,
    Metadata,
    Sample,
    Shutdown,
}

#[derive(Debug)]
enum CollectorResponse {
    Id(Id),
    Metadata(Metadata),
    Sample(Sample),
    CollectionError(Error)
}

/**
* Handle for Main Thread to communicate with CollectorRunner
**/
struct CollectorController {
    id: Id,
    runner_tx: Sender<CollectorRequest>,
    runner_thread: Option<JoinHandle<()>>,
}

impl Debug for CollectorController {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "CollectorController {{ id: {:#?} }}", self.id)
    }
}

impl CollectorController {
    fn new(id: Id, runner_tx: Sender<CollectorRequest>) -> CollectorController {
        CollectorController {
            id: id,
            runner_tx: runner_tx,
            runner_thread: None,
        }
    }
}

/**
* Periodically runs the collector <T>
**/
struct CollectorRunner {
    id: Id,
    runner_rx: Receiver<CollectorRequest>,
    controller_tx: Sender<Msg<CollectorResponse>>,
    collector: Arc<Mutex<Box<Collector + Send>>>,
}

impl CollectorRunner {
    fn new(id: Id,
           runner_rx: Receiver<CollectorRequest>,
           controller_tx: Sender<Msg<CollectorResponse>>,
           collector: Box<Collector + Send>)
           -> CollectorRunner {
        CollectorRunner {
            id: id,
            runner_rx: runner_rx,
            controller_tx: controller_tx,
            collector: Arc::new(Mutex::new(collector)),
        }
    }

    fn spawn(mut self) -> JoinHandle<()> {
        thread::spawn(move || {
            info!("CollectorRunner {} thread started.", self.id);
            loop {
                let message = self.runner_rx.recv();
                match message {
                    Some(CollectorRequest::Helo) => {
                        debug!("CollectorRunner {} received 'Helo' message.", &self.id);
                        self.controller_tx.send(
                            Msg::Collector(self.id.clone(),CollectorResponse::Id(self.id.clone())));
                    },
                    Some(CollectorRequest::Init) => {
                        // TODO: Add failure management exp backoff timer to wait before reconnecting.
                        let exp_backoff = 60;
                        debug!("CollectorRunner {} received 'Init' message. Waiting {} sec.", &self.id, exp_backoff);
                        thread::sleep(Duration::from_secs(exp_backoff));
                        let collector = self.collector.clone();
                        let mut collector = collector.lock().unwrap();
                        match collector.init() {
                            Ok(_) => {
                                info!("CollectorRunner {} successfully re-initialized collector.", &self.id);
                            },
                            Err(_) => {
                                error!("CollectorRunner {} failed to re-initialize collector.", &self.id);
                            }
                        }
                    },
                    Some(CollectorRequest::Metadata) => {
                        debug!("CollectorRunner {} received 'Metadata' message.", &self.id);
                        self.collect_metadata();
                    },
                    Some(CollectorRequest::Sample) => {
                        debug!("CollectorRunner {} received 'Sample' message.", &self.id);
                        self.collect_sample();
                    },
                    Some(CollectorRequest::Shutdown) => {
                        debug!("CollectorRunner {} received 'Shutdown' message.", &self.id);
                        let collector = self.collector.clone();
                        let mut collector = collector.lock().unwrap();
                        collector.shutdown();
                        self.controller_tx.send(
                            Msg::Collector(self.id.clone(),CollectorResponse::Id(self.id.clone())));
                        break;
                    },
                    None => {
                        break;
                    },
                }
            }
            info!("CollectorRunner {} thread finished.", self.id);
        })
    }

    fn collect_metadata(&mut self) {
        let collector = self.collector.clone();
        let lock = collector.try_lock();
        match lock {
            Ok(_) => {
                let id = self.id.clone();
                let tx = self.controller_tx.clone();
                let collector = self.collector.clone();
                thread::spawn(move || {
                    debug!("CollectorRunner {} spawned metadata thread.", &id);
                    let ref collector = *collector.lock().unwrap();
                    let metadata = collector.metadata();
                    for m in metadata.into_iter() {
                        tx.send(
                            Msg::Collector(id.clone(), CollectorResponse::Metadata(m)));
                    }
                    debug!("CollectorRunner {} finished metadata thread.", &id);
                });
            }
            Err(_) => {
                trace!("CollectorRunner {} metadata already running ...", &self.id);
            }
        }
    }

    fn collect_sample(&mut self) {
        let collector = self.collector.clone();
        let lock = collector.try_lock();
        match lock {
            Ok(_) => {
                let id = self.id.clone();
                let tx = self.controller_tx.clone();
                let collector = self.collector.clone();
                thread::spawn(move || {
                    debug!("CollectorRunner {} spawned sample thread.", &id);
                    let ref collector = *collector.lock().unwrap();
                    match collector.collect() {
                        Ok(samples) => {
                            for s in samples.into_iter() {
                                tx.send(
                                    Msg::Collector(id.clone(), CollectorResponse::Sample(s)));
                            }
                        },
                        Err(error) => {
                            warn!("CollectorResponse {} received collection error {}", &id, error);
                            tx.send(
                                Msg::Collector(id.clone(), CollectorResponse::CollectionError(error)));
                        }

                    }
                    debug!("CollectorRunner {} finished sample thread.", &id);
                });
            }
            Err(_) => {
                trace!("CollectorRunner {} sampling already running ...", &self.id);
            }
        }
    }
}

fn create_controllers(
    collectors: Vec<Box<Collector + Send>>,
    runners_to_main_tx: Sender<Msg<CollectorResponse>>)
    -> HashMap<String, CollectorController> {

    let mut controllers: HashMap<String, CollectorController> = HashMap::new();

    for mut c in collectors.into_iter() {
        // Initialization might be moved to collector threads?
        match c.init() {
            Ok(_) => {
                info!("Initialized collector {}", c.id());
            }
            Err(err) => {
                error!("Failed to initialize collector {}: {:?}. Adding anyway.", c.id(), err);
            }
        }

        let (to_runner_tx, from_controller_rx) = chan::async();
        let id = c.id().clone();
        let mut controller = CollectorController::new(id.clone(), to_runner_tx);
        let runner = CollectorRunner::new(id.clone(),
                                          from_controller_rx,
                                          runners_to_main_tx.clone(),
                                          c);
        let runner_thread = runner.spawn();

        controller.runner_thread = Some(runner_thread);
        controllers.insert(id, controller);}

    controllers
}

fn event_loop(threads: &HashMap<String, CollectorController>,
              signal_rx: &Receiver<Signal>,
              timer: &Receiver<Sender<()>>,
              collectors_rx: &Receiver<Msg<CollectorResponse>>,
              bosun_tx: &Sender<BosunRequest>)
              -> () {
    info!("Scheduler thread entering event loop.");

    // TODO: This should not be here.
    // Transmit metadata once.
    for cc in threads.values() {
        cc.runner_tx.send(CollectorRequest::Metadata)
    }

    loop {
        debug!("Scheduler thread event loop.");
        chan_select! {
            signal_rx.recv() => {
                break
            },
            timer.recv() => {
                trace!("Scheduler: I've been ticked.");
                for cc in threads.values() {
                    cc.runner_tx.send(CollectorRequest::Sample)
                }
            },
            collectors_rx.recv() -> message => {
                match message {
                    Some(Msg::Collector(_, CollectorResponse::Id(id))) => {
                        debug!("Scheduler received 'Helo' from collector {}.", id);
                    }
                    Some(Msg::Collector(id, CollectorResponse::Metadata(metadata))) => {
                        debug!("Scheduler received metadata from '{}' for '{}'.", &id, &metadata.metric );
                        bosun_tx.send(BosunRequest::Metadata(metadata));
                    }
                    Some(Msg::Collector(id, CollectorResponse::Sample(sample))) => {
                        debug!("Scheduler received sample from '{}' for '{}'.", &id, &sample.time );
                        bosun_tx.send(BosunRequest::Sample(sample));
                    },
                    Some(Msg::Collector(id, CollectorResponse::CollectionError(error))) => {
                        debug!("Scheduler received collection error from {} '{}'.", &id, &error);
                        // TODO: Take care of failure case
                        if let Some(cc) = threads.get(&id) {
                            cc.runner_tx.send(CollectorRequest::Init);
                        }
                    },
                    None => {
                        error!("Channel unexpectedly shut down.");
                        break
                    }
                }
            }
        };
    }
}

fn tear_down(mut threads: HashMap<String, CollectorController>) -> () {
    info!("Scheduler thread shutting down ...");
    for cc in threads.values() {
        cc.runner_tx.send(CollectorRequest::Shutdown)
    }

    info!("Scheduler thread waiting for collector threads to finish ...");
    for (_, cc) in threads.drain() {
        let jh = cc.runner_thread.unwrap();
        let _ = jh.join();
    }
}
<|endoftext|>


<commit_before>// Loosely based on zlib-licensed code from RustAllegro
//     https://github.com/SiegeLord/RustAllegro
//
// Implements efficient, type-safe flags with support for bitwise operators.
//
// Usage:
//
// flag_type!(FlagTypeName {
//     FlagName1 = FlagValue1,
//     FlagName2 = FlagValue2,
//     ...
//     FlagNameN = FlagValueN
// })
//
// fn foo(flag: FlagTypeName) {
//     let raw = (flag | FlagNameN).get();
//     bar(raw);
// }

#![macro_escape]

macro_rules! flag_type(
    ($typename:ident { $($name:ident = $value:expr),* }) => {
        pub struct $typename {
            bits: u32
        }

        impl $typename {
            #[inline]
            pub fn new(bits: u32) -> $typename {
                $typename { bits: bits }
            }

            #[inline]
            pub fn get(self) -> u32 {
                self.bits
            }
        }

        impl ::std::default::Default for $typename {
            fn default() -> $typename {
                $typename::new(0)
            }
        }

        impl ::std::cmp::Eq for $typename {
            fn eq(&self, other: &$typename) -> bool {
                self.bits == other.bits
            }
        }

        impl ::std::cmp::TotalEq for $typename {}

        impl ::std::cmp::Ord for $typename {
            fn lt(&self, other: &$typename) -> bool {
                self.bits < other.bits
            }
        }

        impl ::std::cmp::TotalOrd for $typename {
            fn cmp(&self, other: &$typename) -> Ordering {
                self.bits.cmp(&other.bits)
            }
        }

        impl ::std::ops::BitAnd<$typename, $typename> for $typename {
            fn bitand(&self, rhs: &$typename) -> $typename {
                $typename { bits: self.bits & rhs.bits }
            }
        }

        impl ::std::ops::BitOr<$typename, $typename> for $typename {
            fn bitor(&self, rhs: &$typename) -> $typename {
                $typename { bits: self.bits | rhs.bits }
            }
        }

        impl ::std::ops::BitXor<$typename, $typename> for $typename {
            fn bitxor(&self, rhs: &$typename) -> $typename {
                $typename { bits: self.bits ^ rhs.bits }
            }
        }

        $(
            pub static $name: $typename = $typename { bits: $value };
        )+
    }
)
<commit_msg>Support all bitwise operations on flags<commit_after>// Loosely based on zlib-licensed code from RustAllegro
//     https://github.com/SiegeLord/RustAllegro
//
// Implements efficient, type-safe flags with support for bitwise operators.
//
// Usage:
//
// flag_type!(FlagTypeName {
//     FlagName1 = FlagValue1,
//     FlagName2 = FlagValue2,
//     ...
//     FlagNameN = FlagValueN
// })
//
// fn foo(flag: FlagTypeName) {
//     let raw = (flag | FlagNameN).get();
//     bar(raw);
// }

#![macro_escape]

macro_rules! flag_type(
    ($typename:ident { $($name:ident = $value:expr),* }) => {
        pub struct $typename {
            bits: u32
        }

        impl $typename {
            #[inline]
            pub fn new(bits: u32) -> $typename {
                $typename { bits: bits }
            }

            #[inline]
            pub fn get(self) -> u32 {
                self.bits
            }
        }

        impl ::std::default::Default for $typename {
            fn default() -> $typename {
                $typename::new(0)
            }
        }

        impl ::std::cmp::Eq for $typename {
            fn eq(&self, other: &$typename) -> bool {
                self.bits == other.bits
            }
        }

        impl ::std::cmp::TotalEq for $typename {}

        impl ::std::cmp::Ord for $typename {
            fn lt(&self, other: &$typename) -> bool {
                self.bits < other.bits
            }
        }

        impl ::std::cmp::TotalOrd for $typename {
            fn cmp(&self, other: &$typename) -> Ordering {
                self.bits.cmp(&other.bits)
            }
        }

        impl ::std::ops::Not<$typename> for $typename {
            fn not(&self) -> $typename {
                $typename { bits: !self.bits }
            }
        }

        impl ::std::ops::BitAnd<$typename, $typename> for $typename {
            fn bitand(&self, rhs: &$typename) -> $typename {
                $typename { bits: self.bits & rhs.bits }
            }
        }

        impl ::std::ops::BitOr<$typename, $typename> for $typename {
            fn bitor(&self, rhs: &$typename) -> $typename {
                $typename { bits: self.bits | rhs.bits }
            }
        }

        impl ::std::ops::BitXor<$typename, $typename> for $typename {
            fn bitxor(&self, rhs: &$typename) -> $typename {
                $typename { bits: self.bits ^ rhs.bits }
            }
        }

        impl ::std::ops::Shl<u32, $typename> for $typename {
            fn shl(&self, rhs: &u32) -> $typename {
                $typename { bits: self.bits << *rhs }
            }
        }

        impl ::std::ops::Shr<u32, $typename> for $typename {
            fn shr(&self, rhs: &u32) -> $typename {
                $typename { bits: self.bits >> *rhs }
            }
        }

        $(
            pub static $name: $typename = $typename { bits: $value };
        )+
    }
)
<|endoftext|>


<commit_before>pub type TxnId = u64;

pub enum TxnOp {
  Put(~[u8], ~[u8]),
  Delete(~[u8]),
}

pub struct Txn {
  ops: Vec<TxnOp>,
}

impl Txn {
  pub fn new() -> Txn {
    Txn{
      ops: Vec::new(),
    }
  }

  pub fn put(&mut self, key: ~[u8], value: ~[u8]) {
    self.ops.push(Put(key, value));
  }

  pub fn delete(&mut self, key: ~[u8]) {
    self.ops.push(Delete(key));
  }
}
<commit_msg>Accidentally recommitted the txn module.<commit_after><|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;
extern crate docopt;
extern crate image;
extern crate gpx;
extern crate quick_xml;

use std::fs;
use std::fs::File;
use std::io::BufReader;
use std::path;

use docopt::Docopt;
use gpx::read;
use gpx::Gpx;
use image::ImageBuffer;

const USAGE: &'static str = "
Generate video from GPX files.

Usage:
  derivers <top-lat> <left-lng> <bottom-lat> <right-lng> <width> <height> <directory>
";

#[derive(Debug, Deserialize)]
struct CommandArgs {
    arg_top_lat: f64,
    arg_left_lng: f64,
    arg_bottom_lat: f64,
    arg_right_lng: f64,
    arg_width: u32,
    arg_height: u32,
    arg_directory: String
}

fn parse_gpx(path: &path::Path) -> () {
}

fn main() {
    let args: CommandArgs = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());

    println!("{:?}", args);

    let paths = fs::read_dir(args.arg_directory).unwrap();
    for path in paths {
        let file_name = path.unwrap().path();
        let file = File::open(file_name.clone()).unwrap();
        let reader = BufReader::new(file);

        let gpx: Gpx = read(reader).unwrap();

        println!("Reading GPX file: {:?}", file_name.display());
    }
}
<commit_msg>Start parsing out fields from GPX files<commit_after>#[macro_use]
extern crate serde_derive;
extern crate docopt;
extern crate image;
extern crate gpx;
extern crate time;

use std::fs;
use std::fs::File;
use std::io::BufReader;
use std::path;

use docopt::Docopt;
use gpx::read;
use gpx::{Gpx, Track};
use image::ImageBuffer;

const USAGE: &'static str = "
Generate video from GPX files.

Usage:
  derivers <top-lat> <left-lng> <bottom-lat> <right-lng> <width> <height> <directory>
";

#[derive(Debug, Deserialize)]
struct CommandArgs {
    arg_top_lat: f64,
    arg_left_lng: f64,
    arg_bottom_lat: f64,
    arg_right_lng: f64,
    arg_width: u32,
    arg_height: u32,
    arg_directory: String,
}

#[derive(Debug)]
struct Activity {
    name: String,
    date: time::Tm,
    track_points: Vec<(f64, f64)>,
}

fn parse_gpx(path: &path::Path) -> Option<Activity> {
    let file = File::open(path).unwrap();
    let reader = BufReader::new(file);

    let gpx: Gpx = read(reader).unwrap();

    // Nothing to do if there are no tracks
    if gpx.tracks.len() == 0 {
        return None;
    } else if gpx.tracks.len() > 1 {
        println!("Warning! more than 1 track, just taking first");
    }

    let track: &Track = &gpx.tracks[0];

    let mut activity = Activity {
        name: String::from("unnamed"),
        date: time::empty_tm(),
        track_points: vec![],
    };

    if let Some(ref name) = track.name {
        activity.name = name.clone();
    }

    if let Some(metadata) = gpx.metadata {

        if let Some(_time) = metadata.time {
            // FIXME: update this
            activity.date = time::now();
        }
    }

    Some(activity)
}

fn main() {
    let args: CommandArgs = Docopt::new(USAGE)
        .and_then(|d| d.deserialize())
        .unwrap_or_else(|e| e.exit());

    println!("{:?}", args);

    let dir_entry = fs::read_dir(args.arg_directory).unwrap();
    let files: Vec<path::PathBuf> = dir_entry.map(|p| p.unwrap().path()).collect();

    for path in files {
        println!("Reading GPX file: {:?}", path);

        let activity = parse_gpx(path.as_path());
        println!("Activity: {:?}", activity);
    }
}
<|endoftext|>