<commit_before>use std::io;

struct PrioData {
    lists: Vec<PrioItem>,
}
struct PrioItem {
    name: String,
    items: Vec<String>,
}

fn main() {
    let mut data = PrioData {
        lists: vec![PrioItem {name: "High".to_string(), items: vec!["something".to_string(), "something else".to_string()]}]
    };

    loop {
        let prompt = "What do you want to do?";
        let choices = vec![
            "1. View priority lists".to_string(),
            "2. Create a new priority".to_string(),
        ];

        let desire = switch_board(prompt, choices);

        match desire.as_ref() {
            "1" => {view_priority_lists(&data);},
            "2" => {create_priority_list(&data);},
            _ => {println!("Please enter a valid number!");}
        }
    }
}

fn view_priority_lists(data: &PrioData) {
    if data.lists.len() == 0 {
        println!("You have no lists!");
    }
    else {
        let mut choices: Vec<String> = vec![];
        let mut index = 0;

        for list in &data.lists {
            index += 1;
            let mut text = index.to_string();
            text.push_str(". ");
            text.push_str(&list.name);
            choices.push(text);
        }

        println!("");

        let prompt = "Which list do you want to view?";

        let desire = switch_board(prompt, choices);
        let mut index: usize = desire.parse().unwrap();
        index -= 1;
        view_list(index, &data);
    }
}

fn view_list(list_index: usize, data: &PrioData) {
    let list = &data.lists[list_index];
    println!("\n--{}--", list.name);

    for item in &list.items {
        println!("{}", item);
    }

}

fn create_priority_list(data: &PrioData) {
    println!("create list!");
}

fn switch_board(prompt: &str, choices: Vec<String>) -> String {
    println!("{}", prompt);
    for choice in choices {
        println!("{}", choice);
    }

    let mut choice = String::new();

    io::stdin().read_line(&mut choice)
        .ok()
        .expect("Failed to read line.");

    choice.trim().to_string()
}
<commit_msg>Renamed PrioItem to PrioList and added a method to added an implementation for new and add_item<commit_after>use std::io;

struct PrioData {
    lists: Vec<PrioList>,
}

struct PrioList {
    name: String,
    items: Vec<String>,
}
impl PrioList {
    fn new(name: &str, items: Vec<String>) -> PrioList {
        PrioList {
            name: name.to_string(),
            items: items.clone(),
        }
    }

    fn add_item(&mut self, new_item: &str) {
        self.items.push(new_item.to_string());
    }
}

fn main() {
    let mut data = PrioData {
        lists: vec![PrioList::new("High", vec!["something".to_string(), "something else".to_string()])]
    };

    loop {
        let prompt = "What do you want to do?";
        let choices = vec![
            "1. View priority lists".to_string(),
            "2. Create a new priority".to_string(),
        ];

        let desire = switch_board(prompt, choices);

        match desire.as_ref() {
            "1" => {view_priority_lists(&data);},
            "2" => {create_priority_list(&data);},
            _ => {println!("Please enter a valid number!");}
        }
    }
}

fn view_priority_lists(data: &PrioData) {
    if data.lists.len() == 0 {
        println!("You have no lists!");
    }
    else {
        let mut choices: Vec<String> = vec![];
        let mut index = 0;

        for list in &data.lists {
            index += 1;
            let mut text = index.to_string();
            text.push_str(". ");
            text.push_str(&list.name);
            choices.push(text);
        }

        println!("");

        let prompt = "Which list do you want to view?";

        let desire = switch_board(prompt, choices);
        let mut index: usize = desire.parse().unwrap();
        index -= 1;
        view_list(index, &data);
    }
}

fn view_list(list_index: usize, data: &PrioData) {
    let list = &data.lists[list_index];
    println!("\n--{}--", list.name);

    for item in &list.items {
        println!("{}", item);

    }

}

fn create_priority_list(data: &PrioData) {
    println!("create list!");
}

fn switch_board(prompt: &str, choices: Vec<String>) -> String {
    println!("{}", prompt);
    for choice in choices {
        println!("{}", choice);
    }

    let mut choice = String::new();

    io::stdin().read_line(&mut choice)
        .ok()
        .expect("Failed to read line.");

    choice.trim().to_string()
}
<|endoftext|>


<commit_before>//! An implementation of [tldr](https://github.com/tldr-pages/tldr) in Rust.

#[macro_use] extern crate log;
#[cfg(feature = "logging")]extern crate env_logger;
extern crate docopt;
extern crate ansi_term;
extern crate flate2;
extern crate tar;
extern crate tempdir;
extern crate curl;
extern crate rustc_serialize;

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

use docopt::Docopt;

mod types;
mod tokenizer;
mod formatter;
mod updater;
mod error;

use tokenizer::Tokenizer;
use updater::Updater;
use error::TldrError;
use formatter::print_lines;

const NAME: &'static str = "tldr-rs";
const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const USAGE: &'static str = "
Usage:

    tldr <command>
    tldr [options]

Options:

    -h --help           Show this screen
    -v --version        Show version information
    -l --list           List all commands in the cache
    -f --render <file>  Render a specific markdown file
    -o --os <type>      Override the operating system [linux, osx, sunos]
    -u --update         Update the local cache
    -c --clear-cache    Clear the local cache

Examples:

    $ tldr tar
    $ tldr --list

To control the cache:

    $ tldr --update
    $ tldr --clear-cache

To render a local file (for testing):

    $ tldr --render /path/to/file.md
";
const ARCHIVE_URL: &'static str = "https://github.com/tldr-pages/tldr/archive/master.tar.gz";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_command: Option<String>,
    flag_help: bool,
    flag_version: bool,
    flag_list: bool,
    flag_render: Option<String>,
    flag_os: Option<String>,  // TODO enum
    flag_update: bool,
    flag_clear_cache: bool,
}

/// Open file, return a `BufRead` instance
fn get_file_reader(filepath: &str) -> Result<BufReader<File>, String> {
    let file = try!(
        File::open(filepath)
            .map_err(|msg| format!("Could not open file: {}", msg))
    );
    Ok(BufReader::new(file))
}

#[cfg(feature = "logging")]
fn init_log() {
    env_logger::init().unwrap();
}

#[cfg(not(feature = "logging"))]
fn init_log() { }

fn main() {

    // Initialize logger
    init_log();

    // Parse arguments
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());
    println!("{:#?}", args);

    // Show version and exit
    if args.flag_version {
        println!("{} v{}", NAME, VERSION);
        process::exit(0);
    }

    // Clear cache, pass through
    if args.flag_clear_cache {
        println!("Flag --clear-cache not yet implemented.");
        process::exit(1);
    }

    // Update cache, pass through
    if args.flag_update {
        let dl = Updater::new(ARCHIVE_URL);
        let copied = dl.update().unwrap_or_else(|e| {
            match e {
                TldrError::UpdateError(msg) => println!("Could not update cache: {}", msg),
            };
            process::exit(1);
        });
        println!("Cached {} tldr pages.", copied);
    }

    // Render local file and exit
    if let Some(file) = args.flag_render {
        // Open file
        let reader = get_file_reader(&file).unwrap_or_else(|msg| {
            println!("{}", msg);
            process::exit(1);
        });

        // Create tokenizer and print output
        let mut tokenizer = Tokenizer::new(reader);
        print_lines(&mut tokenizer);

        process::exit(0);
    }

    // List cached commands and exit
    if args.flag_list {
        println!("Flag --list not yet implemented.");
        process::exit(1);
    }

    // Override OS and exit
    if let Some(os) = args.flag_os {
        println!("Flag --os not yet implemented.");
    }

    // Show command from cache
    if let Some(command) = args.arg_command {
        println!("Flag --os not yet implemented.");
        process::exit(1);
    }

    println!("{}", USAGE);
    process::exit(1);
}

#[cfg(test)]
mod test {
    use types::LineType;

    #[test]
    fn test_linetype_from_str() {
        assert_eq!(LineType::from(""), LineType::Empty);
        assert_eq!(LineType::from(" \n \r"), LineType::Empty);
        assert_eq!(LineType::from("# Hello there"), LineType::Title("Hello there".into()));
        assert_eq!(LineType::from("> tis a description \n"), LineType::Description("tis a description".into()));
        assert_eq!(LineType::from("- some command"), LineType::ExampleText("some command".into()));
        assert_eq!(LineType::from("`$ cargo run`"), LineType::ExampleCode("$ cargo run".into()));
        assert_eq!(LineType::from("`$ cargo run"), LineType::Other("`$ cargo run".into()));
        assert_eq!(LineType::from("jklö"), LineType::Other("jklö".into()));
    }
}
<commit_msg>Stop printing arguments on invocation<commit_after>//! An implementation of [tldr](https://github.com/tldr-pages/tldr) in Rust.

#[macro_use] extern crate log;
#[cfg(feature = "logging")]extern crate env_logger;
extern crate docopt;
extern crate ansi_term;
extern crate flate2;
extern crate tar;
extern crate tempdir;
extern crate curl;
extern crate rustc_serialize;

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

use docopt::Docopt;

mod types;
mod tokenizer;
mod formatter;
mod updater;
mod error;

use tokenizer::Tokenizer;
use updater::Updater;
use error::TldrError;
use formatter::print_lines;

const NAME: &'static str = "tldr-rs";
const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const USAGE: &'static str = "
Usage:

    tldr <command>
    tldr [options]

Options:

    -h --help           Show this screen
    -v --version        Show version information
    -l --list           List all commands in the cache
    -f --render <file>  Render a specific markdown file
    -o --os <type>      Override the operating system [linux, osx, sunos]
    -u --update         Update the local cache
    -c --clear-cache    Clear the local cache

Examples:

    $ tldr tar
    $ tldr --list

To control the cache:

    $ tldr --update
    $ tldr --clear-cache

To render a local file (for testing):

    $ tldr --render /path/to/file.md
";
const ARCHIVE_URL: &'static str = "https://github.com/tldr-pages/tldr/archive/master.tar.gz";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_command: Option<String>,
    flag_help: bool,
    flag_version: bool,
    flag_list: bool,
    flag_render: Option<String>,
    flag_os: Option<String>,  // TODO enum
    flag_update: bool,
    flag_clear_cache: bool,
}

/// Open file, return a `BufRead` instance
fn get_file_reader(filepath: &str) -> Result<BufReader<File>, String> {
    let file = try!(
        File::open(filepath)
            .map_err(|msg| format!("Could not open file: {}", msg))
    );
    Ok(BufReader::new(file))
}

#[cfg(feature = "logging")]
fn init_log() {
    env_logger::init().unwrap();
}

#[cfg(not(feature = "logging"))]
fn init_log() { }

fn main() {

    // Initialize logger
    init_log();

    // Parse arguments
    let args: Args = Docopt::new(USAGE)
                            .and_then(|d| d.decode())
                            .unwrap_or_else(|e| e.exit());

    // Show version and exit
    if args.flag_version {
        println!("{} v{}", NAME, VERSION);
        process::exit(0);
    }

    // Clear cache, pass through
    if args.flag_clear_cache {
        println!("Flag --clear-cache not yet implemented.");
        process::exit(1);
    }

    // Update cache, pass through
    if args.flag_update {
        let dl = Updater::new(ARCHIVE_URL);
        let copied = dl.update().unwrap_or_else(|e| {
            match e {
                TldrError::UpdateError(msg) => println!("Could not update cache: {}", msg),
            };
            process::exit(1);
        });
        println!("Cached {} tldr pages.", copied);
    }

    // Render local file and exit
    if let Some(file) = args.flag_render {
        // Open file
        let reader = get_file_reader(&file).unwrap_or_else(|msg| {
            println!("{}", msg);
            process::exit(1);
        });

        // Create tokenizer and print output
        let mut tokenizer = Tokenizer::new(reader);
        print_lines(&mut tokenizer);

        process::exit(0);
    }

    // List cached commands and exit
    if args.flag_list {
        println!("Flag --list not yet implemented.");
        process::exit(1);
    }

    // Override OS and exit
    if let Some(os) = args.flag_os {
        println!("Flag --os not yet implemented.");
    }

    // Show command from cache
    if let Some(command) = args.arg_command {
        println!("Flag --os not yet implemented.");
        process::exit(1);
    }

    println!("{}", USAGE);
    process::exit(1);
}

