<commit_before>#[macro_use]
extern crate serenity;
extern crate chrono;
extern crate rand;
extern crate time;
#[macro_use(object)] extern crate json;

use std::string::*;
use serenity::model::*;
use serenity::Result as SerenityResult;
use serenity::Client;
use serenity::framework::standard::help_commands;
use serenity::framework::StandardFramework;
use serenity::client::{EventHandler,Context, CACHE};
use std::env;
use std::ascii::AsciiExt;
use std::time::{SystemTime, UNIX_EPOCH};
use serenity::model::permissions::Permissions;
use std::path::Path;
use std::path::PathBuf;

mod commands;

struct Handler;

impl EventHandler for Handler {
    fn on_ready(&self, ctx: Context, ready: Ready) {
        	println!("{} is connected!", ready.user.name);
		ctx.set_game_name("lelcp.github.io/bot");
	}
	fn on_message(&self, _: Context, message: Message) {
		let guild_id = match CACHE.read().unwrap().guild_channel(message.channel_id) {
			Some(channel) => channel.read().unwrap().guild_id,
			None => {
				check_msg(message.channel_id.say(&"Groups and DMs not supported"));
				return ();
			},
		};
		if !message.author.bot {
			if message.content.to_ascii_lowercase().contains("thx") || message.content.to_ascii_lowercase().contains("thank"){
				let start = SystemTime::now();
	    			let since_the_epoch = start.duration_since(UNIX_EPOCH)
	       			.expect("Time went backwards");
	       			if message.mentions.len() > 0 {
				if since_the_epoch.as_secs() >= commands::pierogi::time_pierogi(&message.author.id.to_string(),&guild_id.to_string()) {
					let mut msg: String = "".to_string();
						for mention in message.mentions {
							if message.author.id != mention.id {
								msg = format!("{} <@{}>",msg,mention.id);
								let pierogi = commands::pierogi::read_pierogi(&mention.id.to_string(),&guild_id.to_string());
								commands::pierogi::new_pierogi(&mention.id.to_string(), &guild_id.to_string(), pierogi + 1, commands::pierogi::time_pierogi(&mention.id.to_string(),&guild_id.to_string()));
								commands::pierogi::new_pierogi(&message.author.id.to_string(), &guild_id.to_string(), commands::pierogi::read_pierogi(&message.author.id.to_string(),&guild_id.to_string()), since_the_epoch.as_secs() + 7140);
							}
						}
						if msg != "".to_string() {
							check_msg(message.channel_id.say(&format!("You recived thank you pieróg {}",msg)));
						}
					}
					else {
						check_msg(message.channel_id.say(format!("<@{}>, I know your mommy told you to thank as much as you can, but this is too much",message.author.id)));
					}
				}
			}
			let home = env::var("XDG_DATA_HOME")
				.expect("Expected a token in the environment");
			if Path::new(&format!("{}/.lcpae/commands/{}/{}.json", home, guild_id, message.content)).exists() {
				let path = PathBuf::from(&format!("{}/.lcpae/commands/{}/{}.json", home, guild_id, message.content));
				let text = commands::misc::read_to_string(&path);
				let parsed = json::parse(&text).unwrap();
				if parsed["image"].as_str().unwrap() != "" {
					let _ = message.channel_id.send_message(|m| m
						.embed(|e| e
						.image(parsed["image"].as_str().unwrap())
					));
				}
				if parsed["text"].as_str().unwrap() != "" {
					check_msg(message.channel_id.say(&parsed["text"].as_str().unwrap()));
				}
			}
		}
	}
}

fn main() {

	let token = env::var("DISCORD_TOKEN")
		.expect("Expected a token in the environment");
	let mut client = Client::new(&token, Handler);
	client.with_framework(StandardFramework::new()
		.before(|_ctx, msg, _cmd_name| {
			println!("{} in {}: {}", msg.author.id, msg.channel_id, msg.content);
			true
		})
		.after(|_ctx, _msg, cmd_name, error| {
			if let Err(why) = error {
				println!("Error in {}: {:?}", cmd_name, why);
			}
		})
		.bucket("basic", 5, 60, 3)
		.configure(|c| c
			.prefix("!")
			.on_mention(true)
			.case_insensitivity(true))
		.group("Miscellaneous", |g| g
			.command("gnu", |c| c
				.desc("GNU Interjection copypasta")
				.usage("<GNU replacement> <Linux replacement>")
				.exec(commands::misc::gnu))
			.command("whiteface", |c| c
				.desc("This is not the gif on the internet")
				.exec(commands::misc::whiteface))
			.command("godtellmeyourways", |c| c
				.desc("Quote God himself, Richard Matthew Stallman")
				.exec(commands::misc::god))
			.command("donkey", |c| c
				.desc("Show current bot time and set nickname and playing message")
				.exec(commands::misc::donkey)))
		.group("Useful shit", |g| g
			.command("ddg", |c| c
				.desc("Powerful search with embeds")
				.usage("<search terms>")
				.exec(commands::useful::ddg))
			.command("emoji", |c| c
				.desc(":regional_indicator_s::regional_indicator_p::regional_indicator_e::regional_indicator_a::regional_indicator_k:   :regional_indicator_i::regional_indicator_n:   :regional_indicator_e::regional_indicator_m::regional_indicator_o::regional_indicator_j::regional_indicator_i:")
				.usage("<your text>")
				.bucket("basic")
				.exec(commands::useful::emoji))
			.command("info", |c| c
				.desc("Distro database")
				.usage("<distro name>")
				.exec(commands::useful::info))
			.command("wget", |c| c
				.desc("Sends wget script")
				.usage("<amount of messages in hundreds to download from channel>")
				.exec(commands::useful::wget)))
		.group("About bot", |g| g
			.command("github", |c| c
				.desc("Shilling open source nature of this project")
				.exec(commands::about::github))
			.command("rust", |c| c
				.desc("Shilling rust nature of this project")
				.exec(commands::about::rust))
			.command("lcpae", |c| c
				.exec_help(help_commands::with_embeds)))
		.group("Tux", |g| g
			.command("roasted", |c| c
				.desc("Daaaaaamn!")
				.exec(commands::tux::roasted))
			.command("hypertux", |c| c
				.desc("Laugh all you want")
				.exec(commands::tux::hypertux))
			.command("hyperthink", |c| c
				.desc("TFW hacked mainframe")
				.exec(commands::tux::hyperthink)))
		.group("Admin", |g| g
			.required_permissions(Permissions::ADMINISTRATOR)
			.command("clear", |c| c
				.desc("Clean previous messages")
				.exec(commands::admin::clear))
			.command("ccommand", |c| c
				.desc("Custom commands")
				.exec(commands::admin::ccommand)))
		.group("Pierogi", |g| g
			.prefix("pierog")
			.command("score", |c| c
				.desc("Check your own score")
				.exec(commands::pierogi::score))
			.command("steal", |c| c
				.desc("Steal pierogi, but be careful")
				.exec(commands::pierogi::steal))
			.command("give", |c| c
				.desc("Steal pierogi, but be careful")
				.exec(commands::pierogi::give))

		));
	let _ = client.start().map_err(|why| println!("Client ended: {:?}", why));
}

fn check_msg(result: SerenityResult<Message>) {
	if let Err(why) = result {
		println!("Error sending message: {:?}", why);
	}
}
<commit_msg>This is the last I promise<commit_after>#[macro_use]
extern crate serenity;
extern crate chrono;
extern crate rand;
extern crate time;
#[macro_use(object)] extern crate json;

use std::string::*;
use serenity::model::*;
use serenity::Result as SerenityResult;
use serenity::Client;
use serenity::framework::standard::help_commands;
use serenity::framework::StandardFramework;
use serenity::client::{EventHandler,Context, CACHE};
use std::env;
use std::ascii::AsciiExt;
use std::time::{SystemTime, UNIX_EPOCH};
use serenity::model::permissions::Permissions;
use std::path::Path;
use std::path::PathBuf;

mod commands;

struct Handler;

impl EventHandler for Handler {
    fn on_ready(&self, ctx: Context, ready: Ready) {
        	println!("{} is connected!", ready.user.name);
		ctx.set_game_name("lelcp.github.io/bot");
	}
	fn on_message(&self, _: Context, message: Message) {
		let guild_id = match CACHE.read().unwrap().guild_channel(message.channel_id) {
			Some(channel) => channel.read().unwrap().guild_id,
			None => {
				check_msg(message.channel_id.say(&"Groups and DMs not supported"));
				return ();
			},
		};
		if !message.author.bot {
			if message.content.to_ascii_lowercase().contains("thx") || message.content.to_ascii_lowercase().contains("thank"){
				let start = SystemTime::now();
	    			let since_the_epoch = start.duration_since(UNIX_EPOCH)
	       			.expect("Time went backwards");
	       			if message.mentions.len() > 0 {
				if since_the_epoch.as_secs() >= commands::pierogi::time_pierogi(&message.author.id.to_string(),&guild_id.to_string()) {
					let mut msg: String = "".to_string();
						for mention in message.mentions {
							if message.author.id != mention.id {
								msg = format!("{} <@{}>",msg,mention.id);
								let pierogi = commands::pierogi::read_pierogi(&mention.id.to_string(),&guild_id.to_string());
								commands::pierogi::new_pierogi(&mention.id.to_string(), &guild_id.to_string(), pierogi + 1, commands::pierogi::time_pierogi(&mention.id.to_string(),&guild_id.to_string()));
								commands::pierogi::new_pierogi(&message.author.id.to_string(), &guild_id.to_string(), commands::pierogi::read_pierogi(&message.author.id.to_string(),&guild_id.to_string()), since_the_epoch.as_secs() + 7140);
							}
						}
						if msg != "".to_string() {
							check_msg(message.channel_id.say(&format!("You recived thank you pieróg {}",msg)));
						}
					}
					else {
						check_msg(message.channel_id.say(format!("<@{}>, I know your mommy told you to thank as much as you can, but this is too much",message.author.id)));
					}
				}
			}
			let home = env::var("HOME")
				.expect("Expected a token in the environment");
			if Path::new(&format!("{}/.lcpae/commands/{}/{}.json", home, guild_id, message.content)).exists() {
				let path = PathBuf::from(&format!("{}/.lcpae/commands/{}/{}.json", home, guild_id, message.content));
				let text = commands::misc::read_to_string(&path);
				let parsed = json::parse(&text).unwrap();
				if parsed["image"].as_str().unwrap() != "" {
					let _ = message.channel_id.send_message(|m| m
						.embed(|e| e
						.image(parsed["image"].as_str().unwrap())
					));
				}
				if parsed["text"].as_str().unwrap() != "" {
					check_msg(message.channel_id.say(&parsed["text"].as_str().unwrap()));
				}
			}
		}
	}
}