#[cfg(test)]
mod test {
    use types::LineType;

    #[test]
    fn test_linetype_from_str() {
        assert_eq!(LineType::from(""), LineType::Empty);
        assert_eq!(LineType::from(" \n \r"), LineType::Empty);
        assert_eq!(LineType::from("# Hello there"), LineType::Title("Hello there".into()));
        assert_eq!(LineType::from("> tis a description \n"), LineType::Description("tis a description".into()));
        assert_eq!(LineType::from("- some command"), LineType::ExampleText("some command".into()));
        assert_eq!(LineType::from("`$ cargo run`"), LineType::ExampleCode("$ cargo run".into()));
        assert_eq!(LineType::from("`$ cargo run"), LineType::Other("`$ cargo run".into()));
        assert_eq!(LineType::from("jklö"), LineType::Other("jklö".into()));
    }
}
<|endoftext|>


<commit_before>extern crate kernel32;
extern crate user32;
extern crate winapi;
extern crate libc;
extern crate gdi32;

use winapi::windef::HWND;
use winapi::windef::HMENU;
use winapi::windef::HBRUSH;
use winapi::minwindef::HINSTANCE;

use winapi::minwindef::UINT;
use winapi::minwindef::DWORD;
use winapi::minwindef::WPARAM;
use winapi::minwindef::LPARAM;
use winapi::minwindef::LRESULT;
use winapi::winnt::LPCWSTR;

use winapi::winuser::WS_OVERLAPPEDWINDOW;
use winapi::winuser::WS_VISIBLE;
use winapi::winuser::WNDCLASSW;
use winapi::winuser::CF_BITMAP;

use std::os::windows::ffi::OsStrExt;
use std::ffi::OsStr;

const g_class_name: &'static str = "winshot";

// Rectangle represents screen coordinates
struct Rectangle {
	x: i32,
	y: i32,
	x2: i32,
	y2: i32,
}

// convert normal string to wide string
#[allow(dead_code)]
fn to_wstring(str: &str) -> *const u16 {
	let v: Vec<u16> = OsStr::new(str).encode_wide() . chain(Some(0).into_iter()).collect();
	v.as_ptr()
}

// This is our window message handler function. Currently,
// it only processes the WM_DESTROY message to exit our window properly on close event.
#[allow(dead_code)]
pub unsafe extern "system" fn window_proc(h_wnd: HWND, msg: UINT, w_param: WPARAM, l_param: LPARAM) -> LRESULT {
	if msg == winapi::winuser::WM_DESTROY {
		user32::PostQuitMessage(0);
	} else if msg == winapi::winuser::WM_MOUSEMOVE {
		return 0 as LRESULT;
	} else if msg == winapi::winuser::WM_LBUTTONDOWN {
		return 0 as LRESULT;
	} else if msg == winapi::winuser::WM_LBUTTONUP {
		return 0 as LRESULT;
	} else {
		return user32::DefWindowProcW(h_wnd, msg, w_param, l_param);
	}
}

// The following function hides the Console Window since we are building a GUI application.
#[allow(dead_code)]
fn hide_console_window() {
	let window = unsafe {
		kernel32::GetConsoleWindow()
	};

	if window != std::ptr::null_mut() {
		unsafe {
			user32::ShowWindow(window, winapi::SW_HIDE)
		};
	}
}

fn normalize_coords(rect: Rectangle) -> Rectangle {
    let Rectangle{mut x, mut y, mut x2, mut y2} = rect;

    if x > x2 {
        let tmp = x;
        x = x2;
        x2 = tmp;
    }
    if y > y2 {
        let tmp = y;
        y = y2;
        y2 = tmp;
    }

    Rectangle{x: x, y: y, x2: x2, y2: y2}
}

fn get_screen_rect() -> Rectangle {
	Rectangle{
		x /* left */: user32::GetSystemMetrics(winapi::winuser::SM_XVIRTUALSCREEN),
		y /* top */: user32::GetSystemMetrics(winapi::winuser::SM_YVIRTUALSCREEN),
		x2 /* right */: user32::GetSystemMetrics(winapi::winuser::SM_CXVIRTUALSCREEN) + user32::GetSystemMetrics(winapi::winuser::SM_XVIRTUALSCREEN),
		y2 /* bottom */: user32::GetSystemMetrics(winapi::winuser::SM_CYVIRTUALSCREEN) + user32::GetSystemMetrics(winapi::winuser::SM_CYVIRTUALSCREEN),
	}
}

fn capture_screen_clipboard(hwnd: HWND, mut rect: Rectangle) -> bool {
	// normalize coordinates
	let rect = normalize_coords(rect);
	let w = rect.x2 - rect.x;
	let h = rect.y2 - rect.y;

	let screen_dc = user32::GetDC(0 as HWND);
	let shot_dc = gdi32::CreateCompatibleDC(screen_dc);
	let shot_bitmap = gdi32::CreateCompatibleBitmap(screen_dc, w, h);
	let old_obj = gdi32::SelectObject(shot_dc, shot_bitmap);

	if !gdi32::BitBlt(shot_dc, 0, 0, w, h, screen_dc, rect.x, rect.y, 0 as DWORD) {
		println!("{:?}", "BitBlt failed? Perhaps.");
		false
	}

	let mut ret = false;
	if user32::OpenClipboard(hwnd) {
		if user32::EmptyClipboard() {
			if user32::SetClipboardData(CF_BITMAP, shot_bitmap) {
				ret = true;
			}
			user32::CloseClipboard();
		}
	} else {
		println!("{:?}", "could not open clipboard");
	}

	// Clean up
	gdi32::DeleteDC(shot_dc);
	gdi32::DeleteDC(screen_dc);
	gdi32::SelectObject(shot_dc, old_obj);

	return ret;
}

fn main() {
	unsafe {
		let hInstance = kernel32::GetModuleHandleW(0 as LPCWSTR);
		let m_class_name = to_wstring(g_class_name);
		let wnd = WNDCLASSW {
			hInstance: hInstance,
			lpszClassName: m_class_name,
			lpszMenuName: 0 as LPCWSTR,
			lpfnWndProc: Some(window_proc),
			cbClsExtra: 0,
			cbWndExtra: 0,
			style: winapi::winuser::CS_HREDRAW | winapi::winuser::CS_VREDRAW,
			hbrBackground: 0,
			hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDC_CROSS),
			hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
		};

		user32::RegisterClassW(&wnd);
		let rect = get_screen_rect();
		let exstyle = winapi::winuser::WS_EX_TRANSPARENT;
		let style = winapi::winuser::WS_POPUP;

		let win = user32::CreateWindowExW(exstyle,
			m_class_name,
			m_class_name,
			style,
			// dimensions
			0, 0, rect.x2, rect.y2,
			0, // no parent
			0 as HWND, // no menu
			hInstance, // module_instance
			0 as LPARAM,
		);

		user32::ShowWindow(win, winapi::winuser::SW_SHOW);
		user32::ShowWindow(win, winapi::winuser::SW_SHOWMAXIMIZED);
		user32::SetForegroundWindow(win);

		capture_screen_clipboard(win, Rectangle{
			x: 0,
			y: 0,
			x2: 200,
			y2: 200,
		});
		user32::DestroyWindow(win);
	}
}

// fn main() {
// 	// Here our unsafe code goes
// 	unsafe {
// 		// First we hide the console window
// 		hide_console_window();

// 		// Then we initialize the WNDCLASS structure
// 		let m_class_name = to_wstring(g_class_name);
// 		let wnd = WNDCLASSW {
// 			hInstance: 0 as HINSTANCE,
// 			lpszClassName = m_class_name,
// 			lpszMenuName: 0 as LPCWSTR,
// 			lpfnWndProc: Some(window_proc),

// 			style: winapi::winuser::CS_HREDRAW | winapi::winuser::CS_VREDRAW,

// 			cbClsExtra: 0,
// 			cbWndExtra: 0,

// 			hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
// 			hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
// 			hbrBackground: 16 as HBRUSH,

// 		};

// 		// Register our class
// 		user32::RegisterClassW(&wnd);

// 		let h_wnd_desktop = user32::GetDesktopWindow();

// 		user32::CreateWindowExA(0, "my_window".as_ptr() as *mut _,
// 			"Simple Window".as_ptr() as *mut _, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
// 			0, 0, 400, 400, h_wnd_desktop, 0 as HMENU, 0 as HINSTANCE,
// 			std::ptr::null_mut());

// 		let mut msg = winapi::winuser::MSG {
// 			hwnd: 0 as HWND,
// 			message: 0 as UINT,
// 			wParam: 0 as WPARAM,
// 			lParam: 0 as LPARAM,
// 			time: 0 as DWORD,
// 			pt : winapi::windef::POINT{ x: 0, y: 0, },
// 		};

// 		// Kick off the application loop
// 		loop {
// 			let pm = user32::PeekMessageW(&mut msg, 0 as HWND, 0, 0, winapi::winuser::PM_REMOVE);

// 			if pm == 0 {
// 				continue;
// 			}

// 			if msg.message == winapi::winuser::WM_QUIT {
// 				break;
// 			}

// 			user32::TranslateMessage(&mut msg);
// 			user32::DispatchMessageW(&mut msg);
// 		}
// 	}
// }<commit_msg>casting?<commit_after>extern crate kernel32;
extern crate user32;
extern crate winapi;
extern crate libc;
extern crate gdi32;

use winapi::windef::HWND;
use winapi::windef::HMENU;
use winapi::windef::HBRUSH;
use winapi::minwindef::HINSTANCE;

use winapi::minwindef::UINT;
use winapi::minwindef::DWORD;
use winapi::minwindef::WPARAM;
use winapi::minwindef::LPARAM;
use winapi::minwindef::LRESULT;
use winapi::winnt::LPCWSTR;

use winapi::winuser::WS_OVERLAPPEDWINDOW;
use winapi::winuser::WS_VISIBLE;
use winapi::winuser::WNDCLASSW;
use winapi::winuser::CF_BITMAP;

use std::os::windows::ffi::OsStrExt;
use std::ffi::OsStr;

const g_class_name: &'static str = "winshot";

// Rectangle represents screen coordinates
struct Rectangle {
	x: i32,
	y: i32,
	x2: i32,
	y2: i32,
}

// convert normal string to wide string
#[allow(dead_code)]
fn to_wstring(str: &str) -> *const u16 {
	let v: Vec<u16> = OsStr::new(str).encode_wide() . chain(Some(0).into_iter()).collect();
	v.as_ptr()
}

// This is our window message handler function. Currently,
// it only processes the WM_DESTROY message to exit our window properly on close event.
#[allow(dead_code)]
pub unsafe extern "system" fn window_proc(h_wnd: HWND, msg: UINT, w_param: WPARAM, l_param: LPARAM) -> LRESULT {
	if msg == winapi::winuser::WM_DESTROY {
		user32::PostQuitMessage(0);
	} else if msg == winapi::winuser::WM_MOUSEMOVE {
		return 0 as LRESULT;
	} else if msg == winapi::winuser::WM_LBUTTONDOWN {
		return 0 as LRESULT;
	} else if msg == winapi::winuser::WM_LBUTTONUP {
		return 0 as LRESULT;
	} else {
		return user32::DefWindowProcW(h_wnd, msg, w_param, l_param);
	}
}

// The following function hides the Console Window since we are building a GUI application.
#[allow(dead_code)]
fn hide_console_window() {
	let window = unsafe {
		kernel32::GetConsoleWindow()
	};

	if window != std::ptr::null_mut() {
		unsafe {
			user32::ShowWindow(window, winapi::SW_HIDE)
		};
	}
}

fn normalize_coords(rect: Rectangle) -> Rectangle {
    let Rectangle{mut x, mut y, mut x2, mut y2} = rect;

    if x > x2 {
        let tmp = x;
        x = x2;
        x2 = tmp;
    }
    if y > y2 {
        let tmp = y;
        y = y2;
        y2 = tmp;
    }

    Rectangle{x: x, y: y, x2: x2, y2: y2}
}

fn get_screen_rect() -> Rectangle {
	Rectangle{
		x /* left */: user32::GetSystemMetrics(winapi::winuser::SM_XVIRTUALSCREEN),
		y /* top */: user32::GetSystemMetrics(winapi::winuser::SM_YVIRTUALSCREEN),
		x2 /* right */: user32::GetSystemMetrics(winapi::winuser::SM_CXVIRTUALSCREEN) + user32::GetSystemMetrics(winapi::winuser::SM_XVIRTUALSCREEN),
		y2 /* bottom */: user32::GetSystemMetrics(winapi::winuser::SM_CYVIRTUALSCREEN) + user32::GetSystemMetrics(winapi::winuser::SM_CYVIRTUALSCREEN),
	}
}

fn capture_screen_clipboard(hwnd: HWND, mut rect: Rectangle) -> bool {
	// normalize coordinates
	let rect = normalize_coords(rect);
	let w = rect.x2 - rect.x;
	let h = rect.y2 - rect.y;

	let screen_dc = user32::GetDC(0 as HWND);
	let shot_dc = gdi32::CreateCompatibleDC(screen_dc);
	let shot_bitmap = gdi32::CreateCompatibleBitmap(screen_dc, w, h);
	let old_obj = gdi32::SelectObject(shot_dc, shot_bitmap);

	if !gdi32::BitBlt(shot_dc, 0, 0, w, h, screen_dc, rect.x, rect.y, 0 as DWORD) {
		println!("{:?}", "BitBlt failed? Perhaps.");
		false
	}

	let mut ret = false;
	if user32::OpenClipboard(hwnd) {
		if user32::EmptyClipboard() {
			if user32::SetClipboardData(CF_BITMAP, shot_bitmap) {
				ret = true;
			}
			user32::CloseClipboard();
		}
	} else {
		println!("{:?}", "could not open clipboard");
	}

	// Clean up
	gdi32::DeleteDC(shot_dc);
	gdi32::DeleteDC(screen_dc);
	gdi32::SelectObject(shot_dc, old_obj);

	return ret;
}

fn main() {
	unsafe {
		let hInstance = kernel32::GetModuleHandleW(0 as LPCWSTR);
		let m_class_name = to_wstring(g_class_name);
		let wnd = WNDCLASSW {
			hInstance: hInstance,
			lpszClassName: m_class_name,
			lpszMenuName: 0 as LPCWSTR,
			lpfnWndProc: Some(window_proc),
			cbClsExtra: 0,
			cbWndExtra: 0,
			style: winapi::winuser::CS_HREDRAW | winapi::winuser::CS_VREDRAW,
			hbrBackground: 0,
			hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDC_CROSS),
			hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
		};

		user32::RegisterClassW(&wnd);
		let rect = get_screen_rect();
		let exstyle = winapi::winuser::WS_EX_TRANSPARENT;
		let style = winapi::winuser::WS_POPUP;

		let win = user32::CreateWindowExW(exstyle,
			m_class_name.as_ptr() as *mut _,
			m_class_name.as_ptr() as *mut _,
			style,
			// dimensions
			0, 0, rect.x2, rect.y2,
			0, // no parent
			0 as HWND, // no menu
			hInstance, // module_instance
			0 as LPARAM,
		);

		user32::ShowWindow(win, winapi::winuser::SW_SHOW);
		user32::ShowWindow(win, winapi::winuser::SW_SHOWMAXIMIZED);
		user32::SetForegroundWindow(win);

		capture_screen_clipboard(win, Rectangle{
			x: 0,
			y: 0,
			x2: 200,
			y2: 200,
		});
		user32::DestroyWindow(win);
	}
}

// fn main() {
// 	// Here our unsafe code goes
// 	unsafe {
// 		// First we hide the console window
// 		hide_console_window();

// 		// Then we initialize the WNDCLASS structure
// 		let m_class_name = to_wstring(g_class_name);
// 		let wnd = WNDCLASSW {
// 			hInstance: 0 as HINSTANCE,
// 			lpszClassName = m_class_name,
// 			lpszMenuName: 0 as LPCWSTR,
// 			lpfnWndProc: Some(window_proc),

// 			style: winapi::winuser::CS_HREDRAW | winapi::winuser::CS_VREDRAW,

// 			cbClsExtra: 0,
// 			cbWndExtra: 0,

// 			hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
// 			hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
// 			hbrBackground: 16 as HBRUSH,

// 		};

// 		// Register our class
// 		user32::RegisterClassW(&wnd);

// 		let h_wnd_desktop = user32::GetDesktopWindow();

// 		user32::CreateWindowExA(0, "my_window".as_ptr() as *mut _,
// 			"Simple Window".as_ptr() as *mut _, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
// 			0, 0, 400, 400, h_wnd_desktop, 0 as HMENU, 0 as HINSTANCE,
// 			std::ptr::null_mut());

// 		let mut msg = winapi::winuser::MSG {
// 			hwnd: 0 as HWND,
// 			message: 0 as UINT,
// 			wParam: 0 as WPARAM,
// 			lParam: 0 as LPARAM,
// 			time: 0 as DWORD,
// 			pt : winapi::windef::POINT{ x: 0, y: 0, },
// 		};

// 		// Kick off the application loop
// 		loop {
// 			let pm = user32::PeekMessageW(&mut msg, 0 as HWND, 0, 0, winapi::winuser::PM_REMOVE);

// 			if pm == 0 {
// 				continue;
// 			}

// 			if msg.message == winapi::winuser::WM_QUIT {
// 				break;
// 			}

// 			user32::TranslateMessage(&mut msg);
// 			user32::DispatchMessageW(&mut msg);
// 		}
// 	}
// }<|endoftext|>


<commit_before><commit_msg>rm boxed.rs<commit_after><|endoftext|>


<commit_before>use rustc::lint::*;
use syntax::ptr::P;
use syntax::ast::*;
use syntax::ast_util::{is_comparison_binop, binop_to_string};
use syntax::codemap::{Span, Spanned};
use syntax::visit::FnKind;
use rustc::middle::ty;

use utils::{match_path, snippet, span_lint, walk_ptrs_ty};
use consts::constant;

declare_lint!(pub TOPLEVEL_REF_ARG, Warn,
              "a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not \
               `fn foo((ref x, ref y): (u8, u8))`)");

#[allow(missing_copy_implementations)]
pub struct TopLevelRefPass;

impl LintPass for TopLevelRefPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(TOPLEVEL_REF_ARG)
    }

    fn check_fn(&mut self, cx: &Context, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
        if let FnKind::FkClosure = k {
            // Does not apply to closures
            return
        }
        for ref arg in &decl.inputs {
            if let PatIdent(BindByRef(_), _, _) = arg.pat.node {
                span_lint(cx,
                    TOPLEVEL_REF_ARG,
                    arg.pat.span,
                    "`ref` directly on a function argument is ignored. Consider using a reference type instead."
                );
            }
        }
    }
}

declare_lint!(pub CMP_NAN, Deny,
              "comparisons to NAN (which will always return false, which is probably not intended)");

#[derive(Copy,Clone)]
pub struct CmpNan;

impl LintPass for CmpNan {
    fn get_lints(&self) -> LintArray {
        lint_array!(CMP_NAN)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
            if is_comparison_binop(cmp.node) {
                if let &ExprPath(_, ref path) = &left.node {
                    check_nan(cx, path, expr.span);
                }
                if let &ExprPath(_, ref path) = &right.node {
                    check_nan(cx, path, expr.span);
                }
            }
        }
    }
}

fn check_nan(cx: &Context, path: &Path, span: Span) {
    path.segments.last().map(|seg| if seg.identifier.name == "NAN" {
        span_lint(cx, CMP_NAN, span,
            "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead");
    });
}

declare_lint!(pub FLOAT_CMP, Warn,
              "using `==` or `!=` on float values (as floating-point operations \
               usually involve rounding errors, it is always better to check for approximate \
               equality within small bounds)");

#[derive(Copy,Clone)]
pub struct FloatCmp;

impl LintPass for FloatCmp {
    fn get_lints(&self) -> LintArray {
        lint_array!(FLOAT_CMP)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
            let op = cmp.node;
            if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) {
                if constant(cx, left).or_else(|| constant(cx, right)).map_or(
                        false, |c| c.0.as_float().map_or(false, |f| f == 0.0)) {
                    return;
                }
                span_lint(cx, FLOAT_CMP, expr.span, &format!(
                    "{}-comparison of f32 or f64 detected. Consider changing this to \
                     `abs({} - {}) < epsilon` for some suitable value of epsilon",
                    binop_to_string(op), snippet(cx, left.span, ".."),
                    snippet(cx, right.span, "..")));
            }
        }
    }
}

fn is_float(cx: &Context, expr: &Expr) -> bool {
    if let ty::TyFloat(_) = walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty {
        true
    } else {
        false
    }
}

declare_lint!(pub CMP_OWNED, Warn,
              "creating owned instances for comparing with others, e.g. `x == \"foo\".to_string()`");

#[derive(Copy,Clone)]
pub struct CmpOwned;

impl LintPass for CmpOwned {
    fn get_lints(&self) -> LintArray {
        lint_array!(CMP_OWNED)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
            if is_comparison_binop(cmp.node) {
                check_to_owned(cx, left, right.span);
                check_to_owned(cx, right, left.span)
            }
        }
    }
}

fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) {
    match expr.node {
        ExprMethodCall(Spanned{node: ref ident, ..}, _, ref args) => {
            let name = ident.name;
            if name == "to_string" ||
                name == "to_owned" && is_str_arg(cx, args) {
                    span_lint(cx, CMP_OWNED, expr.span, &format!(
                        "this creates an owned instance just for comparison. \
                         Consider using `{}.as_slice()` to compare without allocation",
                        snippet(cx, other_span, "..")))
                }
        },
        ExprCall(ref path, _) => {
            if let &ExprPath(None, ref path) = &path.node {
                if match_path(path, &["String", "from_str"]) ||
                    match_path(path, &["String", "from"]) {
                        span_lint(cx, CMP_OWNED, expr.span, &format!(
                            "this creates an owned instance just for comparison. \
                             Consider using `{}.as_slice()` to compare without allocation",
                            snippet(cx, other_span, "..")))
                    }
            }
        },
        _ => ()
    }
}

fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool {
    args.len() == 1 && if let ty::TyStr =
        walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty { true } else { false }
}

declare_lint!(pub MODULO_ONE, Warn, "taking a number modulo 1, which always returns 0");

#[derive(Copy,Clone)]
pub struct ModuloOne;