fn main() {

	let token = env::var("DISCORD_TOKEN")
		.expect("Expected a token in the environment");
	let mut client = Client::new(&token, Handler);
	client.with_framework(StandardFramework::new()
		.before(|_ctx, msg, _cmd_name| {
			println!("{} in {}: {}", msg.author.id, msg.channel_id, msg.content);
			true
		})
		.after(|_ctx, _msg, cmd_name, error| {
			if let Err(why) = error {
				println!("Error in {}: {:?}", cmd_name, why);
			}
		})
		.bucket("basic", 5, 60, 3)
		.configure(|c| c
			.prefix("!")
			.on_mention(true)
			.case_insensitivity(true))
		.group("Miscellaneous", |g| g
			.command("gnu", |c| c
				.desc("GNU Interjection copypasta")
				.usage("<GNU replacement> <Linux replacement>")
				.exec(commands::misc::gnu))
			.command("whiteface", |c| c
				.desc("This is not the gif on the internet")
				.exec(commands::misc::whiteface))
			.command("godtellmeyourways", |c| c
				.desc("Quote God himself, Richard Matthew Stallman")
				.exec(commands::misc::god))
			.command("donkey", |c| c
				.desc("Show current bot time and set nickname and playing message")
				.exec(commands::misc::donkey)))
		.group("Useful shit", |g| g
			.command("ddg", |c| c
				.desc("Powerful search with embeds")
				.usage("<search terms>")
				.exec(commands::useful::ddg))
			.command("emoji", |c| c
				.desc(":regional_indicator_s::regional_indicator_p::regional_indicator_e::regional_indicator_a::regional_indicator_k:   :regional_indicator_i::regional_indicator_n:   :regional_indicator_e::regional_indicator_m::regional_indicator_o::regional_indicator_j::regional_indicator_i:")
				.usage("<your text>")
				.bucket("basic")
				.exec(commands::useful::emoji))
			.command("info", |c| c
				.desc("Distro database")
				.usage("<distro name>")
				.exec(commands::useful::info))
			.command("wget", |c| c
				.desc("Sends wget script")
				.usage("<amount of messages in hundreds to download from channel>")
				.exec(commands::useful::wget)))
		.group("About bot", |g| g
			.command("github", |c| c
				.desc("Shilling open source nature of this project")
				.exec(commands::about::github))
			.command("rust", |c| c
				.desc("Shilling rust nature of this project")
				.exec(commands::about::rust))
			.command("lcpae", |c| c
				.exec_help(help_commands::with_embeds)))
		.group("Tux", |g| g
			.command("roasted", |c| c
				.desc("Daaaaaamn!")
				.exec(commands::tux::roasted))
			.command("hypertux", |c| c
				.desc("Laugh all you want")
				.exec(commands::tux::hypertux))
			.command("hyperthink", |c| c
				.desc("TFW hacked mainframe")
				.exec(commands::tux::hyperthink)))
		.group("Admin", |g| g
			.required_permissions(Permissions::ADMINISTRATOR)
			.command("clear", |c| c
				.desc("Clean previous messages")
				.exec(commands::admin::clear))
			.command("ccommand", |c| c
				.desc("Custom commands")
				.exec(commands::admin::ccommand)))
		.group("Pierogi", |g| g
			.prefix("pierog")
			.command("score", |c| c
				.desc("Check your own score")
				.exec(commands::pierogi::score))
			.command("steal", |c| c
				.desc("Steal pierogi, but be careful")
				.exec(commands::pierogi::steal))
			.command("give", |c| c
				.desc("Steal pierogi, but be careful")
				.exec(commands::pierogi::give))

		));
	let _ = client.start().map_err(|why| println!("Client ended: {:?}", why));
}

fn check_msg(result: SerenityResult<Message>) {
	if let Err(why) = result {
		println!("Error sending message: {:?}", why);
	}
}
<|endoftext|>


<commit_before>#![recursion_limit = "256"]

extern crate clipboard;
extern crate ndarray;
extern crate ropey;
extern crate termion;
extern crate unicode_segmentation;
extern crate unicode_width;
#[macro_use]
extern crate delegate;
extern crate syntect;

mod command;
mod data;
mod view;

use command::State;
use data::{Recorded, Select, Text};
use std::env;
use std::io::stdin;
use syntect::dumps::from_binary;
use syntect::highlighting::Theme;
use syntect::parsing::SyntaxSet;
use termion::input::TermRead;
use view::View;

fn main() {
    let args = env::args();

    if args.len() > 1 {
        for filename in args.skip(1) {
            edit_file(&Some(filename));
        }
    } else {
        edit_file(&None);
    }
}

fn edit_file(filename: &Option<String>) {
    let ps = SyntaxSet::load_defaults_nonewlines();
    let ts: Theme = from_binary(include_bytes!("../assets/gruvbox.themedump"));
    let mut text = build_text(&filename);
    let mut view = build_view(&filename, &ps, &ts);
    let mut state = State::Insert;

    let stdin = stdin();

    view.render(&text);

    let mut events = stdin.events();
    loop {
        if let Some(event) = events.next() {
            state = match state.handle(&mut text, &mut view, event.unwrap()) {
                Some(state) => state,
                None => break,
            }
        }

        view.render(&text);
    }
}

fn build_text(filename: &Option<String>) -> Select<Recorded<Text>> {
    Select::new(Recorded::new(match filename {
        Some(name) => match Text::open_file(name.clone()) {
            Ok(v) => v,
            Err(e) => panic!("{}", e),
        },
        None => Text::empty(),
    }))
}

fn build_view<'a>(filename: &Option<String>, ps: &'a SyntaxSet, theme: &'a Theme) -> View<'a> {
    let syntax = match filename {
        Some(filename) => ps
            .find_syntax_for_file(filename)
            .unwrap()
            .unwrap_or_else(|| ps.find_syntax_plain_text()),
        None => ps.find_syntax_plain_text(),
    };

    View::new(theme, syntax, ps)
}
<commit_msg>Fix #22<commit_after>#![recursion_limit = "256"]

extern crate clipboard;
extern crate ndarray;
extern crate ropey;
extern crate termion;
extern crate unicode_segmentation;
extern crate unicode_width;
#[macro_use]
extern crate delegate;
extern crate syntect;

mod command;
mod data;
mod view;

use command::State;
use data::{Recorded, Select, Text};
use std::env;
use std::io::stdin;
use syntect::dumps::from_binary;
use syntect::highlighting::Theme;
use syntect::parsing::SyntaxSet;
use termion::input::TermRead;
use view::View;

fn main() {
    let args = env::args();

    if args.len() > 1 {
        for filename in args.skip(1) {
            edit_file(&Some(filename));
        }
    } else {
        edit_file(&None);
    }
}

fn edit_file(filename: &Option<String>) {
    let ps = SyntaxSet::load_defaults_nonewlines();
    let ts: Theme = from_binary(include_bytes!("../assets/gruvbox.themedump"));
    let mut text = build_text(&filename);
    let mut view = build_view(&filename, &ps, &ts);
    let mut state = State::Insert;

    let stdin = stdin();

    view.render(&text);

    let mut events = stdin.events();
    loop {
        if let Some(event) = events.next() {
            state = match state.handle(&mut text, &mut view, event.unwrap()) {
                Some(state) => state,
                None => break,
            }
        }

        view.render(&text);
    }
}

fn build_text(filename: &Option<String>) -> Select<Recorded<Text>> {
    Select::new(Recorded::new(match filename {
        Some(name) => match Text::open_file(name.clone()) {
            Ok(v) => v,
            Err(e) => panic!("{}", e),
        },
        None => Text::empty(),
    }))
}

fn build_view<'a>(filename: &Option<String>, ps: &'a SyntaxSet, theme: &'a Theme) -> View<'a> {
    let syntax = match filename {
        Some(filename) => match ps.find_syntax_for_file(filename) {
            Ok(Some(syn)) => syn,
            _ => ps.find_syntax_plain_text(),
        },
        None => ps.find_syntax_plain_text(),
    };

    View::new(theme, syntax, ps)
}
<|endoftext|>


<commit_before>use alloc::vec::Vec;
use core::str;
use target_lexicon::Architecture;

use crate::endian::LittleEndian as LE;
use crate::pe;
use crate::pod::Bytes;
use crate::read::{
    self, FileFlags, Object, ObjectSection, ReadError, Result, SectionIndex, Symbol, SymbolIndex,
    SymbolMap,
};

use super::{
    parse_symbol, CoffSection, CoffSectionIterator, CoffSegment, CoffSegmentIterator,
    CoffSymbolIterator, SectionTable, SymbolTable,
};

/// A COFF object file.
#[derive(Debug)]
pub struct CoffFile<'data> {
    pub(super) header: &'data pe::ImageFileHeader,
    pub(super) sections: SectionTable<'data>,
    // TODO: ImageSymbolExBytes
    pub(super) symbols: SymbolTable<'data>,
    pub(super) data: Bytes<'data>,
}

impl<'data> CoffFile<'data> {
    /// Parse the raw COFF file data.
    pub fn parse(data: &'data [u8]) -> Result<Self> {
        let data = Bytes(data);
        let mut tail = data;
        let header = tail
            .read::<pe::ImageFileHeader>()
            .read_error("Invalid COFF file header size or alignment")?;

        // Skip over the optional header and get the section headers.
        tail.skip(header.size_of_optional_header.get(LE) as usize)
            .read_error("Invalid COFF optional header size")?;
        let sections = SectionTable::parse(header, tail)?;
        let symbols = SymbolTable::parse(header, data)?;

        // TODO: maybe validate that the machine is known?
        Ok(CoffFile {
            header,
            sections,
            symbols,
            data,
        })
    }
}

impl<'data> read::private::Sealed for CoffFile<'data> {}

impl<'data, 'file> Object<'data, 'file> for CoffFile<'data>
where
    'data: 'file,
{
    type Segment = CoffSegment<'data, 'file>;
    type SegmentIterator = CoffSegmentIterator<'data, 'file>;
    type Section = CoffSection<'data, 'file>;
    type SectionIterator = CoffSectionIterator<'data, 'file>;
    type SymbolIterator = CoffSymbolIterator<'data, 'file>;

    fn architecture(&self) -> Architecture {
        match self.header.machine.get(LE) {
            pe::IMAGE_FILE_MACHINE_I386 => Architecture::I386,
            pe::IMAGE_FILE_MACHINE_AMD64 => Architecture::X86_64,
            _ => Architecture::Unknown,
        }
    }

    #[inline]
    fn is_little_endian(&self) -> bool {
        true
    }

    #[inline]
    fn is_64(&self) -> bool {
        false
    }

    fn segments(&'file self) -> CoffSegmentIterator<'data, 'file> {
        CoffSegmentIterator {
            file: self,
            iter: self.sections.iter(),
        }
    }

    fn section_by_name(&'file self, section_name: &str) -> Option<CoffSection<'data, 'file>> {
        self.sections()
            .find(|section| section.name() == Ok(section_name))
    }

    fn section_by_index(&'file self, index: SectionIndex) -> Result<CoffSection<'data, 'file>> {
        let section = self.sections.section(index.0)?;
        Ok(CoffSection {
            file: self,
            index,
            section,
        })
    }

    fn sections(&'file self) -> CoffSectionIterator<'data, 'file> {
        CoffSectionIterator {
            file: self,
            iter: self.sections.iter().enumerate(),
        }
    }

    fn symbol_by_index(&self, index: SymbolIndex) -> Result<Symbol<'data>> {
        let symbol = self
            .symbols
            .get(index.0)
            .read_error("Invalid COFF symbol index")?;
        Ok(parse_symbol(&self.symbols, index.0, symbol))
    }

    fn symbols(&'file self) -> CoffSymbolIterator<'data, 'file> {
        CoffSymbolIterator {
            symbols: &self.symbols,
            index: 0,
        }
    }

    fn dynamic_symbols(&'file self) -> CoffSymbolIterator<'data, 'file> {
        CoffSymbolIterator {
            symbols: &self.symbols,
            // Hack: don't return any.
            index: self.symbols.len(),
        }
    }

    fn symbol_map(&self) -> SymbolMap<'data> {
        // TODO: untested
        let mut symbols: Vec<_> = self
            .symbols()
            .map(|(_, s)| s)
            .filter(SymbolMap::filter)
            .collect();
        symbols.sort_by_key(|x| x.address);
        SymbolMap { symbols }
    }

    fn has_debug_symbols(&self) -> bool {
        self.section_by_name(".debug_info").is_some()
    }

    #[inline]
    fn entry(&self) -> u64 {
        0
    }

    fn flags(&self) -> FileFlags {
        FileFlags::Coff {
            characteristics: self.header.characteristics.get(LE),
        }
    }
}
<commit_msg>read/coff: add ImageFileHeader::parse<commit_after>use alloc::vec::Vec;
use core::str;
use target_lexicon::Architecture;