impl LintPass for ModuloOne {
    fn get_lints(&self) -> LintArray {
        lint_array!(MODULO_ONE)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprBinary(ref cmp, _, ref right) = expr.node {
            if let &Spanned {node: BinOp_::BiRem, ..} = cmp {
                if is_lit_one(right) {
                    cx.span_lint(MODULO_ONE, expr.span, "any number modulo 1 will be 0");
                }
            }
        }
    }
}

fn is_lit_one(expr: &Expr) -> bool {
    if let ExprLit(ref spanned) = expr.node {
        if let LitInt(1, _) = spanned.node {
            return true;
        }
    }
    false
}

declare_lint!(pub REDUNDANT_PATTERN, Warn, "using `name @ _` in a pattern");

#[derive(Copy,Clone)]
pub struct PatternPass;

impl LintPass for PatternPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(REDUNDANT_PATTERN)
    }

    fn check_pat(&mut self, cx: &Context, pat: &Pat) {
        if let PatIdent(_, ref ident, Some(ref right)) = pat.node {
            if right.node == PatWild(PatWildSingle) {
                cx.span_lint(REDUNDANT_PATTERN, pat.span, &format!(
                    "the `{} @ _` pattern can be written as just `{}`",
                    ident.node.name, ident.node.name));
            }
        }
    }
}
<commit_msg>FnKind::FkClosure -> FnKind::Closure<commit_after>use rustc::lint::*;
use syntax::ptr::P;
use syntax::ast::*;
use syntax::ast_util::{is_comparison_binop, binop_to_string};
use syntax::codemap::{Span, Spanned};
use syntax::visit::FnKind;
use rustc::middle::ty;

use utils::{match_path, snippet, span_lint, walk_ptrs_ty};
use consts::constant;

declare_lint!(pub TOPLEVEL_REF_ARG, Warn,
              "a function argument is declared `ref` (i.e. `fn foo(ref x: u8)`, but not \
               `fn foo((ref x, ref y): (u8, u8))`)");

#[allow(missing_copy_implementations)]
pub struct TopLevelRefPass;

impl LintPass for TopLevelRefPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(TOPLEVEL_REF_ARG)
    }

    fn check_fn(&mut self, cx: &Context, k: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
        if let FnKind::Closure = k {
            // Does not apply to closures
            return
        }
        for ref arg in &decl.inputs {
            if let PatIdent(BindByRef(_), _, _) = arg.pat.node {
                span_lint(cx,
                    TOPLEVEL_REF_ARG,
                    arg.pat.span,
                    "`ref` directly on a function argument is ignored. Consider using a reference type instead."
                );
            }
        }
    }
}

declare_lint!(pub CMP_NAN, Deny,
              "comparisons to NAN (which will always return false, which is probably not intended)");

#[derive(Copy,Clone)]
pub struct CmpNan;

impl LintPass for CmpNan {
    fn get_lints(&self) -> LintArray {
        lint_array!(CMP_NAN)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
            if is_comparison_binop(cmp.node) {
                if let &ExprPath(_, ref path) = &left.node {
                    check_nan(cx, path, expr.span);
                }
                if let &ExprPath(_, ref path) = &right.node {
                    check_nan(cx, path, expr.span);
                }
            }
        }
    }
}

fn check_nan(cx: &Context, path: &Path, span: Span) {
    path.segments.last().map(|seg| if seg.identifier.name == "NAN" {
        span_lint(cx, CMP_NAN, span,
            "doomed comparison with NAN, use `std::{f32,f64}::is_nan()` instead");
    });
}

declare_lint!(pub FLOAT_CMP, Warn,
              "using `==` or `!=` on float values (as floating-point operations \
               usually involve rounding errors, it is always better to check for approximate \
               equality within small bounds)");

#[derive(Copy,Clone)]
pub struct FloatCmp;

impl LintPass for FloatCmp {
    fn get_lints(&self) -> LintArray {
        lint_array!(FLOAT_CMP)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
            let op = cmp.node;
            if (op == BiEq || op == BiNe) && (is_float(cx, left) || is_float(cx, right)) {
                if constant(cx, left).or_else(|| constant(cx, right)).map_or(
                        false, |c| c.0.as_float().map_or(false, |f| f == 0.0)) {
                    return;
                }
                span_lint(cx, FLOAT_CMP, expr.span, &format!(
                    "{}-comparison of f32 or f64 detected. Consider changing this to \
                     `abs({} - {}) < epsilon` for some suitable value of epsilon",
                    binop_to_string(op), snippet(cx, left.span, ".."),
                    snippet(cx, right.span, "..")));
            }
        }
    }
}

fn is_float(cx: &Context, expr: &Expr) -> bool {
    if let ty::TyFloat(_) = walk_ptrs_ty(cx.tcx.expr_ty(expr)).sty {
        true
    } else {
        false
    }
}

declare_lint!(pub CMP_OWNED, Warn,
              "creating owned instances for comparing with others, e.g. `x == \"foo\".to_string()`");

#[derive(Copy,Clone)]
pub struct CmpOwned;

impl LintPass for CmpOwned {
    fn get_lints(&self) -> LintArray {
        lint_array!(CMP_OWNED)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
            if is_comparison_binop(cmp.node) {
                check_to_owned(cx, left, right.span);
                check_to_owned(cx, right, left.span)
            }
        }
    }
}

fn check_to_owned(cx: &Context, expr: &Expr, other_span: Span) {
    match expr.node {
        ExprMethodCall(Spanned{node: ref ident, ..}, _, ref args) => {
            let name = ident.name;
            if name == "to_string" ||
                name == "to_owned" && is_str_arg(cx, args) {
                    span_lint(cx, CMP_OWNED, expr.span, &format!(
                        "this creates an owned instance just for comparison. \
                         Consider using `{}.as_slice()` to compare without allocation",
                        snippet(cx, other_span, "..")))
                }
        },
        ExprCall(ref path, _) => {
            if let &ExprPath(None, ref path) = &path.node {
                if match_path(path, &["String", "from_str"]) ||
                    match_path(path, &["String", "from"]) {
                        span_lint(cx, CMP_OWNED, expr.span, &format!(
                            "this creates an owned instance just for comparison. \
                             Consider using `{}.as_slice()` to compare without allocation",
                            snippet(cx, other_span, "..")))
                    }
            }
        },
        _ => ()
    }
}

fn is_str_arg(cx: &Context, args: &[P<Expr>]) -> bool {
    args.len() == 1 && if let ty::TyStr =
        walk_ptrs_ty(cx.tcx.expr_ty(&args[0])).sty { true } else { false }
}

declare_lint!(pub MODULO_ONE, Warn, "taking a number modulo 1, which always returns 0");

#[derive(Copy,Clone)]
pub struct ModuloOne;

impl LintPass for ModuloOne {
    fn get_lints(&self) -> LintArray {
        lint_array!(MODULO_ONE)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprBinary(ref cmp, _, ref right) = expr.node {
            if let &Spanned {node: BinOp_::BiRem, ..} = cmp {
                if is_lit_one(right) {
                    cx.span_lint(MODULO_ONE, expr.span, "any number modulo 1 will be 0");
                }
            }
        }
    }
}

fn is_lit_one(expr: &Expr) -> bool {
    if let ExprLit(ref spanned) = expr.node {
        if let LitInt(1, _) = spanned.node {
            return true;
        }
    }
    false
}

declare_lint!(pub REDUNDANT_PATTERN, Warn, "using `name @ _` in a pattern");

#[derive(Copy,Clone)]
pub struct PatternPass;

impl LintPass for PatternPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(REDUNDANT_PATTERN)
    }

    fn check_pat(&mut self, cx: &Context, pat: &Pat) {
        if let PatIdent(_, ref ident, Some(ref right)) = pat.node {
            if right.node == PatWild(PatWildSingle) {
                cx.span_lint(REDUNDANT_PATTERN, pat.span, &format!(
                    "the `{} @ _` pattern can be written as just `{}`",
                    ident.node.name, ident.node.name));
            }
        }
    }
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Standard_deviation
struct StDev {
    len: usize,
    sum: f32,
    sum_sq: f32,
}

impl StDev {
    fn new() -> StDev {
        StDev {
            len: 0,
            sum: 0.0,
            sum_sq: 0.0,
        }
    }

    fn stdev(&mut self, n: f32) -> f32 {
        self.len += 1;
        self.sum += n;
        self.sum_sq += n.powi(2);
        let f32_len = self.len as f32;
        f32::sqrt(self.sum_sq / f32_len - self.sum.powi(2) / f32_len.powi(2))
    }
}

impl Default for StDev {
    fn default() -> Self {
        Self::new()
    }
}

fn main() {
    let test_data: [i32; 8] = [2, 4, 4, 4, 5, 5, 7, 9];
    let mut sd = StDev::new();
    for i in &test_data {
        println!("{}", &sd.stdev(*i as f32));
    }
}

#[test]
fn test_stdev() {
    let eps = 0.000001;
    let mut sd = StDev::new();
    // must be equal with up to eps precision
    assert!(sd.stdev(2.0).abs_sub(0.0) < eps);
    assert!(sd.stdev(4.0).abs_sub(1.0) < eps);
    assert!(sd.stdev(4.0).abs_sub(0.942809) < eps);
    assert!(sd.stdev(4.0).abs_sub(0.866025) < eps);
    assert!(sd.stdev(5.0).abs_sub(0.979796) < eps);
    assert!(sd.stdev(5.0).abs_sub(1.0) < eps);
    assert!(sd.stdev(7.0).abs_sub(1.399708) < eps);
    assert!(sd.stdev(9.0).abs_sub(2.0) < eps);
}
<commit_msg>remove deprecated usage of<commit_after>// http://rosettacode.org/wiki/Standard_deviation
struct StDev {
    len: usize,
    sum: f32,
    sum_sq: f32,
}

impl StDev {
    fn new() -> StDev {
        StDev {
            len: 0,
            sum: 0.0,
            sum_sq: 0.0,
        }
    }

    fn stdev(&mut self, n: f32) -> f32 {
        self.len += 1;
        self.sum += n;
        self.sum_sq += n.powi(2);
        let f32_len = self.len as f32;
        f32::sqrt(self.sum_sq / f32_len - self.sum.powi(2) / f32_len.powi(2))
    }
}

impl Default for StDev {
    fn default() -> Self {
        Self::new()
    }
}

fn main() {
    let test_data: [i32; 8] = [2, 4, 4, 4, 5, 5, 7, 9];
    let mut sd = StDev::new();
    for i in &test_data {
        println!("{}", &sd.stdev(*i as f32));
    }
}

#[test]
fn test_stdev() {
    let eps = 0.000001;
    let mut sd = StDev::new();
    // must be equal with up to eps precision
    assert!((sd.stdev(2.0) - 0.0).abs() < eps);
    assert!((sd.stdev(4.0) - 1.0).abs() < eps);
    assert!((sd.stdev(4.0) - 0.942809).abs() < eps);
    assert!((sd.stdev(4.0) - 0.866025).abs() < eps);
    assert!((sd.stdev(5.0) - 0.979796).abs() < eps);
    assert!((sd.stdev(5.0) - 1.0).abs() < eps);
    assert!((sd.stdev(7.0) - 1.399708).abs() < eps);
    assert!((sd.stdev(9.0) - 2.0).abs() < eps);
}
<|endoftext|>


<commit_before>//! Code for applying CSS styles to the DOM.
//!
//! This is not very interesting at the moment.  It will get much more
//! complicated if I add support for compound selectors.

use dom::{Node, Element, ElementData};
use css::{Stylesheet, Rule, Selector, Simple, SimpleSelector, Value, Keyword};
use std::collections::hashmap::HashMap;

/// Map from CSS property names to values.
pub type PropertyMap =  HashMap<String, Value>;

/// A node with associated style data.
pub struct StyledNode<'a> {
    pub node: &'a Node,
    pub specified_values: PropertyMap,
    pub children: Vec<StyledNode<'a>>,
}

#[deriving(PartialEq)]
pub enum Display {
    Inline,
    Block,
    None,
}

impl<'a> StyledNode<'a> {
    /// Return the specified value of a property if it exists, otherwise `None`.
    pub fn value(&self, name: &str) -> Option<Value> {
        self.specified_values.find_equiv(&name).map(|v| v.clone())
    }

    /// Return the specified value of property `name`, or property `fallback_name` if that doesn't
    /// exist. or value `default` if neither does.
    pub fn lookup(&self, name: &str, fallback_name: &str, default: &Value) -> Value {
        self.value(name).unwrap_or_else(|| self.value(fallback_name)
                        .unwrap_or_else(|| default.clone()))
    }

    /// The value of the `display` property (defaults to `Block`).
    pub fn display(&self) -> Display {
        match self.value("display") {
            Some(Keyword(s)) => match s.as_slice() {
                "inline" => Inline,
                "none" => None,
                _ => Block
            },
            _ => Block
        }
    }
}

/// Apply a stylesheet to an entire DOM tree, returning a StyledNode tree.
///
/// This finds only the specified values at the moment. Eventually it should be extended to find the
/// computed values too, including inherited values.
pub fn style_tree<'a>(root: &'a Node, stylesheet: &'a Stylesheet) -> StyledNode<'a> {
    StyledNode {
        node: root,
        specified_values: match root.node_type {
            Element(ref elem) => specified_values(elem, stylesheet),
            _ => HashMap::new(),
        },
        children: root.children.iter().map(|child| style_tree(child, stylesheet)).collect(),
    }
}

/// Apply styles to a single element, returning the specified styles.
///
/// To do: Allow multiple UA/author/user stylesheets, and implement the cascade.
fn specified_values(elem: &ElementData, stylesheet: &Stylesheet) -> PropertyMap {
    let mut values = HashMap::new();
    let mut rules = matching_rules(elem, stylesheet);

    // Go through the rules from lowest to highest specificity.
    rules.sort_by(|&(a, _), &(b, _)| a.specificity().cmp(&b.specificity()));
    for &(_, rule) in rules.iter() {
        for declaration in rule.declarations.iter() {
            values.insert(declaration.name.clone(), declaration.value.clone());
        }
    }
    values
}

/// A single CSS rule and the highest-specificity selector that resulted in a given match.
type MatchedRule<'a> = (&'a Selector, &'a Rule);

/// Find all CSS rules that match the given element.
fn matching_rules<'a>(elem: &ElementData, stylesheet: &'a Stylesheet) -> Vec<MatchedRule<'a>> {
    // For now, we just do a linear scan of all the rules.  For large
    // documents, it would be more efficient to store the rules in hash tables
    // based on tag name, id, class, etc.
    stylesheet.rules.iter()
        .filter_map(|rule| {
            // Find the first (highest-specificity) matching selector.
            rule.selectors.iter().find(|selector| matches(elem, *selector))
                .map(|selector| (selector, rule))
        }).collect()
}

/// Selector matching:
fn matches(elem: &ElementData, selector: &Selector) -> bool {
    match *selector {
        Simple(ref simple_selector) => matches_simple_selector(elem, simple_selector)
    }
}

fn matches_simple_selector(elem: &ElementData, selector: &SimpleSelector) -> bool {
    // Check type selector
    if selector.tag_name.iter().any(|name| elem.tag_name != *name) {
        return false;
    }

    // Check ID selector
    if selector.id.iter().any(|id| {
        elem.id().iter().any(|elem_id| {
            *elem_id != id
    })}) {
        return false;
    }

    // Check class selectors
    let elem_classes = elem.classes();
    if selector.class.iter().any(|class| !elem_classes.contains(&class.as_slice())) {
        return false;
    }

    // We didn't find any non-matching selector components.
    return true;
}
<commit_msg>Make matching return specificity directly<commit_after>//! Code for applying CSS styles to the DOM.
//!
//! This is not very interesting at the moment.  It will get much more
//! complicated if I add support for compound selectors.

use dom::{Node, Element, ElementData};
use css::{Stylesheet, Rule, Selector, Simple, SimpleSelector, Value, Keyword, Specificity};
use std::collections::hashmap::HashMap;

/// Map from CSS property names to values.
pub type PropertyMap =  HashMap<String, Value>;

/// A node with associated style data.
pub struct StyledNode<'a> {
    pub node: &'a Node,
    pub specified_values: PropertyMap,
    pub children: Vec<StyledNode<'a>>,
}

#[deriving(PartialEq)]
pub enum Display {
    Inline,
    Block,
    None,
}

impl<'a> StyledNode<'a> {
    /// Return the specified value of a property if it exists, otherwise `None`.
    pub fn value(&self, name: &str) -> Option<Value> {
        self.specified_values.find_equiv(&name).map(|v| v.clone())
    }

    /// Return the specified value of property `name`, or property `fallback_name` if that doesn't
    /// exist. or value `default` if neither does.
    pub fn lookup(&self, name: &str, fallback_name: &str, default: &Value) -> Value {
        self.value(name).unwrap_or_else(|| self.value(fallback_name)
                        .unwrap_or_else(|| default.clone()))
    }

    /// The value of the `display` property (defaults to `Block`).
    pub fn display(&self) -> Display {
        match self.value("display") {
            Some(Keyword(s)) => match s.as_slice() {
                "inline" => Inline,
                "none" => None,
                _ => Block
            },
            _ => Block
        }
    }
}

/// Apply a stylesheet to an entire DOM tree, returning a StyledNode tree.
///
/// This finds only the specified values at the moment. Eventually it should be extended to find the
/// computed values too, including inherited values.
pub fn style_tree<'a>(root: &'a Node, stylesheet: &'a Stylesheet) -> StyledNode<'a> {
    StyledNode {
        node: root,
        specified_values: match root.node_type {
            Element(ref elem) => specified_values(elem, stylesheet),
            _ => HashMap::new(),
        },
        children: root.children.iter().map(|child| style_tree(child, stylesheet)).collect(),
    }
}

/// Apply styles to a single element, returning the specified styles.
///
/// To do: Allow multiple UA/author/user stylesheets, and implement the cascade.
fn specified_values(elem: &ElementData, stylesheet: &Stylesheet) -> PropertyMap {
    let mut values = HashMap::new();
    let mut rules = matching_rules(elem, stylesheet);

    // Go through the rules from lowest to highest specificity.
    rules.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
    for &(_, rule) in rules.iter() {
        for declaration in rule.declarations.iter() {
            values.insert(declaration.name.clone(), declaration.value.clone());
        }
    }
    values
}

/// A single CSS rule and the highest-specificity selector that resulted in a given match.
type MatchedRule<'a> = (Specificity, &'a Rule);

/// Find all CSS rules that match the given element.
fn matching_rules<'a>(elem: &ElementData, stylesheet: &'a Stylesheet) -> Vec<MatchedRule<'a>> {
    // For now, we just do a linear scan of all the rules.  For large
    // documents, it would be more efficient to store the rules in hash tables
    // based on tag name, id, class, etc.
    stylesheet.rules.iter()
        .filter_map(|rule| {
            // Find the first (highest-specificity) matching selector.
            rule.selectors.iter().find(|selector| matches(elem, *selector))
                .map(|selector| (selector.specificity(), rule))
        }).collect()
}

/// Selector matching:
fn matches(elem: &ElementData, selector: &Selector) -> bool {
    match *selector {
        Simple(ref simple_selector) => matches_simple_selector(elem, simple_selector)
    }
}

fn matches_simple_selector(elem: &ElementData, selector: &SimpleSelector) -> bool {
    // Check type selector
    if selector.tag_name.iter().any(|name| elem.tag_name != *name) {
        return false;
    }

    // Check ID selector
    if selector.id.iter().any(|id| {
        elem.id().iter().any(|elem_id| {
            *elem_id != id
    })}) {
        return false;
    }

    // Check class selectors
    let elem_classes = elem.classes();
    if selector.class.iter().any(|class| !elem_classes.contains(&class.as_slice())) {
        return false;
    }

    // We didn't find any non-matching selector components.
    return true;
}
<|endoftext|>


<commit_before>#![crate_name = "unlink"]
#![feature(collections, core, old_io, old_path, rustc_private)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Colin Warren <me@zv.ms>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: unlink (GNU coreutils) 8.21 */

extern crate getopts;
extern crate libc;

use std::old_io as io;
use std::old_io::fs::{self, PathExtensions};
use std::old_io::print;

#[path = "../common/util.rs"]
#[macro_use]
mod util;

static NAME: &'static str = "unlink";

pub fn uumain(args: Vec<String>) -> i32 {
    let program = args[0].clone();
    let opts = [
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];

    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => {
            crash!(1, "invalid options\n{}", f)
        }
    };

    if matches.opt_present("help") {
        println!("unlink 1.0.0");
        println!("");
        println!("Usage:");
        println!("  {0} [FILE]... [OPTION]...", program);
        println!("");
        print(getopts::usage("Unlink the file at [FILE].", &opts).as_slice());
        return 0;
    }

    if matches.opt_present("version") {
        println!("unlink 1.0.0");
        return 0;
    }

    if matches.free.len() == 0 {
        crash!(1, "missing operand\nTry '{0} --help' for more information.", program);
    } else if matches.free.len() > 1 {
        crash!(1, "extra operand: '{1}'\nTry '{0} --help' for more information.", program, matches.free[1]);
    }

    let path = Path::new(matches.free[0].clone());

    let result = path.lstat().and_then(|info| {
        match info.kind {
            io::FileType::RegularFile => Ok(()),
            io::FileType::Symlink => Ok(()),
            _ => Err(io::IoError {
                kind: io::OtherIoError,
                desc: "is not a file or symlink",
                detail: None
            })
        }
    }).and_then(|_| {
        fs::unlink(&path)
    });

    match result {
        Ok(_) => (),
        Err(e) => {
            crash!(1, "cannot unlink '{0}': {1}", path.display(), e.desc);
        }
    }

    0
}
<commit_msg>fix `unlink`<commit_after>#![crate_name = "unlink"]
#![feature(rustc_private)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Colin Warren <me@zv.ms>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: unlink (GNU coreutils) 8.21 */

extern crate getopts;
extern crate libc;

use libc::consts::os::posix88::{S_IFMT, S_IFLNK, S_IFREG};
use libc::types::os::arch::c95::c_char;
use libc::types::os::arch::posix01::stat;
use libc::funcs::posix01::stat_::lstat;
use libc::funcs::posix88::unistd::unlink;

use std::mem::uninitialized;
use std::io::{Error, ErrorKind, Write};

#[path = "../common/util.rs"]
#[macro_use]
mod util;

static NAME: &'static str = "unlink";