use crate::endian::LittleEndian as LE;
use crate::pe;
use crate::pod::Bytes;
use crate::read::{
    self, FileFlags, Object, ObjectSection, ReadError, Result, SectionIndex, Symbol, SymbolIndex,
    SymbolMap,
};

use super::{
    parse_symbol, CoffSection, CoffSectionIterator, CoffSegment, CoffSegmentIterator,
    CoffSymbolIterator, SectionTable, SymbolTable,
};

/// A COFF object file.
#[derive(Debug)]
pub struct CoffFile<'data> {
    pub(super) header: &'data pe::ImageFileHeader,
    pub(super) sections: SectionTable<'data>,
    // TODO: ImageSymbolExBytes
    pub(super) symbols: SymbolTable<'data>,
    pub(super) data: Bytes<'data>,
}

impl<'data> CoffFile<'data> {
    /// Parse the raw COFF file data.
    pub fn parse(data: &'data [u8]) -> Result<Self> {
        let data = Bytes(data);
        let (header, tail) = pe::ImageFileHeader::parse(data)?;
        let sections = header.sections(tail)?;
        let symbols = header.symbols(data)?;

        Ok(CoffFile {
            header,
            sections,
            symbols,
            data,
        })
    }
}

impl<'data> read::private::Sealed for CoffFile<'data> {}

impl<'data, 'file> Object<'data, 'file> for CoffFile<'data>
where
    'data: 'file,
{
    type Segment = CoffSegment<'data, 'file>;
    type SegmentIterator = CoffSegmentIterator<'data, 'file>;
    type Section = CoffSection<'data, 'file>;
    type SectionIterator = CoffSectionIterator<'data, 'file>;
    type SymbolIterator = CoffSymbolIterator<'data, 'file>;

    fn architecture(&self) -> Architecture {
        match self.header.machine.get(LE) {
            pe::IMAGE_FILE_MACHINE_I386 => Architecture::I386,
            pe::IMAGE_FILE_MACHINE_AMD64 => Architecture::X86_64,
            _ => Architecture::Unknown,
        }
    }

    #[inline]
    fn is_little_endian(&self) -> bool {
        true
    }

    #[inline]
    fn is_64(&self) -> bool {
        false
    }

    fn segments(&'file self) -> CoffSegmentIterator<'data, 'file> {
        CoffSegmentIterator {
            file: self,
            iter: self.sections.iter(),
        }
    }

    fn section_by_name(&'file self, section_name: &str) -> Option<CoffSection<'data, 'file>> {
        self.sections()
            .find(|section| section.name() == Ok(section_name))
    }

    fn section_by_index(&'file self, index: SectionIndex) -> Result<CoffSection<'data, 'file>> {
        let section = self.sections.section(index.0)?;
        Ok(CoffSection {
            file: self,
            index,
            section,
        })
    }

    fn sections(&'file self) -> CoffSectionIterator<'data, 'file> {
        CoffSectionIterator {
            file: self,
            iter: self.sections.iter().enumerate(),
        }
    }

    fn symbol_by_index(&self, index: SymbolIndex) -> Result<Symbol<'data>> {
        let symbol = self
            .symbols
            .get(index.0)
            .read_error("Invalid COFF symbol index")?;
        Ok(parse_symbol(&self.symbols, index.0, symbol))
    }

    fn symbols(&'file self) -> CoffSymbolIterator<'data, 'file> {
        CoffSymbolIterator {
            symbols: &self.symbols,
            index: 0,
        }
    }

    fn dynamic_symbols(&'file self) -> CoffSymbolIterator<'data, 'file> {
        CoffSymbolIterator {
            symbols: &self.symbols,
            // Hack: don't return any.
            index: self.symbols.len(),
        }
    }

    fn symbol_map(&self) -> SymbolMap<'data> {
        // TODO: untested
        let mut symbols: Vec<_> = self
            .symbols()
            .map(|(_, s)| s)
            .filter(SymbolMap::filter)
            .collect();
        symbols.sort_by_key(|x| x.address);
        SymbolMap { symbols }
    }

    fn has_debug_symbols(&self) -> bool {
        self.section_by_name(".debug_info").is_some()
    }

    #[inline]
    fn entry(&self) -> u64 {
        0
    }

    fn flags(&self) -> FileFlags {
        FileFlags::Coff {
            characteristics: self.header.characteristics.get(LE),
        }
    }
}

impl pe::ImageFileHeader {
    /// Read the DOS header.
    ///
    /// The given data must be for the entire file.  Returns the data following the optional
    /// header, which will contain the section headers.
    pub fn parse<'data>(mut data: Bytes<'data>) -> read::Result<(&'data Self, Bytes<'data>)> {
        let header = data
            .read::<pe::ImageFileHeader>()
            .read_error("Invalid COFF file header size or alignment")?;

        // Skip over the optional header.
        data.skip(header.size_of_optional_header.get(LE) as usize)
            .read_error("Invalid COFF optional header size")?;

        // TODO: maybe validate that the machine is known?
        Ok((header, data))
    }

    /// Read the section table.
    ///
    /// `tail` must be the data following the optional header.
    #[inline]
    fn sections<'data>(&self, tail: Bytes<'data>) -> read::Result<SectionTable<'data>> {
        SectionTable::parse(self, tail)
    }

    /// Read the symbol table and string table.
    ///
    /// `data` must be the entire file data.
    #[inline]
    fn symbols<'data>(&self, data: Bytes<'data>) -> read::Result<SymbolTable<'data>> {
        SymbolTable::parse(self, data)
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::collections::HashMap;

extern crate clap;
use clap::{Arg, App, SubCommand};
extern crate toml;

extern crate reqwest;
use reqwest::header::Authorization;

extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

extern crate glob;
use glob::glob;

extern crate libc;
#[derive(Deserialize, Debug)]
struct Config {
    token: String,
    org: String,
    team: String,
    #[serde(default="default_endpoint")]
    endpoint: String,
    #[serde(default="default_home")]
    home: String,
    #[serde(default="default_gid")]
    gid: u64,
    #[serde(default="default_sh")]
    sh: String,
    group: Option<String>,
    #[serde(default="default_cache_duration")]
    cache_duration: u64,
    #[serde(default="default_cert_path")]
    cert_path: String
}

fn default_endpoint() -> String { String::from("https://api.github.com") }
fn default_home() -> String { String::from("/home/{}") }
fn default_gid() -> u64 { 2000 }
fn default_sh() -> String { String::from("/bin/bash") }
fn default_cache_duration() -> u64 { 3600 }
fn default_cert_path() -> String { String::from("/etc/ssl/certs/ca-certificates.crt") }

#[derive(Serialize, Deserialize, Debug)]
struct Team {
    id: u64,
    name: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct Member {
    id: u64,
    login: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct PublicKey {
    id: u64,
    key: String,
}

#[derive(Debug)]
enum CliError {
    Serde(serde_json::Error),
    Reqwest(reqwest::Error),
    Io(std::io::Error),
}

impl From<serde_json::Error> for CliError {fn from(err: serde_json::Error) -> CliError { CliError::Serde(err) }}
impl From<reqwest::Error> for CliError {fn from(err: reqwest::Error) -> CliError { CliError::Reqwest(err) }}
impl From<std::io::Error> for CliError {fn from(err: std::io::Error) -> CliError { CliError::Io(err) }}

fn main() {

    let matches = App::new("ghteam-auth")
                      .version("0.1")
                      .author("Yasuyuki YAMADA <yasuyuki.ymd@gmail.com>")
                      .about("")
                      .arg(Arg::with_name("config")
                               .short("c")
                               .long("config")
                               .value_name("FILE")
                               .help("Sets a custom config file (toml)")
                               .takes_value(true))
                      .arg(Arg::with_name("v")
                               .short("v")
                               .multiple(true)
                               .help("Sets the level of verbosity"))
                      .subcommand(SubCommand::with_name("key")
                                             .about("get user public key")
                                             .arg(Arg::with_name("USER")
                                                      .required(true)
                                                      .index(1)
                                                      .help("user name")))
                      .subcommand(SubCommand::with_name("pam")
                                             .about("get user public key")
                                             .arg(Arg::with_name("USER")
                                                      .required(false)
                                                      .index(1)
                                                      .help("user name")))
                      .subcommand(SubCommand::with_name("passwd")
                                             .about("get passwd"))
                      .subcommand(SubCommand::with_name("shadow")
                                             .about("get shadow"))
                      .subcommand(SubCommand::with_name("group")
                                             .about("get group"))
                      .subcommand(SubCommand::with_name("refresh")
                                             .about("refresh cache"))
                      .get_matches();

    let config = matches.value_of("config").unwrap_or("/etc/ghteam-auth.conf");
    let mut file = File::open(config).unwrap();
    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();
    let config = toml::from_str::<Config>(contents.as_str()).unwrap();

    match std::env::var("SSL_CERT_FILE") {
        Ok(_) => (),
        Err(_) => std::env::set_var("SSL_CERT_FILE", config.cert_path.clone()),
    }

    let client = reqwest::Client::new().unwrap();
    let client = GithubClient::new(client, config);

    if let Some(matches) = matches.subcommand_matches("key") {
        client.print_user_public_key(matches.value_of("USER").unwrap()).unwrap();
    } else if let Some(_) = matches.subcommand_matches("passwd") {
        client.get_passwd().unwrap();
    } else if let Some(_) = matches.subcommand_matches("shadow") {
        client.get_shadow().unwrap();
    } else if let Some(_) = matches.subcommand_matches("group") {
        client.get_group().unwrap();
    } else if let Some(_) = matches.subcommand_matches("refresh") {
        client.clear_all_caches().unwrap();
    } else if let Some(_) = matches.subcommand_matches("pam") {
        match std::env::var("PAM_USER") {
            Ok(user) => {
                if client.check_pam(&user).unwrap() { std::process::exit(0); }
                else { std::process::exit(1) }
            }
            Err(e) => println!("couldn't interpret PAM_USER: {}", e),
        }
    }

}

struct GithubClient {
    client: reqwest::Client,
    conf: Config
}

impl GithubClient {
    fn new(client:reqwest::Client, conf:Config) -> GithubClient {
        GithubClient {client:client, conf:conf}
    }

    fn load_content_from_cache(&self, url:&String) -> Result<(std::fs::Metadata,String),CliError> {
        let mut path = std::env::temp_dir();
        path.push("ghteam-auth-cache");
        path.push(url.as_str());
        let metadata = std::fs::metadata(path.to_str().unwrap())?;
        let mut f = File::open(path.to_str().unwrap())?;
        let mut content = String::new();
        f.read_to_string(&mut content)?;
        Ok((metadata,content))
    }

    fn store_content_to_cache(&self, url:&String, content:&String) -> Result<(),CliError> {
        let mut path = std::env::temp_dir();
        path.push("ghteam-auth-cache");
        path.push(url.as_str());
        let mut dirpath = path.clone(); dirpath.pop();
        std::fs::create_dir_all(dirpath)?;
        let mut f = File::create(path.to_str().unwrap())?;
        f.write(content.as_bytes())?;
        Ok(())
    }

    fn get_content_from_url(&self, url:&String) -> Result<String,CliError> {
        let token = String::from("token ") + self.conf.token.clone().as_str();
        let res = self.client.get(url.as_str()).header(Authorization(token)).send();
        let mut content = String::new();
        res?.read_to_string(&mut content)?;
        self.store_content_to_cache(url,&content)?;
        Ok(content)
    }

    fn get_content(&self, url:&String) -> Result<String,CliError> {
        match self.load_content_from_cache(url) {
            Ok((metadata,cache_content)) => {
                match std::time::SystemTime::now().duration_since(metadata.modified()?) {
                    Ok(caching_duration) => {
                        if caching_duration.as_secs() > self.conf.cache_duration {
                            match self.get_content_from_url(url) {
                                Ok(content_from_url) => Ok(content_from_url),
                                Err(_) => Ok(cache_content)
                            }
                        } else {
                            Ok(cache_content)
                        }
                    },
                    Err(_) => {
                        Ok(cache_content)
                    }
                }
            },
            Err(_) => self.get_content_from_url(url)
        }
    }

    fn print_user_public_key(&self, user:&str) -> Result<(), CliError> {
        let keys = self.get_user_public_key(user)?;
        println!("{}", keys);
        Ok(())
    }

    fn get_user_public_key(&self, user:&str) -> Result<String, CliError> {
        let url = format!("{}/users/{}/keys", self.conf.endpoint, user);
        let content = self.get_content(&url);
        let keys = serde_json::from_str::<Vec<PublicKey>>(content?.as_str())?;
        Ok(keys.iter().map(|k|{k.key.clone()}).collect::<Vec<String>>().join("\n"))
    }

    fn check_pam(&self, user:&String) -> Result<bool, CliError> {
        let teams:HashMap<String,Team> = self.get_teams()?;
        if let Some(team) = teams.get(&self.conf.team.clone()) {
            for member in self.get_members(team.id)? {
                if member.login==*user { return Ok(true) }
            }
        }
        Ok(false)
    }

    fn get_passwd(&self) -> Result<(), CliError> {
        let teams:HashMap<String,Team> = self.get_teams()?;
        if let Some(team) = teams.get(&self.conf.team.clone()) {
            for member in self.get_members(team.id)? {
                println!("{}", self.create_passwd_line(&member));
            }
            Ok(())
        } else {
            Ok(())
        }
    }

    fn get_shadow(&self) -> Result<(), CliError> {
        let teams:HashMap<String,Team> = self.get_teams()?;
        if let Some(team) = teams.get(&self.conf.team.clone()) {
            for member in self.get_members(team.id)? {
                println!("{}", self.create_shadow_line(&member));
            }
            Ok(())
        } else {
            Ok(())
        }
    }

    fn get_group(&self) -> Result<(), CliError> {
        let teams:HashMap<String,Team> = self.get_teams()?;
        if let Some(team) = teams.get(&self.conf.team.clone()) {
            let members = self.get_members(team.id)?;
            println!("{}", self.create_group_line(&team.name, self.conf.gid, &members));
            Ok(())
        } else {
            Ok(())
        }
    }

    fn create_passwd_line(&self, member:&Member) -> String {
        format!("{login}:x:{uid}:{gid}:user@{org}:{home}:{sh}",
                login=member.login,
                uid=member.id,
                gid=self.conf.gid,
                org=self.conf.org,
                home=self.conf.home.replace("{}",member.login.as_str()),
                sh=self.conf.sh,
                )
    }

    fn create_shadow_line(&self, member:&Member) -> String {
        format!("{login}:!!:::::::", login=member.login )
    }

    fn create_group_line(&self, name:&String, id:u64, members:&Vec<Member>) -> String {
        format!("{name}:x:{id}:{members}", name=name, id=id,
                members=members.iter().map(|m|{m.login.clone()}).collect::<Vec<String>>().join(","))
    }

    fn get_teams(&self) -> Result<HashMap<String,Team>, CliError> {
        let url = format!("{}/orgs/{}/teams",self.conf.endpoint, self.conf.org);
        let content = self.get_content(&url)?;
        let teams = serde_json::from_str::<Vec<Team>>(content.as_str())?;
        let mut team_map = HashMap::new();
        for team in teams { team_map.insert(team.name.clone(), team); }
        Ok(team_map)
    }

    fn get_members(&self, mid:u64) -> Result<Vec<Member>, CliError> {
        let url = format!("{}/teams/{}/members",self.conf.endpoint.clone(), mid);
        let content = self.get_content(&url)?;
        let members = serde_json::from_str::<Vec<Member>>(content.as_str())?;
        Ok(members)
    }

    fn clear_all_caches(&self) -> Result<(), CliError> {
        let mut path = std::env::temp_dir();
        path.push("ghteam-auth-cache");
        path.push("**");
        path.push("*");
        for entry in glob(&path.to_str().unwrap()).unwrap() {
            match entry {
                Ok(path) => {if path.is_file() {std::fs::remove_file(path)?}},
                Err(e) => println!("{:?}", e),
            }
        }
        Ok(())
    }

}

#[repr(C)]
#[allow(missing_copy_implementations)]
pub struct Passwd {
    name:   *mut libc::c_char,
    pass:   *mut libc::c_char,
    uid:    libc::uid_t,
    gid:    libc::gid_t,
    gecos:  *mut libc::c_char,
    home:   *mut libc::c_char,
    sh:     *mut libc::c_char,
}
<commit_msg>Refactor creation of client<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::collections::HashMap;

extern crate clap;
use clap::{Arg, App, SubCommand};
extern crate toml;

extern crate reqwest;
use reqwest::header::Authorization;

extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

extern crate glob;
use glob::glob;

extern crate libc;
#[derive(Deserialize, Debug)]
struct Config {
    token: String,
    org: String,
    team: String,
    #[serde(default="default_endpoint")]
    endpoint: String,
    #[serde(default="default_home")]
    home: String,
    #[serde(default="default_gid")]
    gid: u64,
    #[serde(default="default_sh")]
    sh: String,
    group: Option<String>,
    #[serde(default="default_cache_duration")]
    cache_duration: u64,
    #[serde(default="default_cert_path")]
    cert_path: String
}

fn default_endpoint() -> String { String::from("https://api.github.com") }
fn default_home() -> String { String::from("/home/{}") }
fn default_gid() -> u64 { 2000 }
fn default_sh() -> String { String::from("/bin/bash") }
fn default_cache_duration() -> u64 { 3600 }
fn default_cert_path() -> String { String::from("/etc/ssl/certs/ca-certificates.crt") }

#[derive(Serialize, Deserialize, Debug)]
struct Team {
    id: u64,
    name: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct Member {
    id: u64,
    login: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct PublicKey {
    id: u64,
    key: String,
}

#[derive(Debug)]
enum CliError {
    Serde(serde_json::Error),
    Reqwest(reqwest::Error),
    Io(std::io::Error),
}

impl From<serde_json::Error> for CliError {fn from(err: serde_json::Error) -> CliError { CliError::Serde(err) }}
impl From<reqwest::Error> for CliError {fn from(err: reqwest::Error) -> CliError { CliError::Reqwest(err) }}
impl From<std::io::Error> for CliError {fn from(err: std::io::Error) -> CliError { CliError::Io(err) }}

fn main() {

    let matches = App::new("ghteam-auth")
                      .version("0.1")
                      .author("Yasuyuki YAMADA <yasuyuki.ymd@gmail.com>")
                      .about("")
                      .arg(Arg::with_name("config")
                               .short("c")
                               .long("config")
                               .value_name("FILE")
                               .help("Sets a custom config file (toml)")
                               .takes_value(true))
                      .arg(Arg::with_name("v")
                               .short("v")
                               .multiple(true)
                               .help("Sets the level of verbosity"))
                      .subcommand(SubCommand::with_name("key")
                                             .about("get user public key")
                                             .arg(Arg::with_name("USER")
                                                      .required(true)
                                                      .index(1)
                                                      .help("user name")))
                      .subcommand(SubCommand::with_name("pam")
                                             .about("get user public key")
                                             .arg(Arg::with_name("USER")
                                                      .required(false)
                                                      .index(1)
                                                      .help("user name")))
                      .subcommand(SubCommand::with_name("passwd")
                                             .about("get passwd"))
                      .subcommand(SubCommand::with_name("shadow")
                                             .about("get shadow"))
                      .subcommand(SubCommand::with_name("group")
                                             .about("get group"))
                      .subcommand(SubCommand::with_name("refresh")
                                             .about("refresh cache"))
                      .get_matches();

    let configpath = matches.value_of("config").unwrap_or("/etc/ghteam-auth.conf");
    let client = create_github_client(configpath).unwrap();

    if let Some(matches) = matches.subcommand_matches("key") {
        client.print_user_public_key(matches.value_of("USER").unwrap()).unwrap();
    } else if let Some(_) = matches.subcommand_matches("passwd") {
        client.get_passwd().unwrap();
    } else if let Some(_) = matches.subcommand_matches("shadow") {
        client.get_shadow().unwrap();
    } else if let Some(_) = matches.subcommand_matches("group") {
        client.get_group().unwrap();
    } else if let Some(_) = matches.subcommand_matches("refresh") {
        client.clear_all_caches().unwrap();
    } else if let Some(_) = matches.subcommand_matches("pam") {
        match std::env::var("PAM_USER") {
            Ok(user) => {
                if client.check_pam(&user).unwrap() { std::process::exit(0); }
                else { std::process::exit(1) }
            }
            Err(e) => println!("couldn't interpret PAM_USER: {}", e),
        }
    }

}

fn create_github_client( configpath: &str ) -> Result<GithubClient, CliError> {
    let mut file = File::open(configpath)?;
    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();
    let config = toml::from_str::<Config>(contents.as_str()).unwrap();
    match std::env::var("SSL_CERT_FILE") {
        Ok(_) => (),
        Err(_) => std::env::set_var("SSL_CERT_FILE", config.cert_path.clone()),
    }
    let client = reqwest::Client::new()?;
    Ok(GithubClient::new(client, config))
}

struct GithubClient {
    client: reqwest::Client,
    conf: Config
}

impl GithubClient {
    fn new(client:reqwest::Client, conf:Config) -> GithubClient {
        GithubClient {client:client, conf:conf}
    }

    fn load_content_from_cache(&self, url:&String) -> Result<(std::fs::Metadata,String),CliError> {
        let mut path = std::env::temp_dir();
        path.push("ghteam-auth-cache");
        path.push(url.as_str());
        let metadata = std::fs::metadata(path.to_str().unwrap())?;
        let mut f = File::open(path.to_str().unwrap())?;
        let mut content = String::new();
        f.read_to_string(&mut content)?;
        Ok((metadata,content))
    }

    fn store_content_to_cache(&self, url:&String, content:&String) -> Result<(),CliError> {
        let mut path = std::env::temp_dir();
        path.push("ghteam-auth-cache");
        path.push(url.as_str());
        let mut dirpath = path.clone(); dirpath.pop();
        std::fs::create_dir_all(dirpath)?;
        let mut f = File::create(path.to_str().unwrap())?;
        f.write(content.as_bytes())?;
        Ok(())
    }

    fn get_content_from_url(&self, url:&String) -> Result<String,CliError> {
        let token = String::from("token ") + self.conf.token.clone().as_str();
        let res = self.client.get(url.as_str()).header(Authorization(token)).send();
        let mut content = String::new();
        res?.read_to_string(&mut content)?;
        self.store_content_to_cache(url,&content)?;
        Ok(content)
    }

    fn get_content(&self, url:&String) -> Result<String,CliError> {
        match self.load_content_from_cache(url) {
            Ok((metadata,cache_content)) => {
                match std::time::SystemTime::now().duration_since(metadata.modified()?) {
                    Ok(caching_duration) => {
                        if caching_duration.as_secs() > self.conf.cache_duration {
                            match self.get_content_from_url(url) {
                                Ok(content_from_url) => Ok(content_from_url),
                                Err(_) => Ok(cache_content)
                            }
                        } else {
                            Ok(cache_content)
                        }
                    },
                    Err(_) => {
                        Ok(cache_content)
                    }
                }
            },
            Err(_) => self.get_content_from_url(url)
        }
    }

    fn print_user_public_key(&self, user:&str) -> Result<(), CliError> {
        let keys = self.get_user_public_key(user)?;
        println!("{}", keys);
        Ok(())
    }

    fn get_user_public_key(&self, user:&str) -> Result<String, CliError> {
        let url = format!("{}/users/{}/keys", self.conf.endpoint, user);
        let content = self.get_content(&url);
        let keys = serde_json::from_str::<Vec<PublicKey>>(content?.as_str())?;
        Ok(keys.iter().map(|k|{k.key.clone()}).collect::<Vec<String>>().join("\n"))
    }

    fn check_pam(&self, user:&String) -> Result<bool, CliError> {
        let teams:HashMap<String,Team> = self.get_teams()?;
        if let Some(team) = teams.get(&self.conf.team.clone()) {
            for member in self.get_members(team.id)? {
                if member.login==*user { return Ok(true) }
            }
        }
        Ok(false)
    }

    fn get_passwd(&self) -> Result<(), CliError> {
        let teams:HashMap<String,Team> = self.get_teams()?;
        if let Some(team) = teams.get(&self.conf.team.clone()) {
            for member in self.get_members(team.id)? {
                println!("{}", self.create_passwd_line(&member));
            }
            Ok(())
        } else {
            Ok(())
        }
    }

    fn get_shadow(&self) -> Result<(), CliError> {
        let teams:HashMap<String,Team> = self.get_teams()?;
        if let Some(team) = teams.get(&self.conf.team.clone()) {
            for member in self.get_members(team.id)? {
                println!("{}", self.create_shadow_line(&member));
            }
            Ok(())
        } else {
            Ok(())
        }
    }

    fn get_group(&self) -> Result<(), CliError> {
        let teams:HashMap<String,Team> = self.get_teams()?;
        if let Some(team) = teams.get(&self.conf.team.clone()) {
            let members = self.get_members(team.id)?;
            println!("{}", self.create_group_line(&team.name, self.conf.gid, &members));
            Ok(())
        } else {
            Ok(())
        }
    }

    fn create_passwd_line(&self, member:&Member) -> String {
        format!("{login}:x:{uid}:{gid}:user@{org}:{home}:{sh}",
                login=member.login,
                uid=member.id,
                gid=self.conf.gid,
                org=self.conf.org,
                home=self.conf.home.replace("{}",member.login.as_str()),
                sh=self.conf.sh,
                )
    }

    fn create_shadow_line(&self, member:&Member) -> String {
        format!("{login}:!!:::::::", login=member.login )
    }

    fn create_group_line(&self, name:&String, id:u64, members:&Vec<Member>) -> String {
        format!("{name}:x:{id}:{members}", name=name, id=id,
                members=members.iter().map(|m|{m.login.clone()}).collect::<Vec<String>>().join(","))
    }

    fn get_teams(&self) -> Result<HashMap<String,Team>, CliError> {
        let url = format!("{}/orgs/{}/teams",self.conf.endpoint, self.conf.org);
        let content = self.get_content(&url)?;
        let teams = serde_json::from_str::<Vec<Team>>(content.as_str())?;
        let mut team_map = HashMap::new();
        for team in teams { team_map.insert(team.name.clone(), team); }
        Ok(team_map)
    }

    fn get_members(&self, mid:u64) -> Result<Vec<Member>, CliError> {
        let url = format!("{}/teams/{}/members",self.conf.endpoint.clone(), mid);
        let content = self.get_content(&url)?;
        let members = serde_json::from_str::<Vec<Member>>(content.as_str())?;
        Ok(members)
    }

    fn clear_all_caches(&self) -> Result<(), CliError> {
        let mut path = std::env::temp_dir();
        path.push("ghteam-auth-cache");
        path.push("**");
        path.push("*");
        for entry in glob(&path.to_str().unwrap()).unwrap() {
            match entry {
                Ok(path) => {if path.is_file() {std::fs::remove_file(path)?}},
                Err(e) => println!("{:?}", e),
            }
        }
        Ok(())
    }

}

#[repr(C)]
#[allow(missing_copy_implementations)]
pub struct Passwd {
    name:   *mut libc::c_char,
    pass:   *mut libc::c_char,
    uid:    libc::uid_t,
    gid:    libc::gid_t,
    gecos:  *mut libc::c_char,
    home:   *mut libc::c_char,
    sh:     *mut libc::c_char,
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate hyper;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate toml;

mod config;
mod issue;
mod jira_api;
mod jira_client;
mod jira_request;
mod search_command;
mod search_response;
mod workflow;

use clap::{App, SubCommand};

fn main() {
    let workflow = workflow::new();
    let matches = App::new("jira")
        .version(env!("CARGO_PKG_VERSION"))
        .about("Alfred JIRA Workflow.")
        .subcommand(SubCommand::with_name("Search")
            .about("Search JIRA issues"))
        .get_matches();

    if let Some(_) = matches.subcommand_matches("search") {
        match workflow.seach().run(&"".to_string()) {
            Ok(_) => (),
            Err(e) => {
                println!("{}", e.to_string());
                std::process::exit(1);
            }
        }
        std::process::exit(0);
    };
    std::process::exit(0);
}
<commit_msg>:art: Make possible to take argument in subcommand<commit_after>extern crate clap;
extern crate hyper;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate toml;

mod config;
mod issue;
mod jira_api;
mod jira_client;
mod jira_request;
mod search_command;
mod search_response;
mod workflow;

use clap::{Arg, App, SubCommand};

fn main() {
    let workflow = workflow::new();
    let matches = App::new("jira")
        .version(env!("CARGO_PKG_VERSION"))
        .about("Alfred JIRA Workflow.")
        .subcommand(SubCommand::with_name("search")
            .about("Search JIRA issues")
            .arg(Arg::with_name("keyword")
                .required(true)))
        .get_matches();

    if let Some(matches) = matches.subcommand_matches("search") {
        if let Some(keyword) = matches.value_of("keyword") {
            match workflow.search().run(&keyword.to_string()) {
                Ok(_) => (),
                Err(e) => {
                    println!("{}", e.to_string());
                    std::process::exit(1);
                }
            }
        }
        std::process::exit(0);
    };
    std::process::exit(0);
}
<|endoftext|>


<commit_before>//! `fomo` is an experiment to see if the file watching needs of build tools can
//! be solved a bit differently than existing solutions.
//!
//! For example, solutions like [chokidar](TODOLINKHERE) are often unable to
//! keep up with sweeping changes like `rm -rf node_modules`. Other solutions
//! like [watchman](TODOLINKHERE) are fantastic for many tasks, but also have several
//! layers of caching which sometimes must be manually deleted due to corrupt
//! data.
//!
//! So anyways, the main goal here is to see if we can find a goldilocks for
//! the needs of file watching for JavaScript tools (to start).

//#![warn(missing_docs)]

// error-chain can go pretty deep
#![recursion_limit = "1024"]

extern crate chrono;
extern crate clap;
extern crate env_logger;
#[macro_use]
extern crate error_chain;
extern crate glob;
#[macro_use]
extern crate log;
extern crate regex;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate walkdir;

#[cfg(test)]
extern crate tempdir;

use std::collections::BTreeMap;
use std::io::prelude::*;

use clap::App;

mod errors {
  // Create the Error, ErrorKind, ResultExt, and Result types
  error_chain!{
    foreign_links {
      GlobError(::glob::PatternError);
      JsonError(::serde_json::Error);
      IoError(::std::io::Error);
    }
  }
}

pub mod fs_view;
mod glob_wrapper;
pub mod query;
mod regex_wrapper;
mod times;

use errors::*;

fn run() -> Result<()> {
  env_logger::LogBuilder::new()
    .format(|rec: &log::LogRecord| format!("{}:{}", rec.level(), rec.args()))
    .filter(None, log::LogLevelFilter::Debug)
    .init()
    .unwrap();

  // don't need any arguments, as they should be passed by env var
  // but we want a nice help message for them
  // TODO write help message about env vars
  App::new(env!("CARGO_PKG_NAME"))
    .version(env!("CARGO_PKG_VERSION"))
    .author(env!("CARGO_PKG_AUTHORS"))
    .about(env!("CARGO_PKG_DESCRIPTION"))
    .before_help("Logging can be configured via the RUST_LOG environment variable.
See https://docs.rs/env_logger/ for details.")
    .get_matches();

  // acquire exclusive use of stdin/stdout
  info!("Initializing stdin/stdout handles");
  let stdin = ::std::io::stdin();

  let stdout_lock = ::std::io::stdout();
  let mut stdout = stdout_lock.lock();

  info!("listening to stdin for queries");
  for input in stdin.lock().lines() {
    let input = input.chain_err(|| "reading from stdin")?;
    let query: query::Query = match serde_json::from_str(&input) {
      Ok(q) => q,
      Err(why) => {

        error!("Parsing query failed: {:?}. Query string: '{}'", why, input);

        let mut error_map = BTreeMap::new();
        error_map.insert("error", "parse".to_string());
        error_map.insert("queryString", input.clone());

        // let's see if we can find the id of the query at least
        match serde_json::from_str::<query::PartialQuery>(&input) {
          Ok(p) => {
            error_map.insert("id", p.id);
            error_map.insert("humanError",
                             format!("Unable to parse query object: {:?}", why));
          }
          Err(why) => {
            error!("Unable to retrieve id from query string: {:?}", why);
            error_map.insert("humanError",
                             format!("Unable to parse query or even id from query object: {:?}",
                                     why));
          }
        }

        writeln!(&mut stdout, "{}", serde_json::to_string(&error_map)?)?;
        continue;
      }
    };
  }

  Ok(())
}

// TODO(dikaiosune) write a catch_panic facade that restarts everything
quick_main!(run);

#[derive(Deserialize, Serialize)]
struct StartupMessage {
  sync_port: u16,
  ws_port: u16,
  error: Option<StartError>,
  error_human: String,
}

#[derive(Deserialize, Serialize)]
enum StartError {
  PortUnavailable,
  PlatformUnsupported,
}
<commit_msg>Move the RPC context into its own function with generics.<commit_after>//! `fomo` is an experiment to see if the file watching needs of build tools can
//! be solved a bit differently than existing solutions.
//!
//! For example, solutions like [chokidar](TODOLINKHERE) are often unable to
//! keep up with sweeping changes like `rm -rf node_modules`. Other solutions
//! like [watchman](TODOLINKHERE) are fantastic for many tasks, but also have several
//! layers of caching which sometimes must be manually deleted due to corrupt
//! data.
//!
//! So anyways, the main goal here is to see if we can find a goldilocks for
//! the needs of file watching for JavaScript tools (to start).

//#![warn(missing_docs)]

// error-chain can go pretty deep
#![recursion_limit = "1024"]

extern crate chrono;
extern crate clap;
extern crate env_logger;
#[macro_use]
extern crate error_chain;
extern crate glob;
#[macro_use]
extern crate log;
extern crate regex;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate walkdir;

#[cfg(test)]
extern crate tempdir;

use std::collections::BTreeMap;
use std::io::prelude::*;

use clap::App;

mod errors {
  // Create the Error, ErrorKind, ResultExt, and Result types
  error_chain!{
    foreign_links {
      GlobError(::glob::PatternError);
      JsonError(::serde_json::Error);
      IoError(::std::io::Error);
    }
  }
}

pub mod fs_view;
mod glob_wrapper;
pub mod query;
mod regex_wrapper;
mod times;

use errors::*;

fn run() -> Result<()> {
  env_logger::LogBuilder::new()
    .format(|rec: &log::LogRecord| format!("{}:{}", rec.level(), rec.args()))
    .filter(None, log::LogLevelFilter::Debug)
    .init()
    .unwrap();

  // don't need any arguments, as they should be passed by env var
  // but we want a nice help message for them
  // TODO write help message about env vars
  App::new(env!("CARGO_PKG_NAME"))
    .version(env!("CARGO_PKG_VERSION"))
    .author(env!("CARGO_PKG_AUTHORS"))
    .about(env!("CARGO_PKG_DESCRIPTION"))
    .before_help("Logging can be configured via the RUST_LOG environment variable.
See https://docs.rs/env_logger/ for details.")
    .get_matches();

  // acquire exclusive use of stdin/stdout
  info!("Initializing stdin/stdout handles");
  let stdin = ::std::io::stdin();
  let stdin = stdin.lock();
  let stdout = ::std::io::stdout();
  let stdout = stdout.lock();

  run_for_realsies(stdin, stdout)
}

fn run_for_realsies<R, W>(stdin: R, mut stdout: W) -> Result<()>
  where R: Read + BufRead,
        W: Write
{
  info!("listening to stdin for queries");
  for input in stdin.lines() {
    let input = input.chain_err(|| "reading from stdin")?;
    let query: query::Query = match serde_json::from_str(&input) {
      Ok(q) => q,
      Err(why) => {

        error!("Parsing query failed: {:?}. Query string: '{}'", why, input);

        let mut error_map = BTreeMap::new();
        error_map.insert("error", "parse".to_string());
        error_map.insert("queryString", input.clone());

        // let's see if we can find the id of the query at least
        match serde_json::from_str::<query::PartialQuery>(&input) {
          Ok(p) => {
            error_map.insert("id", p.id);
            error_map.insert("humanError",
                             format!("Unable to parse query object: {:?}", why));
          }
          Err(why) => {
            error!("Unable to retrieve id from query string: {:?}", why);
            error_map.insert("humanError",
                             format!("Unable to parse query or even id from query object: {:?}",
                                     why));
          }
        }

        writeln!(&mut stdout, "{}", serde_json::to_string(&error_map)?)?;
        continue;
      }
    };
  }
  Ok(())
}

// TODO(dikaiosune) write a catch_panic facade that restarts everything
quick_main!(run);

#[derive(Deserialize, Serialize)]
struct StartupMessage {
  sync_port: u16,
  ws_port: u16,
  error: Option<StartError>,
  error_human: String,
}

#[derive(Deserialize, Serialize)]
enum StartError {
  PortUnavailable,
  PlatformUnsupported,
}
<|endoftext|>


<commit_before>extern crate unicode_names;
extern crate byteorder;

use std::env;
use std::fmt;
use std::str;
use std::char;

use byteorder::{ByteOrder, BigEndian};

struct Describable {
    c: char,
}

impl fmt::Display for Describable {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let cp : Codepoint = self.c.into();
        try!(cp.fmt(f));
        let printable : Printable = self.c.into();
        try!(write!(f, "\n{}", printable));
        match unicode_names::name(self.c) {
            Some(n) => {
                write!(f, "\nUnicode name: {}\n", n)
            },
            None => write!(f, "\n")
        }
    }
}

impl std::convert::From<char> for Describable {
    fn from(c: char) -> Describable {
        Describable{c: c}
    }
}

struct Printable {
    c: char,
}

impl std::convert::From<char> for Printable {
    fn from(c: char) -> Printable {
        Printable{c: c}
    }
}

impl fmt::Display for Printable {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let quote : String = self.c.escape_default().collect();
        if self.c.is_control() {
            try!(write!(f, "Control character; quotes as {}", quote));
        } else {
            if ! self.c.is_whitespace() {
                try!(write!(f, "Prints as {}", self.c));
            } else {
                try!(write!(f, "Prints as `{}'", self.c));
            }
            // Check if we can up/downcase:
            let mut caseflipped = String::new();
            if self.c.is_uppercase() {
                for c in self.c.to_lowercase() {
                    caseflipped.push(c);
                }
                try!(write!(f, "\nLower case {}", caseflipped));
            } else if self.c.is_lowercase() {
                for c in self.c.to_uppercase() {
                    caseflipped.push(c);
                }
                try!(write!(f, "\nUpper case {}", caseflipped));
            }

            // If we have quotable text, print that too:
            if quote.len() > 1 {
                try!(write!(f, "\nQuotes as {}", quote));
            }
        }
        Ok(())
    }
}

enum Codepoint {
    ASCII7bit(char),
    Latin1(char),
    UnicodeBasic(char),
    UnicodeWide(char)
}

impl std::convert::From<char> for Codepoint {
    fn from(c: char) -> Codepoint {
        match c as u32 {
            0 ... 128 => Codepoint::ASCII7bit(c),
            128 ... 256 => Codepoint::Latin1(c),
            256 ... 65536 => Codepoint::UnicodeBasic(c),
            _ => Codepoint::UnicodeWide(c),
        }
    }
}

impl fmt::Display for Codepoint {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &Codepoint::ASCII7bit(c) => {
                let num = c as u32;
                write!(f, "ASCII  {:02x}, {:3}, 0x{:02x}, 0{:03o}, bits {:08b}",
                       num, num, num, num, num)
            }
            &Codepoint::Latin1(c) => {
                let num = c as u32;
                write!(f, "LATIN1 {:02x}, {:3}, 0x{:02x}, 0{:03o}, bits {:08b}",
                       num, num, num, num, num)
            }
            &Codepoint::UnicodeBasic(c) | &Codepoint::UnicodeWide(c) => {
                let num = c as u32;
                let mut string = String::new();
                string.push(c);
                let s = string.as_str();
                let utf8 = ByteRepresentation::from(s.bytes());
                let utf16 = ByteRepresentation::from(s.encode_utf16());
                let width = match self {
                    &Codepoint::UnicodeWide(_) => 8,
                    _ => 4,
                };
                write!(f, "U+{:0width$X}, &#{:}; 0x{:0width$X}, \\0{:o}, UTF-8: {}, UTF-16BE: {}",
                       num, num, num, num, utf8, utf16, width = width)
            }
        }
    }
}

enum ByteRepresentation {
    UTF8(Vec<u8>),
    UTF16BE(Vec<u8>),
}

impl<'a> std::convert::From<str::EncodeUtf16<'a>> for ByteRepresentation {
    fn from(bs: str::EncodeUtf16<'a>) -> ByteRepresentation {
        let words: Vec<u16> = bs.collect();
        let mut buf: Vec<u8> = Vec::with_capacity(words.len() * 2);
        for word in words {
            let mut split_word = [0; 2];
            BigEndian::write_u16(&mut split_word, word);
            buf.extend_from_slice(&split_word);
        }

        ByteRepresentation::UTF16BE(buf)
    }
}

impl<'a> std::convert::From<str::Bytes<'a>> for ByteRepresentation {
    fn from(bs: str::Bytes<'a>) -> ByteRepresentation {
        let bytes: Vec<u8> = bs.collect();
        ByteRepresentation::UTF8(bytes)
    }
}

impl fmt::Display for ByteRepresentation {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &ByteRepresentation::UTF8(ref bytes) => {
                let mut byte_iter = bytes.iter();
                try!(write!(f, "{:02x}", byte_iter.next().unwrap()));
                for byte in byte_iter {
                    try!(write!(f, " {:02x}", byte));
                }
            },
            &ByteRepresentation::UTF16BE(ref bytes) => {
                for byte in bytes.iter() {
                    try!(write!(f, "{:02x}", byte));
                }
            }
        }
        Ok(())
    }
}

/// Takes a stringly description of a character (the character itself,
/// or a unicode code point name) and returns a Vec of Describable
/// elements that hold the corresponding character. The elements of
/// the vector are sorted by descending numeric code point.
fn from_arg(spec: &str) -> Vec<Describable> {
    let mut chars: Vec<char> = Vec::new();

    // match the character itself, or any of its names:
    if spec.chars().count() == 1 {
        spec.chars().next().map(|c| chars.push(c));
    } else {
        unicode_names::character(spec).map(|c| chars.push(c));
    }
    // Match hex/U+ strings specifically:
    if spec.starts_with("0x") || spec.starts_with("U+") {
        let _ = u32::from_str_radix(&spec[2..], 16).ok().
            map(|num| char::from_u32(num).map(|c| chars.push(c)));
    }

    // Match plain numbers in all bases:
    for base in vec![16, 10, 8, 2] {
        let _ = u32::from_str_radix(spec, base.clone()).ok().
            map(|num| char::from_u32(num).map(|c| chars.push(c)));
    }
    chars.sort_by(|a, b| b.cmp(a));
    chars.dedup();
    chars.iter().map(|c| c.clone().into()).collect()
}

fn main() {
    let args =
        env::args().skip(1)
        .flat_map(|argument| from_arg(argument.as_ref()));
    for c in args {
        println!("{}", c);
    }
}

#[test]
fn from_arg_translates_chars() {
    assert_eq!('n', from_arg("n")[0].c);
    assert_eq!(']', from_arg("]")[0].c);
}

#[test]
fn from_arg_translates_descriptions() {
    assert_eq!('n', from_arg("latin small letter n")[0].c);
    assert_eq!(']', from_arg("right square bracket")[0].c);
}

#[test]
fn from_arg_translates_numbers() {
    let received = from_arg("60");
    let mut iter = received.iter();
    assert_eq!('`', iter.next().unwrap().c);
    assert_eq!('<', iter.next().unwrap().c);
    assert_eq!('0', iter.next().unwrap().c);

    assert_eq!(2, from_arg("0").len());
    assert_eq!(0x30, from_arg("0").iter().next().unwrap().c as u32);

    assert_eq!(1, from_arg("0x0").len());
    assert_eq!(1, from_arg("0x41").len());
    assert_eq!('A', from_arg("0x41")[0].c);
}
<commit_msg>Improve case / flipping information a little<commit_after>extern crate unicode_names;
extern crate byteorder;

use std::env;
use std::fmt;
use std::str;
use std::char;

use byteorder::{ByteOrder, BigEndian};

struct Describable {
    c: char,
}

impl fmt::Display for Describable {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let cp : Codepoint = self.c.into();
        try!(cp.fmt(f));
        let printable : Printable = self.c.into();
        try!(write!(f, "\n{}", printable));
        match unicode_names::name(self.c) {
            Some(n) => {
                write!(f, "\nUnicode name: {}\n", n)
            },
            None => write!(f, "\n")
        }
    }
}