pub fn uumain(args: Vec<String>) -> i32 {
    let opts = [
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];

    let matches = match getopts::getopts(&args[1..], &opts) {
        Ok(m) => m,
        Err(f) => {
            crash!(1, "invalid options\n{}", f)
        }
    };

    if matches.opt_present("help") {
        println!("unlink 1.0.0");
        println!("");
        println!("Usage:");
        println!("  {0} [FILE]... [OPTION]...", args[0]);
        println!("");
        println!("{}", getopts::usage("Unlink the file at [FILE].", &opts));
        return 0;
    }

    if matches.opt_present("version") {
        println!("unlink 1.0.0");
        return 0;
    }

    if matches.free.len() == 0 {
        crash!(1, "missing operand\nTry '{0} --help' for more information.", args[0]);
    } else if matches.free.len() > 1 {
        crash!(1, "extra operand: '{1}'\nTry '{0} --help' for more information.", args[0], matches.free[1]);
    }

    let st_mode = {
        let mut buf: stat = unsafe { uninitialized() };
        let result = unsafe { lstat(matches.free[0].as_ptr() as *const c_char, &mut buf as *mut stat) };

        if result < 0 {
            crash!(1, "Cannot stat '{}': {}", matches.free[0], Error::last_os_error());
        }

        buf.st_mode & S_IFMT
    };

    let result = if st_mode != S_IFREG && st_mode != S_IFLNK {
        Err(Error::new(ErrorKind::Other, "Not a regular file or symlink"))
    } else {
        let result = unsafe { unlink(matches.free[0].as_ptr() as *const c_char) };

        if result < 0 {
            Err(Error::last_os_error())
        } else {
            Ok(())
        }
    };

    match result {
        Ok(_) => (),
        Err(e) => {
            crash!(1, "cannot unlink '{0}': {1}", matches.free[0], e);
        }
    }

    0
}
<|endoftext|>


<commit_before>//!
//! Desync pipes provide a way to generate and process streams via a `Desync` object
//!

use super::desync::*;

use futures::*;
use futures::executor;
use futures::executor::Spawn;

use std::mem;
use std::sync::*;
use std::thread;
use std::thread::JoinHandle;
use std::result::Result;
use std::collections::{HashMap, HashSet};

lazy_static! {
    /// The shared poll thread that's used to schedule events from pipe streams
    static ref POLL_THREAD: PollThread = PollThread::new();
}

///
/// Pipes a stream into a desync object. Whenever an item becomes available on the stream, the
/// processing function is called asynchronously with the item that was received.
///
/// Piping a stream to a `Desync` like this will cause it to start executing: ie, this is
/// similar to calling `executor::spawn(stream)`, except that the stream will immediately
/// start draining into the `Desync` object.
///
pub fn pipe_in<Core, S, ProcessFn>(desync: Arc<Desync<Core>>, stream: S, process: ProcessFn)
where   Core:       'static+Send,
        S:          'static+Send+Stream,
        S::Item:    Send,
        S::Error:   Send,
        ProcessFn:  'static+Send+FnMut(&mut Core, Result<S::Item, S::Error>) -> () {

    // Need a mutable version of the stream
    let mut stream = stream;

    // Wrap the process fn up so we can call it asynchronously
    // (it doesn't really need to be in a mutex as it's only called by our object but we need to make it pass Rust's checks and we don't have a way to specify this at the moment)
    let process = Arc::new(Mutex::new(process));

    // Poll the stream on the poll thread
    POLL_THREAD.monitor(move || {
        loop {
            // Read the current status of the stream
            let process     = Arc::clone(&process);
            let next        = stream.poll();

            match next {
                // Just wait if the stream is not ready
                Ok(Async::NotReady) => { return Ok(Async::NotReady); },

                // Stream returned a value
                Ok(Async::Ready(Some(next))) => {
                    // Process the value on the stream
                    desync.async(move |core| {
                        let mut process = process.lock().unwrap();
                        let process     = &mut *process;
                        process(core, Ok(next));
                    });
                },

                // Stream returned an error
                Err(e) => {
                    // Process the error on the stream
                    desync.async(move |core| {
                        let mut process = process.lock().unwrap();
                        let process     = &mut *process;
                        process(core, Err(e));
                    });
                },

                // Stream finished
                Ok(Async::Ready(None)) => { return Ok(Async::Ready(())); }
            }
        }
    });
}

/*
///
/// Pipes a stream into this object. Whenever an item becomes available on the stream, the
/// processing function is called asynchronously with the item that was received. The
/// return value is placed onto the output stream.
///
pub fn pipe<Core, S, Output, OutputErr, ProcessFn>(desync: Arc<Desync<Core>>, stream: S, process: ProcessFn) -> Box<dyn Stream<Item=Output, Error=OutputErr>>
where   Core:       'static+Send,
        S:          'static+Send+Stream,
        S::Item:    Send,
        S::Error:   Send,
        Output:     Send,
        OutputErr:  Send,
        ProcessFn:  'static+Send+FnMut(&mut Core, Result<S::Item, S::Error>) -> Result<Output, OutputErr> {
    unimplemented!()
}
*/

///
/// In order to implement the polling functions, we need a thread that runs the executor
/// for any streams that we're currently piping (calling pipe_in or pipe will effectively
/// need to spawn the relevant stream).
///
/// This represents that thread. There's a bit of a limitation in that the `poll` methods
/// for the various streams will block the thread so this may start to bottleneck at times of
/// high load or with streams with poll methods that take significant time to execute.
///
struct PollThread {
    /// The poll functions that are being monitored by this thread
    notifications: Arc<Mutex<PollNotifications>>,

    /// The function that should be called for every notification ID
    poll_functions: Arc<Mutex<HashMap<u32, Spawn<Box<Future<Item=(), Error=()>+Send>>>>>,

    /// The joinhandle of the running thread
    thread: Arc<JoinHandle<()>>
}

///
/// Stores things being monitored
///
struct PollNotifications {
    /// Next available ID for a polling function
    next_id: u32,

    /// Poll functions where the notify handle has been set
    notified_ids: HashSet<u32>
}

///
/// Provides the 'Notify' interface for a polling function with a particular ID
///
struct PollNotify {
    /// The ID that should be marked as notified when the callback is made
    id: u32,

    /// The structure where the notifications are stored
    notifications: Arc<Mutex<PollNotifications>>,

    /// The thread that should be notified when this notification occurs
    thread: thread::Thread
}

impl PollThread {
    ///
    /// Creates a new poll thread
    ///
    pub fn new() -> PollThread {
        // Create the monitors for the new thread
        let notifications = PollNotifications {
            next_id:        0,
            notified_ids:   HashSet::new()
        };
        let notifications = Arc::new(Mutex::new(notifications));

        // Create the set of polling functions
        let poll_functions = Arc::new(Mutex::new(HashMap::new()));

        // Run the thread with the monitors
        let thread = Self::run(Arc::clone(&notifications), Arc::clone(&poll_functions));
        let thread = Arc::new(thread);

        // Generate the thread object
        let thread = PollThread {
            notifications:  notifications,
            poll_functions: poll_functions,
            thread:         thread
        };

        thread
    }

    ///
    /// Starts the poll thread running (poll threads cannot currently be stopped)
    ///
    fn run(notifications: Arc<Mutex<PollNotifications>>, functions: Arc<Mutex<HashMap<u32, Spawn<Box<Future<Item=(), Error=()>+Send>>>>>) -> JoinHandle<()> {
        thread::spawn(move || {
            loop {
                // Park the thread until there is something to do
                thread::park();

                // Fetch the list of notified functions we should call
                let to_notify = {
                    let mut notifications   = notifications.lock().unwrap();
                    let mut to_notify       = HashSet::new();

                    mem::swap(&mut to_notify, &mut notifications.notified_ids);

                    to_notify
                };

                // Notify each function in turn
                let mut functions   = functions.lock().unwrap();
                let thread          = thread::current();

                for function_id in to_notify {
                    // Fetch the function. If it returns false, we need to remove it from the list
                    let finished_polling = functions.get_mut(&function_id)
                        .map(|poll_function| {
                            // Create the notification structure
                            let notify = PollNotify {
                                id:             function_id,
                                notifications:  Arc::clone(&notifications),
                                thread:         thread.clone()
                            };

                            // Call the polling function
                            poll_function.poll_future_notify(&Arc::new(notify), 0)
                        })
                        .unwrap_or(Ok(Async::Ready(())));

                    // If the polling function completes, then remove the function
                    if finished_polling == Ok(Async::Ready(())) {
                        functions.remove(&function_id);
                    }
                }
            }
        })
    }

    ///
    /// Adds a polling function to the current thread. It will be called using the futures
    /// notification system (ie, can call things like the stream poll function)
    ///
    pub fn monitor<PollFn>(&self, poll_fn: PollFn)
    where PollFn: 'static+Send+FnMut() -> Poll<(), ()> {
        let mut functions       = self.poll_functions.lock().unwrap();
        let mut notifications   = self.notifications.lock().unwrap();

        // Get an ID for this monitor
        let id = notifications.next_id;
        notifications.next_id += 1;

        // Turn the polling function into a future
        let poll_fn: Box<dyn Future<Item=(), Error=()>+Send> = Box::new(future::poll_fn(poll_fn));
        let poll_fn = executor::spawn(poll_fn);

        functions.insert(id, poll_fn);

        // Mark it as notified
        notifications.notified_ids.insert(id);

        // Wake the thread
        self.thread.thread().unpark();
    }
}

impl executor::Notify for PollNotify {
    fn notify(&self, _id: usize) {
        // Add our ID to the notification list
        let mut notifications = self.notifications.lock().unwrap();
        notifications.notified_ids.insert(self.id);

        // Wake the thread
        self.thread.unpark();
    }
}
<commit_msg>Want to use a desync-based approach rather than a thread-based approach for our monitors<commit_after>//!
//! Desync pipes provide a way to generate and process streams via a `Desync` object
//!

use super::desync::*;

use futures::*;
use futures::executor;
use futures::executor::Spawn;

use std::mem;
use std::sync::*;
use std::thread;
use std::thread::JoinHandle;
use std::result::Result;
use std::collections::{HashMap, HashSet};

lazy_static! {
    /// The shared poll thread that's used to schedule events from pipe streams
    static ref POLL_THREAD: PollThread = PollThread::new();
}

///
/// Pipes a stream into a desync object. Whenever an item becomes available on the stream, the
/// processing function is called asynchronously with the item that was received.
///
/// Piping a stream to a `Desync` like this will cause it to start executing: ie, this is
/// similar to calling `executor::spawn(stream)`, except that the stream will immediately
/// start draining into the `Desync` object.
///
pub fn pipe_in<Core, S, ProcessFn>(desync: Arc<Desync<Core>>, stream: S, process: ProcessFn)
where   Core:       'static+Send,
        S:          'static+Send+Stream,
        S::Item:    Send,
        S::Error:   Send,
        ProcessFn:  'static+Send+FnMut(&mut Core, Result<S::Item, S::Error>) -> () {

    // Need a mutable version of the stream
    let mut stream = stream;

    // Wrap the process fn up so we can call it asynchronously
    // (it doesn't really need to be in a mutex as it's only called by our object but we need to make it pass Rust's checks and we don't have a way to specify this at the moment)
    let process = Arc::new(Mutex::new(process));

    // Poll the stream on the poll thread
    POLL_THREAD.monitor(move || {
        loop {
            // Read the current status of the stream
            let process     = Arc::clone(&process);
            let next        = stream.poll();

            match next {
                // Just wait if the stream is not ready
                Ok(Async::NotReady) => { return Ok(Async::NotReady); },

                // Stream returned a value
                Ok(Async::Ready(Some(next))) => {
                    // Process the value on the stream
                    desync.async(move |core| {
                        let mut process = process.lock().unwrap();
                        let process     = &mut *process;
                        process(core, Ok(next));
                    });
                },

                // Stream returned an error
                Err(e) => {
                    // Process the error on the stream
                    desync.async(move |core| {
                        let mut process = process.lock().unwrap();
                        let process     = &mut *process;
                        process(core, Err(e));
                    });
                },

                // Stream finished
                Ok(Async::Ready(None)) => { return Ok(Async::Ready(())); }
            }
        }
    });
}