impl std::convert::From<char> for Describable {
    fn from(c: char) -> Describable {
        Describable{c: c}
    }
}

struct Printable {
    c: char,
}

impl std::convert::From<char> for Printable {
    fn from(c: char) -> Printable {
        Printable{c: c}
    }
}

impl fmt::Display for Printable {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let quote : String = self.c.escape_default().collect();
        if self.c.is_control() {
            try!(write!(f, "Control character; quotes as {}", quote));
        } else {
            if ! self.c.is_whitespace() {
                try!(write!(f, "Prints as {}", self.c));
            } else {
                try!(write!(f, "Prints as `{}'", self.c));
            }
            // Check if we can up/downcase:
            let mut caseflipped = String::new();
            if self.c.is_uppercase() {
                for c in self.c.to_lowercase() {
                    caseflipped.push(c);
                }
                try!(write!(f, "\nUpper case. Downcases to {}", caseflipped));
            } else if self.c.is_lowercase() {
                for c in self.c.to_uppercase() {
                    caseflipped.push(c);
                }
                try!(write!(f, "\nLower case. Upcases to {}", caseflipped));
            }

            // If we have quotable text, print that too:
            if quote.len() > 1 {
                try!(write!(f, "\nQuotes as {}", quote));
            }
        }
        Ok(())
    }
}

enum Codepoint {
    ASCII7bit(char),
    Latin1(char),
    UnicodeBasic(char),
    UnicodeWide(char)
}

impl std::convert::From<char> for Codepoint {
    fn from(c: char) -> Codepoint {
        match c as u32 {
            0 ... 128 => Codepoint::ASCII7bit(c),
            128 ... 256 => Codepoint::Latin1(c),
            256 ... 65536 => Codepoint::UnicodeBasic(c),
            _ => Codepoint::UnicodeWide(c),
        }
    }
}

impl fmt::Display for Codepoint {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &Codepoint::ASCII7bit(c) => {
                let num = c as u32;
                write!(f, "ASCII  {:02x}, {:3}, 0x{:02x}, 0{:03o}, bits {:08b}",
                       num, num, num, num, num)
            }
            &Codepoint::Latin1(c) => {
                let num = c as u32;
                write!(f, "LATIN1 {:02x}, {:3}, 0x{:02x}, 0{:03o}, bits {:08b}",
                       num, num, num, num, num)
            }
            &Codepoint::UnicodeBasic(c) | &Codepoint::UnicodeWide(c) => {
                let num = c as u32;
                let mut string = String::new();
                string.push(c);
                let s = string.as_str();
                let utf8 = ByteRepresentation::from(s.bytes());
                let utf16 = ByteRepresentation::from(s.encode_utf16());
                let width = match self {
                    &Codepoint::UnicodeWide(_) => 8,
                    _ => 4,
                };
                write!(f, "U+{:0width$X}, &#{:}; 0x{:0width$X}, \\0{:o}, UTF-8: {}, UTF-16BE: {}",
                       num, num, num, num, utf8, utf16, width = width)
            }
        }
    }
}