/*
///
/// Pipes a stream into this object. Whenever an item becomes available on the stream, the
/// processing function is called asynchronously with the item that was received. The
/// return value is placed onto the output stream.
///
pub fn pipe<Core, S, Output, OutputErr, ProcessFn>(desync: Arc<Desync<Core>>, stream: S, process: ProcessFn) -> Box<dyn Stream<Item=Output, Error=OutputErr>>
where   Core:       'static+Send,
        S:          'static+Send+Stream,
        S::Item:    Send,
        S::Error:   Send,
        Output:     Send,
        OutputErr:  Send,
        ProcessFn:  'static+Send+FnMut(&mut Core, Result<S::Item, S::Error>) -> Result<Output, OutputErr> {
    unimplemented!()
}
*/

///
/// The main polling component for that implements the stream pipes
///
struct PollThread {
}

///
/// Provides the 'Notify' interface for a polling function with a particular ID
///
struct PollNotify {
}

impl PollThread {
    ///
    /// Creates a new poll thread
    ///
    pub fn new() -> PollThread {
        PollThread {

        }
    }

    ///
    /// Adds a polling function to the current thread. It will be called using the futures
    /// notification system (ie, can call things like the stream poll function)
    ///
    pub fn monitor<PollFn>(&self, poll_fn: PollFn)
    where PollFn: 'static+Send+FnMut() -> Poll<(), ()> {

    }
}

impl executor::Notify for PollNotify {
    fn notify(&self, _id: usize) {
    }
}
<|endoftext|>


<commit_before>extern crate chrono;
extern crate regex;
extern crate toml;

use self::chrono::{Duration, NaiveTime};
use self::regex::Regex;
use self::toml::Value as Toml;

use constant::CONFIG_FILE_NAME;
use error::{CannotHappenError, CliError, ConfigError, ConfigErrorKind};
use lib::io::*;
use std::borrow::Borrow;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::{Error as IoError, Read};
use std::path::PathBuf;
use std::str::FromStr;

const CONFIG_KEY_BURN_AFTER  : &'static str = "burn.after";
const CONFIG_KEY_SWEEP_PERIOD: &'static str = "sweep.period";
const CONFIG_KEY_SWEEP_TIME  : &'static str = "sweep.time";

const CONFIG_DEFAULT_VALUE_BURN_AFTER  : &'static str = "2 weeks";
const CONFIG_DEFAULT_VALUE_SWEEP_PERIOD: &'static str = "daily";
const CONFIG_DEFAULT_VALUE_SWEEP_TIME  : &'static str = "00:00";

pub enum ConfigKey {
    BurnAfter,
    SweepPeriod,
    SweepTime,
}

impl ConfigKey {
    pub fn from<S: AsRef<str>>(key: S) -> Result<ConfigKey, ConfigError> {
        match key.as_ref().trim() {
            CONFIG_KEY_BURN_AFTER   => Ok(ConfigKey::BurnAfter),
            CONFIG_KEY_SWEEP_PERIOD => Ok(ConfigKey::SweepPeriod),
            CONFIG_KEY_SWEEP_TIME   => Ok(ConfigKey::SweepTime),
            _                       => Err(ConfigError::new(ConfigErrorKind::InvalidKey)),
        }
    }

    fn to_str(&self) -> &str {
        match *self {
            ConfigKey::BurnAfter   => CONFIG_KEY_BURN_AFTER,
            ConfigKey::SweepPeriod => CONFIG_KEY_SWEEP_PERIOD,
            ConfigKey::SweepTime   => CONFIG_KEY_SWEEP_TIME,
        }
    }

    fn to_pair(&self) -> (&str, &str) {
        let key = self
            .to_str()
            .split('.')
            .collect::<Vec<&str>>();
        (key[0], key[1]) // unsafe!
    }
}

type EditableTomlCore = BTreeMap<String, BTreeMap<String, String>>;

#[derive(Clone)]
struct EditableToml(EditableTomlCore);

impl EditableToml {
    fn from(toml: Toml) -> Result<Self, ConfigError> {
        toml::decode::<EditableTomlCore>(toml)
            .map(|c| EditableToml(c))
            .ok_or(ConfigError::new(ConfigErrorKind::Something))
    }

    fn overwrite<CK: Borrow<ConfigKey>>(&mut self, key: CK, value: String) {
        let &mut EditableToml(ref mut core) = self;

        let (first, second) = key.borrow().to_pair();
        let second          = second.to_string();

        if core.contains_key(first) {
            core.get_mut(first).map(|e| e.insert(second, value));
        } else {
            let mut entry = BTreeMap::new();
            entry.insert(second, value);

            core.insert(first.to_string(), entry);
        }
    }

    fn to_toml(self) -> Toml {
        let EditableToml(core) = self;
        toml::encode(&core)
    }
}

pub struct Config {
    toml: Toml,
}

impl Config {
    fn path() -> PathBuf {
        path_buf![super::working_dir(), CONFIG_FILE_NAME]
    }

    pub fn exist() -> bool {
        Self::path().is_file()
    }

    fn to_string(&self) -> String {
        toml::encode_str(&self.toml)
    }

    pub fn create(&self) -> Result<(), IoError> {
        print_with_tag(Tag::Info, format!("Create \"{}\" file", CONFIG_FILE_NAME));

        super::create_setting_file(Self::path(), self.to_string())
    }

    fn _new(toml: Toml) -> Self {
        Config { toml: toml }
    }

    pub fn default() -> Self {
        let mut editable = EditableToml(BTreeMap::new());
        editable.overwrite(ConfigKey::BurnAfter  , CONFIG_DEFAULT_VALUE_BURN_AFTER  .to_string());
        editable.overwrite(ConfigKey::SweepPeriod, CONFIG_DEFAULT_VALUE_SWEEP_PERIOD.to_string());
        editable.overwrite(ConfigKey::SweepTime  , CONFIG_DEFAULT_VALUE_SWEEP_TIME  .to_string());

        Self::_new(editable.to_toml())
    }

    pub fn read() -> Result<Self, CliError> {
        print_with_tag(Tag::Info, format!("Read \"{}\" file", CONFIG_FILE_NAME));

        let mut f = try!(File::open(Self::path()));

        let mut contents = String::new();
        try!(f.read_to_string(&mut contents));

        let result = contents
            .parse()
            .map_err(|e: Vec<_>| e.into_iter().next());
        let toml = match result {
            Ok(toml)    => toml,
            Err(option) => match option {
                Some(e) => return Err(From::from(e)),
                None    => return Err(From::from(CannotHappenError)),
            },
        };

        Ok(Self::_new(toml))
    }

    pub fn get<CK: Borrow<ConfigKey>>(&self, key: CK) -> Result<String, CliError> {
        let key = key.borrow();

        let result = self.toml
            .lookup(key.to_str())
            .ok_or(ConfigError::new(match *key {
                ConfigKey::BurnAfter   => ConfigErrorKind::NotFoundBurnAfter,
                ConfigKey::SweepPeriod => unimplemented!(),
                ConfigKey::SweepTime   => unimplemented!(),
            }));
        let value = try!(result);

        value
            .as_str()
            .ok_or(From::from(ConfigError::new(ConfigErrorKind::NonStringValue)))
            .and_then(|s| Self::validate(key, s))
    }

    pub fn to_duration(value: String) -> Result<Duration, CliError> {
        let mut value   = value.split(' ');
        let (num, unit) = match (value.next(), value.next()) {
            (Some(num), Some(unit)) => (num, unit),
            _                       => return Err(From::from(CannotHappenError)),
        };
        let num = try!(num.parse::<u32>()) as i64;

        let duration = match unit {
            "day"  | "days"  => Duration::days(num),
            "week" | "weeks" => Duration::weeks(num),
            _                => return Err(From::from(CannotHappenError)),
        };

        Ok(duration)
    }

    pub fn set<CK: Borrow<ConfigKey>>(mut self, key: CK, value: String) -> Result<Self, ConfigError> {
        let mut editable = try!(EditableToml::from(self.toml));

        editable.overwrite(key, value);

        self.toml = editable.to_toml();

        Ok(self)
    }

    pub fn validate<CK: Borrow<ConfigKey>, S: AsRef<str>>(key: CK, value: S) -> Result<String, CliError> {
        let value = value.as_ref().trim();

        match *key.borrow() {
            ConfigKey::BurnAfter => {
                let pair = try!(Regex::new(r"^(?P<num>\d+)\s?(?P<unit>days?|weeks?)$"))
                    .captures(value)
                    .map_or((None, None), |caps| (caps.name("num"), caps.name("unit")));
                let (num, unit) = match pair {
                    (Some(num), Some(unit)) => (num, unit),
                    _                       => return Err(From::from(ConfigError::new(ConfigErrorKind::BurnAfter))),
                };
                Ok(format!("{} {}", num, unit))
            },
            ConfigKey::SweepPeriod => {
                match value {
                    "daily" | "weekly" => Ok(value.to_string()),
                    _                  => Err(From::from(ConfigError::new(ConfigErrorKind::SweepPeriod))),
                }
            },
            ConfigKey::SweepTime => {
                match NaiveTime::from_str(format!("{}:00", value).as_ref()) {
                    Ok(_)  => Ok(value.to_string()),
                    // should set Err(e) to Error::cause()
                    Err(_) => Err(From::from(ConfigError::new(ConfigErrorKind::SweepTime))),
                }
            },
        }
    }
}

#[test]
fn config_key_to_pair_should_return_pair() {
    let keys = [
        (ConfigKey::BurnAfter  , CONFIG_KEY_BURN_AFTER  ),
        (ConfigKey::SweepPeriod, CONFIG_KEY_SWEEP_PERIOD),
        (ConfigKey::SweepTime  , CONFIG_KEY_SWEEP_TIME  ),
    ];
    for &(ref key, ref correct) in &keys {
        let (first, second) = key.to_pair();
        assert_eq!(correct.to_string(), format!("{}.{}", first, second));
    }
}

#[test]
fn editable_toml_overwrite_should_add_value() {
    let b_tree_map: EditableTomlCore = BTreeMap::new();
    let mut correct                  = b_tree_map.clone();
    let mut editable                 = EditableToml(b_tree_map);

    let v1 = "value1".to_string();

    let mut entry         = BTreeMap::new();
    let key1              = ConfigKey::BurnAfter;
    let (first1, second1) = key1.to_pair();
    entry.insert(second1.to_string(), v1.clone());
    correct.insert(first1.to_string(), entry);

    editable.overwrite(ConfigKey::BurnAfter, v1);
    let EditableToml(calculated) = editable.clone();

    assert_eq!(&correct, &calculated);

    let v2 = "value2".to_string();
    let v3 = "value3".to_string();

    let mut entry         = BTreeMap::new();
    let key2              = ConfigKey::SweepPeriod;
    let (first2, second2) = key2.to_pair();
    let key3              = ConfigKey::SweepTime;
    let (_, second3)      = key3.to_pair();
    entry.insert(second2.to_string(), v2.clone());
    entry.insert(second3.to_string(), v3.clone());
    correct.insert(first2.to_string(), entry);

    editable.overwrite(ConfigKey::SweepPeriod, v2);
    editable.overwrite(ConfigKey::SweepTime  , v3);
    let &EditableToml(ref calculated) = &editable;

    assert_eq!(&correct, calculated);
}