enum ByteRepresentation {
    UTF8(Vec<u8>),
    UTF16BE(Vec<u8>),
}

impl<'a> std::convert::From<str::EncodeUtf16<'a>> for ByteRepresentation {
    fn from(bs: str::EncodeUtf16<'a>) -> ByteRepresentation {
        let words: Vec<u16> = bs.collect();
        let mut buf: Vec<u8> = Vec::with_capacity(words.len() * 2);
        for word in words {
            let mut split_word = [0; 2];
            BigEndian::write_u16(&mut split_word, word);
            buf.extend_from_slice(&split_word);
        }

        ByteRepresentation::UTF16BE(buf)
    }
}

impl<'a> std::convert::From<str::Bytes<'a>> for ByteRepresentation {
    fn from(bs: str::Bytes<'a>) -> ByteRepresentation {
        let bytes: Vec<u8> = bs.collect();
        ByteRepresentation::UTF8(bytes)
    }
}

impl fmt::Display for ByteRepresentation {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &ByteRepresentation::UTF8(ref bytes) => {
                let mut byte_iter = bytes.iter();
                try!(write!(f, "{:02x}", byte_iter.next().unwrap()));
                for byte in byte_iter {
                    try!(write!(f, " {:02x}", byte));
                }
            },
            &ByteRepresentation::UTF16BE(ref bytes) => {
                for byte in bytes.iter() {
                    try!(write!(f, "{:02x}", byte));
                }
            }
        }
        Ok(())
    }
}

/// Takes a stringly description of a character (the character itself,
/// or a unicode code point name) and returns a Vec of Describable
/// elements that hold the corresponding character. The elements of
/// the vector are sorted by descending numeric code point.
fn from_arg(spec: &str) -> Vec<Describable> {
    let mut chars: Vec<char> = Vec::new();

    // match the character itself, or any of its names:
    if spec.chars().count() == 1 {
        spec.chars().next().map(|c| chars.push(c));
    } else {
        unicode_names::character(spec).map(|c| chars.push(c));
    }
    // Match hex/U+ strings specifically:
    if spec.starts_with("0x") || spec.starts_with("U+") {
        let _ = u32::from_str_radix(&spec[2..], 16).ok().
            map(|num| char::from_u32(num).map(|c| chars.push(c)));
    }

    // Match plain numbers in all bases:
    for base in vec![16, 10, 8, 2] {
        let _ = u32::from_str_radix(spec, base.clone()).ok().
            map(|num| char::from_u32(num).map(|c| chars.push(c)));
    }
    chars.sort_by(|a, b| b.cmp(a));
    chars.dedup();
    chars.iter().map(|c| c.clone().into()).collect()
}

fn main() {
    let args =
        env::args().skip(1)
        .flat_map(|argument| from_arg(argument.as_ref()));
    for c in args {
        println!("{}", c);
    }
}

#[test]
fn from_arg_translates_chars() {
    assert_eq!('n', from_arg("n")[0].c);
    assert_eq!(']', from_arg("]")[0].c);
}

#[test]
fn from_arg_translates_descriptions() {
    assert_eq!('n', from_arg("latin small letter n")[0].c);
    assert_eq!(']', from_arg("right square bracket")[0].c);
}

#[test]
fn from_arg_translates_numbers() {
    let received = from_arg("60");
    let mut iter = received.iter();
    assert_eq!('`', iter.next().unwrap().c);
    assert_eq!('<', iter.next().unwrap().c);
    assert_eq!('0', iter.next().unwrap().c);

    assert_eq!(2, from_arg("0").len());
    assert_eq!(0x30, from_arg("0").iter().next().unwrap().c as u32);

    assert_eq!(1, from_arg("0x0").len());
    assert_eq!(1, from_arg("0x41").len());
    assert_eq!('A', from_arg("0x41")[0].c);
}
<|endoftext|>


<commit_before>#![cfg_attr(test, allow(dead_code))]

extern crate arguments;

use arguments::Arguments;
use std::{env, process};
use std::fmt::Display;

const USAGE: &'static str = "
Usage: layer [options]

Options:
    --database PATH          SQLite3 database (required).
    --table    NAME          Table to look for area measurements (required).

    --help                   Display this message.
";

macro_rules! print_error(
    ($fmt:expr, $($args:tt)*) => ({
        use std::io::Write;
        ::std::io::stderr().write_fmt(format_args!($fmt, $($args)*)).unwrap()
    });
);

macro_rules! ok(
    ($result:expr) => (match $result {
        Ok(result) => result,
        Err(error) => fail(error),
    });
);

fn main() {
    let Arguments { options, .. } = ok!(arguments::parse(env::args()));
    match options.get_ref::<String>("database") {
        Some(_) => {},
        _ => usage(USAGE),
    }
}

fn fail<T: Display>(error: T) -> ! {
    print_error!("Error: {}.\n", error);
    process::exit(1);
}

fn usage(message: &str) -> ! {
    print_error!("{}\n", message.trim());
    process::exit(0);
}
<commit_msg>Read the area estimates from a database<commit_after>#![cfg_attr(test, allow(dead_code))]

extern crate arguments;
extern crate sqlite;

use arguments::Arguments;
use sqlite::Database;
use std::fmt::Display;
use std::path::Path;
use std::{env, process};

const CORE_LIKE: &'static str = "core%_area";
const L3_LIKE: &'static str = "l3%_area";

const USAGE: &'static str = "
Usage: layer [options]

Options:
    --database PATH          SQLite3 database (required).
    --table    NAME          Table to look for area measurements (required).

    --help                   Display this message.
";

macro_rules! die(
    ($($arg:tt)*) => (fail(format!($($arg)*)));
);

macro_rules! ok(
    ($result:expr) => (match $result {
        Ok(result) => result,
        Err(error) => fail(error),
    });
);

macro_rules! print_error(
    ($($arg:tt)*) => ({
        use std::io::Write;
        ::std::io::stderr().write_fmt(format_args!($($arg)*)).unwrap_or(())
    });
);

fn main() {
    let Arguments { options, .. } = ok!(arguments::parse(env::args()));

    let database = match options.get_ref::<String>("database") {
        Some(database) => ok!(sqlite::open(&Path::new(database))),
        _ => usage(USAGE),
    };
    let (core, l3) = match options.get_ref::<String>("table") {
        Some(table) => (find(&database, table, CORE_LIKE), find(&database, table, L3_LIKE)),
        _ => usage(USAGE),
    };
    println!("Core: {}", core);
    println!("L3: {}", l3);
}

fn find(database: &Database, table: &str, like: &str) -> f64 {
    use sqlite::State;
    let mut statement = ok!(database.prepare(&format!(
        "SELECT name, value FROM `{}` WHERE name LIKE '{}' LIMIT 1;", table, like,
    )));
    match ok!(statement.step()) {
        State::Row => ok!(statement.column::<f64>(0 + 1)),
        _ => die!("failed to find a required value in the table"),
    }
}

fn fail<T: Display>(error: T) -> ! {
    print_error!("Error: {}.\n", error);
    process::exit(1);
}

fn usage(message: &str) -> ! {
    print_error!("{}\n", message.trim());
    process::exit(0);
}
<|endoftext|>


<commit_before>//! Types used in the registry.

use std::sync::Arc;
use std::fmt::{Debug, Formatter};
use std::fmt::Result as FmtResult;

use rustc_serialize::json::Json;

bitflags! {
    /// Access permissions for items in the registry
    pub flags AccessFlags: u8 {
        /// Clients can read/get the data
        const READ    = 1 << 0,
        /// Clients can write/set the data
        const WRITE   = 1 << 1,
    }
}

impl AccessFlags {
    /// Read permissions
    #[inline]
    #[allow(non_snake_case)]
    pub fn READ() -> AccessFlags { READ }

    /// Write permissions
    #[inline]
    #[allow(non_snake_case)]
    pub fn WRITE() -> AccessFlags { WRITE }
}

/// Command type for Rust function
pub type CommandFn = Arc<Fn() + Send + Sync>;

/// Function which will yield an object
pub type GetFn = Arc<Fn() -> Json + Send + Sync>;

/// Function which will set an object
pub type SetFn = Arc<Fn(Json) + Send + Sync>;

/// Enum of types of registry fields
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum FieldType { Object, Property, Command }

/// Data which can be stored in the registry
#[derive(Clone)]
pub enum RegistryField {
    /// An object with permission flags
    Object {
        /// Permission flags for Lua get/setting the value
        flags: AccessFlags,
        /// Data associated with this value
        data: Arc<Json>
    },
    /// A registry value whose get and set maps to other Rust code
    Property {
        /// Method called to set a property
        get: Option<GetFn>,
        /// Method called to set a property
        set: Option<SetFn>
    },
    /// A command
    Command(CommandFn)
}

/// Result of what can be accessed from a registry value.
#[derive(Clone)]
pub enum RegistryGetData {
    /// An object in the registry
    Object(AccessFlags, Arc<Json>),
    /// Get field of a property in the registry
    Property(GetFn)
}

impl Debug for RegistryField {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match self {
            &RegistryField::Object { ref flags, ref data } =>
                f.debug_struct("RegistryField::Object")
                .field("flags", flags as &Debug)
                .field("data", data as &Debug).finish(),
            &RegistryField::Property { ref get, ref set } => {
                let new_get = match get { &Some(_) => Some(true), &None => None };
                let new_set = match set { &Some(_) => Some(true), &None => None };
                f.debug_struct("RegistryField::Property")
                    .field("get", &new_get)
                    .field("set", &new_set)
                    .finish()
            }
            &RegistryField::Command(_) =>
                write!(f, "RegistryField::Command(...)")
        }
    }
}

impl Debug for RegistryGetData {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match self {
            &RegistryGetData::Object(ref flags, ref data) =>
                f.debug_struct("RegistryGetData::Object")
                .field("flags", flags as &Debug)
                .field("data", data as &Debug).finish(),
            &RegistryGetData::Property(_) =>
                write!(f, "RegistryGetData::Property")
        }
    }
}