#[test]
fn default_should_return_config() {
    let correct: Toml = format!(
        r#"
            [burn]
            after = "{}"
            [sweep]
            period = "{}"
            time   = "{}"
        "#,
        CONFIG_DEFAULT_VALUE_BURN_AFTER,
        CONFIG_DEFAULT_VALUE_SWEEP_PERIOD,
        CONFIG_DEFAULT_VALUE_SWEEP_TIME
    )
        .parse()
        .unwrap();

    assert_eq!(correct, Config::default().toml);
}

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

    #[test]
    fn get_should_return_ok() {
    }
    #[test]
    fn get_should_return_err() {
    }

    #[test]
    fn set_should_return_ok() {
    }
    #[test]
    fn set_should_retrun_err() {
    }

    #[test]
    fn to_duration_should_return_ok() {
    }
    #[test]
    fn to_duration_should_return_err() {
    }

    #[test]
    fn validate_should_return_ok() {
    }
    #[test]
    fn validate_should_return_err() {
    }
}
<commit_msg>[Test] Change where using unwrap()<commit_after>extern crate chrono;
extern crate regex;
extern crate toml;

use self::chrono::{Duration, NaiveTime};
use self::regex::Regex;
use self::toml::Value as Toml;

use constant::CONFIG_FILE_NAME;
use error::{CannotHappenError, CliError, ConfigError, ConfigErrorKind};
use lib::io::*;
use std::borrow::Borrow;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::{Error as IoError, Read};
use std::path::PathBuf;
use std::str::FromStr;

const CONFIG_KEY_BURN_AFTER  : &'static str = "burn.after";
const CONFIG_KEY_SWEEP_PERIOD: &'static str = "sweep.period";
const CONFIG_KEY_SWEEP_TIME  : &'static str = "sweep.time";

const CONFIG_DEFAULT_VALUE_BURN_AFTER  : &'static str = "2 weeks";
const CONFIG_DEFAULT_VALUE_SWEEP_PERIOD: &'static str = "daily";
const CONFIG_DEFAULT_VALUE_SWEEP_TIME  : &'static str = "00:00";

pub enum ConfigKey {
    BurnAfter,
    SweepPeriod,
    SweepTime,
}

impl ConfigKey {
    pub fn from<S: AsRef<str>>(key: S) -> Result<ConfigKey, ConfigError> {
        match key.as_ref().trim() {
            CONFIG_KEY_BURN_AFTER   => Ok(ConfigKey::BurnAfter),
            CONFIG_KEY_SWEEP_PERIOD => Ok(ConfigKey::SweepPeriod),
            CONFIG_KEY_SWEEP_TIME   => Ok(ConfigKey::SweepTime),
            _                       => Err(ConfigError::new(ConfigErrorKind::InvalidKey)),
        }
    }

    fn to_str(&self) -> &str {
        match *self {
            ConfigKey::BurnAfter   => CONFIG_KEY_BURN_AFTER,
            ConfigKey::SweepPeriod => CONFIG_KEY_SWEEP_PERIOD,
            ConfigKey::SweepTime   => CONFIG_KEY_SWEEP_TIME,
        }
    }

    fn to_pair(&self) -> (&str, &str) {
        let key = self
            .to_str()
            .split('.')
            .collect::<Vec<&str>>();
        (key[0], key[1]) // unsafe!
    }
}

type EditableTomlCore = BTreeMap<String, BTreeMap<String, String>>;

#[derive(Clone)]
struct EditableToml(EditableTomlCore);

impl EditableToml {
    fn from(toml: Toml) -> Result<Self, ConfigError> {
        toml::decode::<EditableTomlCore>(toml)
            .map(|c| EditableToml(c))
            .ok_or(ConfigError::new(ConfigErrorKind::Something))
    }

    fn overwrite<CK: Borrow<ConfigKey>>(&mut self, key: CK, value: String) {
        let &mut EditableToml(ref mut core) = self;

        let (first, second) = key.borrow().to_pair();
        let second          = second.to_string();

        if core.contains_key(first) {
            core.get_mut(first).map(|e| e.insert(second, value));
        } else {
            let mut entry = BTreeMap::new();
            entry.insert(second, value);

            core.insert(first.to_string(), entry);
        }
    }

    fn to_toml(self) -> Toml {
        let EditableToml(core) = self;
        toml::encode(&core)
    }
}

pub struct Config {
    toml: Toml,
}

impl Config {
    fn path() -> PathBuf {
        path_buf![super::working_dir(), CONFIG_FILE_NAME]
    }

    pub fn exist() -> bool {
        Self::path().is_file()
    }

    fn to_string(&self) -> String {
        toml::encode_str(&self.toml)
    }

    pub fn create(&self) -> Result<(), IoError> {
        print_with_tag(Tag::Info, format!("Create \"{}\" file", CONFIG_FILE_NAME));

        super::create_setting_file(Self::path(), self.to_string())
    }

    fn _new(toml: Toml) -> Self {
        Config { toml: toml }
    }

    pub fn default() -> Self {
        let mut editable = EditableToml(BTreeMap::new());
        editable.overwrite(ConfigKey::BurnAfter  , CONFIG_DEFAULT_VALUE_BURN_AFTER  .to_string());
        editable.overwrite(ConfigKey::SweepPeriod, CONFIG_DEFAULT_VALUE_SWEEP_PERIOD.to_string());
        editable.overwrite(ConfigKey::SweepTime  , CONFIG_DEFAULT_VALUE_SWEEP_TIME  .to_string());

        Self::_new(editable.to_toml())
    }

    pub fn read() -> Result<Self, CliError> {
        print_with_tag(Tag::Info, format!("Read \"{}\" file", CONFIG_FILE_NAME));

        let mut f = try!(File::open(Self::path()));

        let mut contents = String::new();
        try!(f.read_to_string(&mut contents));

        let result = contents
            .parse()
            .map_err(|e: Vec<_>| e.into_iter().next());
        let toml = match result {
            Ok(toml)    => toml,
            Err(option) => match option {
                Some(e) => return Err(From::from(e)),
                None    => return Err(From::from(CannotHappenError)),
            },
        };

        Ok(Self::_new(toml))
    }

    pub fn get<CK: Borrow<ConfigKey>>(&self, key: CK) -> Result<String, CliError> {
        let key = key.borrow();

        let result = self.toml
            .lookup(key.to_str())
            .ok_or(ConfigError::new(match *key {
                ConfigKey::BurnAfter   => ConfigErrorKind::NotFoundBurnAfter,
                ConfigKey::SweepPeriod => unimplemented!(),
                ConfigKey::SweepTime   => unimplemented!(),
            }));
        let value = try!(result);

        value
            .as_str()
            .ok_or(From::from(ConfigError::new(ConfigErrorKind::NonStringValue)))
            .and_then(|s| Self::validate(key, s))
    }

    pub fn to_duration(value: String) -> Result<Duration, CliError> {
        let mut value   = value.split(' ');
        let (num, unit) = match (value.next(), value.next()) {
            (Some(num), Some(unit)) => (num, unit),
            _                       => return Err(From::from(CannotHappenError)),
        };
        let num = try!(num.parse::<u32>()) as i64;

        let duration = match unit {
            "day"  | "days"  => Duration::days(num),
            "week" | "weeks" => Duration::weeks(num),
            _                => return Err(From::from(CannotHappenError)),
        };

        Ok(duration)
    }

    pub fn set<CK: Borrow<ConfigKey>>(mut self, key: CK, value: String) -> Result<Self, ConfigError> {
        let mut editable = try!(EditableToml::from(self.toml));

        editable.overwrite(key, value);

        self.toml = editable.to_toml();

        Ok(self)
    }

    pub fn validate<CK: Borrow<ConfigKey>, S: AsRef<str>>(key: CK, value: S) -> Result<String, CliError> {
        let value = value.as_ref().trim();

        match *key.borrow() {
            ConfigKey::BurnAfter => {
                let pair = try!(Regex::new(r"^(?P<num>\d+)\s?(?P<unit>days?|weeks?)$"))
                    .captures(value)
                    .map_or((None, None), |caps| (caps.name("num"), caps.name("unit")));
                let (num, unit) = match pair {
                    (Some(num), Some(unit)) => (num, unit),
                    _                       => return Err(From::from(ConfigError::new(ConfigErrorKind::BurnAfter))),
                };
                Ok(format!("{} {}", num, unit))
            },
            ConfigKey::SweepPeriod => {
                match value {
                    "daily" | "weekly" => Ok(value.to_string()),
                    _                  => Err(From::from(ConfigError::new(ConfigErrorKind::SweepPeriod))),
                }
            },
            ConfigKey::SweepTime => {
                match NaiveTime::from_str(format!("{}:00", value).as_ref()) {
                    Ok(_)  => Ok(value.to_string()),
                    // should set Err(e) to Error::cause()
                    Err(_) => Err(From::from(ConfigError::new(ConfigErrorKind::SweepTime))),
                }
            },
        }
    }
}

#[test]
fn config_key_to_pair_should_return_pair() {
    let keys = [
        (ConfigKey::BurnAfter  , CONFIG_KEY_BURN_AFTER  ),
        (ConfigKey::SweepPeriod, CONFIG_KEY_SWEEP_PERIOD),
        (ConfigKey::SweepTime  , CONFIG_KEY_SWEEP_TIME  ),
    ];
    for &(ref key, ref correct) in &keys {
        let (first, second) = key.to_pair();
        assert_eq!(correct.to_string(), format!("{}.{}", first, second));
    }
}

#[test]
fn editable_toml_overwrite_should_add_value() {
    let b_tree_map: EditableTomlCore = BTreeMap::new();
    let mut correct                  = b_tree_map.clone();
    let mut editable                 = EditableToml(b_tree_map);

    let v1 = "value1".to_string();

    let mut entry         = BTreeMap::new();
    let key1              = ConfigKey::BurnAfter;
    let (first1, second1) = key1.to_pair();
    entry.insert(second1.to_string(), v1.clone());
    correct.insert(first1.to_string(), entry);

    editable.overwrite(ConfigKey::BurnAfter, v1);
    let EditableToml(calculated) = editable.clone();

    assert_eq!(&correct, &calculated);

    let v2 = "value2".to_string();
    let v3 = "value3".to_string();

    let mut entry         = BTreeMap::new();
    let key2              = ConfigKey::SweepPeriod;
    let (first2, second2) = key2.to_pair();
    let key3              = ConfigKey::SweepTime;
    let (_, second3)      = key3.to_pair();
    entry.insert(second2.to_string(), v2.clone());
    entry.insert(second3.to_string(), v3.clone());
    correct.insert(first2.to_string(), entry);

    editable.overwrite(ConfigKey::SweepPeriod, v2);
    editable.overwrite(ConfigKey::SweepTime  , v3);
    let &EditableToml(ref calculated) = &editable;

    assert_eq!(&correct, calculated);
}

#[test]
fn default_should_return_config() {
    let correct: Result<Toml, Vec<toml::ParserError>> = format!(
        r#"
            [burn]
            after = "{}"
            [sweep]
            period = "{}"
            time   = "{}"
        "#,
        CONFIG_DEFAULT_VALUE_BURN_AFTER,
        CONFIG_DEFAULT_VALUE_SWEEP_PERIOD,
        CONFIG_DEFAULT_VALUE_SWEEP_TIME
    ).parse();

    assert_eq!(correct.unwrap(), Config::default().toml);
}

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

    #[test]
    fn get_should_return_ok() {
    }
    #[test]
    fn get_should_return_err() {
    }

    #[test]
    fn set_should_return_ok() {
    }
    #[test]
    fn set_should_retrun_err() {
    }

    #[test]
    fn to_duration_should_return_ok() {
    }
    #[test]
    fn to_duration_should_return_err() {
    }

    #[test]
    fn validate_should_return_ok() {
    }
    #[test]
    fn validate_should_return_err() {
    }
}
<|endoftext|>