impl FieldType {
    /// Whether a field of this type can be changed by a field of type other.
    pub fn can_set_from(self, other: FieldType) -> bool {
        match self {
            FieldType::Command => other == FieldType::Command,
            FieldType::Property =>
                other == FieldType::Object ||
                other == FieldType::Property,
            FieldType::Object => other == FieldType::Object
        }
    }
}

impl RegistryField {
    /// What access the module has to it
    #[allow(dead_code)]
    pub fn get_flags(&self) -> Option<AccessFlags> {
        match self {
            &RegistryField::Object { ref flags, .. } => Some(flags.clone()),
            &RegistryField::Property { ref get, ref set } => {
                let mut flags = AccessFlags::empty();
                if get.is_some() { flags.insert(AccessFlags::READ()); }
                if set.is_some() { flags.insert(AccessFlags::WRITE()); }
                Some(flags)
            },
            _ => None
        }
    }

    /// Attempts to access the RegistryField as a command
    pub fn get_command(&self) -> Option<CommandFn> {
        match *self {
            RegistryField::Command(ref com) => Some(com.clone()),
            _ => None
        }
    }

    /// Attempts to access the RegistryField as a file
    #[allow(dead_code)]
    pub fn get_data(&self) -> Option<RegistryGetData> {
        match *self {
            RegistryField::Object { ref flags, ref data } =>
                Some(RegistryGetData::Object(flags.clone(), data.clone())),
            RegistryField::Property { ref get, .. } =>
                get.clone().and_then(|g| Some(RegistryGetData::Property(g))),
            _ => None
        }
    }

    /// Converts this RegistryField to maybe a command
    #[allow(dead_code)]
    pub fn as_command(self) -> Option<CommandFn> {
        match self {
            RegistryField::Command(com) => Some(com),
            _ => None
        }
    }

    /// Converts this RegistryField to maybe an object. Does not call property methods.
    pub fn as_object(self) -> Option<(AccessFlags, Arc<Json>)> {
        match self {
            RegistryField::Object { flags, data } => Some((flags, data)),
            _ => None
        }
    }

    /// Gets this field as maybe a property with maybe a getter and setter.
    pub fn as_property(self) -> Option<(Option<GetFn>, Option<SetFn>)> {
        match self {
            RegistryField::Property { get, set } => Some((get, set)),
            _ => None
        }
    }

    /// Returns the getter, if this field is a property with a getter.
    #[allow(dead_code)]
    pub fn as_property_get(self) -> Option<GetFn> {
        self.as_property().and_then(|(maybe_get, _)| maybe_get)
    }

    /// Returns a setter if this field is a property with a setter.
    pub fn as_property_set(self) -> Option<SetFn> {
        self.as_property().and_then(|(_, maybe_set)| maybe_set)
    }

    /// Gets the type of this registry field
    pub fn get_type(&self) -> FieldType {
        match self {
            &RegistryField::Object { .. }   => FieldType::Object,
            &RegistryField::Property { .. } => FieldType::Property,
            &RegistryField::Command(_)      => FieldType::Command
        }
    }
}

impl RegistryGetData {
    /// Collapses the waveform.
    ///
    /// If this is a Json, returns the Json data. If this is a property, runs the
    /// method and returns the output.
    pub fn resolve(self) -> (AccessFlags, Arc<Json>) {
        match self {
            RegistryGetData::Object(flags, data) => (flags, data),
            RegistryGetData::Property(get) =>
                (AccessFlags::all(), Arc::new(get()))
        }
    }

    /// Gets the FieldType of this GetData (property or object)
    #[allow(dead_code)]
    pub fn get_type(&self) -> FieldType {
        match self {
            &RegistryGetData::Property(_) => FieldType::Property,
            &RegistryGetData::Object(_, _) => FieldType::Object
        }
    }
}
<commit_msg>Add RegistrySetData and flags to RegistryGetData<commit_after>//! Types used in the registry.

use std::sync::Arc;
use std::fmt::{Debug, Formatter};
use std::fmt::Result as FmtResult;

use rustc_serialize::json::Json;

bitflags! {
    /// Access permissions for items in the registry
    pub flags AccessFlags: u8 {
        /// Clients can read/get the data
        const READ    = 1 << 0,
        /// Clients can write/set the data
        const WRITE   = 1 << 1,
    }
}

impl AccessFlags {
    /// Read permissions
    #[inline]
    #[allow(non_snake_case)]
    pub fn READ() -> AccessFlags { READ }

    /// Write permissions
    #[inline]
    #[allow(non_snake_case)]
    pub fn WRITE() -> AccessFlags { WRITE }
}

/// Command type for Rust function
pub type CommandFn = Arc<Fn() + Send + Sync>;

/// Function which will yield an object
pub type GetFn = Arc<Fn() -> Json + Send + Sync>;

/// Function which will set an object
pub type SetFn = Arc<Fn(Json) + Send + Sync>;

/// Enum of types of registry fields
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum FieldType { Object, Property, Command }

/// Data which can be stored in the registry
#[derive(Clone)]
pub enum RegistryField {
    /// An object with permission flags
    Object {
        /// Permission flags for Lua get/setting the value
        flags: AccessFlags,
        /// Data associated with this value
        data: Arc<Json>
    },
    /// A registry value whose get and set maps to other Rust code
    Property {
        /// Method called to set a property
        get: Option<GetFn>,
        /// Method called to set a property
        set: Option<SetFn>
    },
    /// A command
    Command(CommandFn)
}

/// Result of what can be accessed from a registry value.
#[derive(Clone)]
pub enum RegistryGetData {
    /// An object in the registry
    Object(AccessFlags, Arc<Json>),
    /// Get field of a property in the registry
    Property(AccessFlags, GetFn)
}

/// Result of what can be set to a registry value.
#[derive(Clone)]
pub enum RegistrySetData {
    /// Some data was displaced, here it is
    Displaced(Arc<Json>),
    /// A property was retrieved, you should run it
    Property(SetFn)
}

impl Debug for RegistryField {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match self {
            &RegistryField::Object { ref flags, ref data } =>
                f.debug_struct("RegistryField::Object")
                .field("flags", flags as &Debug)
                .field("data", data as &Debug).finish(),
            &RegistryField::Property { ref get, ref set } => {
                let new_get = match get { &Some(_) => Some(true), &None => None };
                let new_set = match set { &Some(_) => Some(true), &None => None };
                f.debug_struct("RegistryField::Property")
                    .field("get", &new_get)
                    .field("set", &new_set)
                    .finish()
            }
            &RegistryField::Command(_) =>
                write!(f, "RegistryField::Command(...)")
        }
    }
}

impl Debug for RegistryGetData {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match self {
            &RegistryGetData::Object(ref flags, ref data) =>
                f.debug_struct("RegistryGetData::Object")
                .field("flags", flags as &Debug)
                .field("data", data as &Debug).finish(),
            &RegistryGetData::Property(ref flags, _) =>
                write!(f, "RegistryGetData::Property({:?})", flags)
        }
    }
}

impl Debug for RegistrySetData {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match self {
            &RegistrySetData::Displaced(ref data) =>
                f.debug_struct("RegistrySetData::Displaced")
                .field("data", data as &Debug).finish(),
            &RegistrySetData::Property(_) =>
                write!(f, "RegistrySetData::Property(...)")
        }
    }
}

impl FieldType {
    /// Whether a field of this type can be changed by a field of type other.
    pub fn can_set_from(self, other: FieldType) -> bool {
        match self {
            FieldType::Command => other == FieldType::Command,
            FieldType::Property =>
                other == FieldType::Object ||
                other == FieldType::Property,
            FieldType::Object => other == FieldType::Object
        }
    }
}

impl RegistryField {
    /// What access the module has to it
    pub fn get_flags(&self) -> Option<AccessFlags> {
        match *self {
            RegistryField::Object { ref flags, .. } => Some(flags.clone()),
            RegistryField::Property { ref get, ref set } => {
                let mut flags = AccessFlags::empty();
                if get.is_some() { flags.insert(AccessFlags::READ()); }
                if set.is_some() { flags.insert(AccessFlags::WRITE()); }
                Some(flags)
            },
            RegistryField::Command(_) => None
        }
    }

    /// Attempts to access the RegistryField as a command
    pub fn get_command(&self) -> Option<CommandFn> {
        match *self {
            RegistryField::Command(ref com) => Some(com.clone()),
            _ => None
        }
    }

    /// Attempts to access the RegistryField as a file
    #[allow(dead_code)]
    pub fn get_data(&self) -> Option<RegistryGetData> {
        match *self {
            RegistryField::Object { ref flags, ref data } =>
                Some(RegistryGetData::Object(flags.clone(), data.clone())),
            RegistryField::Property { ref get, ref set } => {
                let mut flags = AccessFlags::empty();
                if get.is_some() { flags.insert(AccessFlags::READ()) }
                if set.is_some() { flags.insert(AccessFlags::WRITE()) }
                get.map(|g| RegistryGetData::Property(flags, g))
            }
            _ => None
        }
    }

    /// Converts this RegistryField to maybe a command
    #[allow(dead_code)]
    pub fn as_command(self) -> Option<CommandFn> {
        match self {
            RegistryField::Command(com) => Some(com),
            _ => None
        }
    }

    /// Converts this RegistryField to maybe an object. Does not call property methods.
    pub fn as_object(self) -> Option<(AccessFlags, Arc<Json>)> {
        match self {
            RegistryField::Object { flags, data } => Some((flags, data)),
            _ => None
        }
    }

    /// Gets this field as maybe a property with maybe a getter and setter.
    pub fn as_property(self) -> Option<(Option<GetFn>, Option<SetFn>)> {
        match self {
            RegistryField::Property { get, set } => Some((get, set)),
            _ => None
        }
    }

    /// Returns the getter, if this field is a property with a getter.
    #[allow(dead_code)]
    pub fn as_property_get(self) -> Option<GetFn> {
        self.as_property().and_then(|(maybe_get, _)| maybe_get)
    }

    /// Returns a setter if this field is a property with a setter.
    pub fn as_property_set(self) -> Option<SetFn> {
        self.as_property().and_then(|(_, maybe_set)| maybe_set)
    }

    /// Gets the type of this registry field
    pub fn get_type(&self) -> FieldType {
        match self {
            &RegistryField::Object { .. }   => FieldType::Object,
            &RegistryField::Property { .. } => FieldType::Property,
            &RegistryField::Command(_)      => FieldType::Command
        }
    }
}

impl RegistryGetData {
    /// Collapses the waveform.
    ///
    /// If this is a Json, returns the Json data. If this is a property, runs the
    /// method and returns the output.
    pub fn resolve(self) -> (AccessFlags, Arc<Json>) {
        match self {
            RegistryGetData::Object(flags, data) => (flags, data),
            RegistryGetData::Property(flags, get) =>
                (flags, Arc::new(get()))
        }
    }

    /// Gets the FieldType of this GetData (property or object)
    #[allow(dead_code)]
    pub fn get_type(&self) -> FieldType {
        match self {
            &RegistryGetData::Property(_, _) => FieldType::Property,
            &RegistryGetData::Object(_, _) => FieldType::Object
        }
    }
}

impl RegistrySetData {
    /// If this set data is a property, calls the property
    pub fn call(self, json: Json) {
        match self {
            RegistrySetData::Displaced(_) => (),
            RegistrySetData::Property(set) => set(json)
        }
    }

    /// Gets the FieldType of this SetData (property or object)
    #[allow(dead_code)]
    pub fn get_type(&self) -> FieldType {
        match *self {
            RegistrySetData::Displaced(_) => FieldType::Object,
            RegistrySetData::Property(_) => FieldType::Property
        }
    }
}
<|endoftext|>